$ (window) .width () не збігається з медіа-запитом


186

Я використовую Twitter Bootstrap для проекту. Крім стилів завантаження за замовчуванням, я також додав свої власні

//My styles
@media (max-width: 767px)
{
    //CSS here
}

Я також використовую jQuery, щоб змінити порядок певних елементів на сторінці, коли ширина вікна перегляду менше 767 пікселів.

$(document).load($(window).bind("resize", checkPosition));

function checkPosition()
{
    if($(window).width() < 767)
    {
        $("#body-container .main-content").remove().insertBefore($("#body-container .left-sidebar"));
    } else {
        $("#body-container .main-content").remove().insertAfter($("#body-container .left-sidebar"));
    }
}

Проблема, яка у мене виникає, полягає в тому, що ширина, обчислена $(window).width()і ширина, обчислена CSS, здається, не однакова. Коли $(window).width()повертається 767, css обчислює його ширину вікна перегляду як 751, тому здається, що 16px відрізняється.

Хтось знає, що викликає це, і як я міг вирішити проблему? Люди припустили, що ширина смуги прокрутки не береться до уваги, а використання $(window).innerWidth() < 751- це шлях. Однак в ідеалі я хочу знайти рішення, яке обчислює ширину смуги прокрутки, яке відповідає моєму медіа-запиту (наприклад, коли обидві умови перевіряють значення 767). Тому що напевно не всі браузери матимуть ширину смуги прокрутки 16 пікселів?


1
Спробуйте щось, якщо ($ ('html'). Width () <= 767) {// Зроби щось}
Vaibs_Cool

@Vaibs_Cool Дякую за пропозицію, але я все одно отримую той самий результат
Pattle


Відповідь , який я тут [введіть опис посилання тут] [1] [1]: stackoverflow.com/questions/11309859 / ...
Rantiev

Чи працює "document.documentElement.clientWidth" (замість "$ (window) .width ()"), як ви хочете, щоб він працював? Редагувати: моя помилка, щойно побачила відповідь Vaibs_Cool.
Джошунт

Відповіді:


293

Якщо вам не потрібно підтримувати IE9, ви можете просто скористатися window.matchMedia()( документація MDN ).

function checkPosition() {
    if (window.matchMedia('(max-width: 767px)').matches) {
        //...
    } else {
        //...
    }
}

window.matchMediaповністю відповідає медіа-запитам CSS, і підтримка браузера є досить хорошою: http://caniuse.com/#feat=matchmedia

ОНОВЛЕННЯ:

Якщо вам доведеться підтримувати більше браузерів, ви можете використовувати mq метод Modernizr , він підтримує всі браузери, які розуміють медіа-запити в CSS.

if (Modernizr.mq('(max-width: 767px)')) {
    //...
} else {
    //...
}

8
Якщо ви можете дозволити собі використовувати бібліотеку Modernizr, це найкраща відповідь там.
richsinn

1
Це рішення краще: stackoverflow.com/a/19292035/1136132 (2-й код). Тільки JS.
joseantgv

@joseantgv Моє рішення також є лише js. Чи можете ви пояснити, чому рішення, з яким ви пов’язали, краще?
ausi

2
@edwardm Modernizr.mqповертає лише булеве значення, тому вам доведеться викликати його самостійно в обробці onresizeподій.
ausi

2
@Bernig window.matchMedia- рекомендований спосіб, оскільки він не викликає поповнення , залежно від того, як часто ви викликаєте функцію, це може спричинити проблеми з продуктивністю. Якщо ви не хочете використовувати Modernizr безпосередньо, ви можете скопіювати вихідний код з src / mq.js та src / injectElementWithStyles.js .
ауси

175

Перевірте правило CSS, що медіа-запит змінюється. Це гарантовано завжди працює.

http://www.fourfront.us/blog/jquery-window-width-and-media-queries

HTML:

<body>
    ...
    <div id="mobile-indicator"></div>
</body>

Javascript:

function isMobileWidth() {
    return $('#mobile-indicator').is(':visible');
}

CSS:

#mobile-indicator {
    display: none;
}

@media (max-width: 767px) {
    #mobile-indicator {
        display: block;
    }
}

9
Це більш елегантне рішення, ніж хакі JS, згадані в інших відповідях.
Рене Рот

3
+1 це просто розумно. Мені подобається, як якщо ви хочете змінити точки перерви, все, що вам потрібно зробити, - це змінити css, а не javascript.
JoeMoe1984

Це рішення працює чудово, і я вважаю його більш елегантним, ніж хакер JavaScript, запропонований у найбільш проголосованій відповіді.
Андрес Меза-Ескаллон

2
Якщо ви використовуєте bootstrap, ви можете зробити це без css на зразок<div id="xs-indicator" class="xs-visible">
Čamo

33

Це може бути пов'язано з scrollbar, використовувати innerWidthзамість widthподібного

if($(window).innerWidth() <= 751) {
   $("#body-container .main-content").remove()
                                .insertBefore($("#body-container .left-sidebar"));
} else {
   $("#body-container .main-content").remove()
                                .insertAfter($("#body-container .left-sidebar"));
}

Також ви можете отримати viewportподібне

function viewport() {
    var e = window, a = 'inner';
    if (!('innerWidth' in window )) {
        a = 'client';
        e = document.documentElement || document.body;
    }
    return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}

Вище Джерело


Дякую. Це буде працювати, але чи все-таки я можу використовувати jquery для включення ширини смуги прокрутки. Я просто думаю, що ширина смуги прокрутки може змінюватися в різних браузерах?
Паттл

1
Так, використовуйте, innerWidth()або ви можете використовувати його як $('body').innerWidth();дивіться це stackoverflow.com/questions/8339377/…
Rohan Kumar

3
Ви маєте на увазі window.innerWidth, а не на об'єкт jQuery $ (window), $ (window) .width () повертає його неправильно
EJanuszewski

1
window.innerWidthне відповідає CSS-медіа-запитам у Safari 8, якщо смуги прокрутки включені в системних налаштуваннях OSX.
ausi

10

так, це пов’язано з прокруткою. Правильне джерело відповіді: сюди введіть опис посилання

function viewport() {
    var e = window, a = 'inner';
    if (!('innerWidth' in window )) {
        a = 'client';
        e = document.documentElement || document.body;
    }
    return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}

4

Це може бути кращою практикою не застосовувати JS-ширину документа, а якусь зміну, внесену запитом css @media. За допомогою цього методу ви можете бути впевнені, що функція JQuery і зміна css відбуваються одночасно.

css:

#isthin {
    display: inline-block;
    content: '';
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media only screen and (max-width: 990px) {
    #isthin {
        display: none;
    }
}

jquery:

$(window).ready(function(){
    isntMobile = $('#isthin').is(":visible");
    ...
});

$(window).resize(function(){
    isntMobile = $('#isthin').is(":visible");
    ...
});

3

Нещодавно я стикався з тією ж проблемою - також із Bootstrap 3.

Ні $ .width (), ні $ .innerWidth () не працюватимуть для вас.

Найкраще рішення, яке я придумав - і спеціально призначений для BS3 -
це перевірити ширину .containerелемента.

Як ви, напевно, знаєте, як .containerпрацює елемент,
це єдиний елемент, який дасть вам поточну ширину, встановлену правилами BS css.

Тож іде щось на кшталт

bsContainerWidth = $("body").find('.container').width()
if (bsContainerWidth <= 768)
    console.log("mobile");
else if (bsContainerWidth <= 950)
    console.log("small");
else if (bsContainerWidth <= 1170)
    console.log("medium");
else
    console.log("large");


3

Ось альтернатива вищезгаданим методам, які покладаються на те, щоб змінити щось через CSS та прочитати його через Javascript. Цей метод не потрібен window.matchMediaабо Modernizr. Також йому не потрібен додатковий HTML-елемент. Він працює, використовуючи псевдоелемент HTML для "зберігання" інформації точки перелому:

body:after {
  visibility: hidden;
  height: 0;
  font-size: 0;
}

@media (min-width: 20em) {
  body:after {
    content: "mobile";
  }
}

@media (min-width: 48em) {
  body:after {
    content: "tablet";
  }
}

@media (min-width: 64em) {
  body:after {
    content: "desktop";
  }
}

Я використовував bodyяк приклад, ви можете використовувати для цього будь-який HTML-елемент. Ви можете додати будь-який рядок або число, яке ви хочете, в contentпсевдоелемент. Не обов’язково бути "мобільним" тощо.

Тепер ми можемо читати цю інформацію з Javascript таким чином:

var breakpoint = window.getComputedStyle(document.querySelector('body'), ':after').getPropertyValue('content').replace(/"/g,'');

if (breakpoint === 'mobile') {
    doSomething();
}

Таким чином, ми завжди впевнені, що інформація про точку перерви є правильною, оскільки вона надходить безпосередньо з CSS, і нам не доведеться турбуватися з отриманням потрібної ширини екрана через Javascript.


Вам не потрібно використовувати querySelector()або getPropertyValue(). Ви також можете шукати одну цитату в регулярному виразі (оскільки це не відповідає). Це: window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, ''). І, щоб зробити це трохи дешевше, ви можете загорнути його в підкреслення / подачу ._debounce()з ~ 100мс очікування. Нарешті, додавання атрибутів до <html> робить вихід доступним для інших речей, таких як підказки для відключення пропозицій, які шукають нераціональні прапори / дані за межами vars. Приклад: gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin

2

Javascript надає більше одного способу перевірки ширини вікна перегляду. Як ви помітили, внутрішня ширина не включає ширину панелі інструментів, а ширина панелі інструментів буде відрізнятися в різних системах. Також є опція externalWidth , яка буде включати ширину панелі інструментів. В API Mozilla Javascript говорить:

Window.outerWidth отримує ширину зовнішньої сторони вікна браузера. Він представляє ширину всього вікна веб-переглядача, включаючи бічну панель (якщо вона розширена), хром вікна та розмір рамки / ручки для зміни розміру вікна.

Стан javascript такий, що не можна покладатися на певне значення для externalWidth у кожному браузері на кожній платформі.

outerWidthце НЕ дуже добре підтримуються на більш старих мобільних браузерах , хоча він користується підтримкою в центральних настільних браузерах і більшість новіших розумних телефонів браузерів.

Як зазначав ausi, matchMediaце буде чудовим вибором, оскільки CSS краще стандартизується (matchMedia використовує JS для зчитування значень вікна перегляду, виявлених CSS). Але навіть із прийнятими стандартами, все ще існують відсталі браузери, які їх ігнорують (IE <10 в цьому випадку, що робить matchMedia не дуже корисним принаймні, поки XP не вмирає).

В цілому , якщо ви розробляєте тільки для настільних браузерів і нових мобільних браузерів, outerWidth повинні дати вам те , що ви шукаєте, з деякими застереженнями .


1

Ось менш прихильний трюк для вирішення медіа-запитів. Підтримка перехресного браузера трохи обмежує, оскільки не підтримує мобільний IE.

     if (window.matchMedia('(max-width: 694px)').matches)
    {
        //do desired changes
    }

Докладнішу інформацію див. У документації Mozilla .


1

спробуйте це

getData(){
    if(window.innerWidth <= 768) {
      alert('mobile view')
      return;
    }

   //else function will work

    let body= {
      "key" : 'keyValue'
    }
    this.dataService.getData(body).subscribe(
      (data: any) => {
        this.myData = data
      }
    )
}

0

Обхід, який завжди працює і синхронізується із запитами медіа CSS.

Додайте дів до тіла

<body>
    ...
    <div class='check-media'></div>
    ...
</body>

Додайте стиль та змініть їх, ввівши конкретний медіа-запит

.check-media{
    display:none;
    width:0;
}
@media screen and (max-width: 768px) {
    .check-media{
         width:768px;
    }
    ...
}

Потім у стилі перевірки JS, який ви змінюєте, ввівши в медіа-запит

if($('.check-media').width() == 768){
    console.log('You are in (max-width: 768px)');
}else{
    console.log('You are out of (max-width: 768px)');
}

Тому, як правило, ви можете перевірити будь-який стиль, який змінюється, ввівши конкретний медіа-запит.


0

Найкраще рішення крос-браузера - використовувати Modernizr.mq

посилання: https://modernizr.com/docs/#mq

Modernizr.mq дозволяє програмно перевірити, чи відповідає поточний стан вікна браузера медіа-запиту.

var query = Modernizr.mq('(min-width: 900px)');
if (query) {
   // the browser window is larger than 900px
}

Примітка : браузер не підтримує медіа-запити (наприклад, старий IE) mq завжди поверне помилковий.


0
if(window.matchMedia('(max-width: 768px)').matches)
    {
        $(".article-item").text(function(i, text) {

            if (text.length >= 150) {
                text = text.substring(0, 250);
                var lastIndex = text.lastIndexOf(" ");     
                text = text.substring(0, lastIndex) + '...'; 
            }

            $(this).text(text);

        });

    }

0

Що я роблю ;

<body>
<script>
function getWidth(){
return Math.max(document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth);
}
var aWidth=getWidth();
</script>
...

і викликати змінну aWidth в будь-якому місці після цього.

Потрібно поставити getWidth () в тіло документа, щоб переконатися, що ширина смуги прокрутки рахується, інакше ширина смуги прокрутки браузера віднімається від getWidth ().


-1

Реалізація слайдера слайда та відображення різної кількості слайдів у блоці залежно від роздільної здатності (jQuery)

   if(window.matchMedia('(max-width: 768px)').matches) {
      $('.view-id-hot_products .view-content').slick({
        infinite: true,
        slidesToShow: 3,
        slidesToScroll: 3,
        dots: true,
      });
    }

    if(window.matchMedia('(max-width: 1024px)').matches) {
      $('.view-id-hot_products .view-content').slick({
        infinite: true,
        slidesToShow: 4,
        slidesToScroll: 4,
        dots: true,
      });
    }

-2

Спробуйте це

if (document.documentElement.clientWidth < 767) {
   // scripts
}

Для отримання додаткової довідки натисніть тут


Дякую, це все-таки має той самий результат
Pattle
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.