$(window).width() не совпадает с медиа-запросом

Я использую 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

Если вам не нужно поддерживать IE9, вы можете просто использовать window.matchMedia() (документацию MDN).

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

window.matchMedia полностью согласуется с запросами на мультимедиа CSS, и поддержка браузера неплоха: http://caniuse.com/#feat=matchmedia

UPDATE:

Если вам нужно поддерживать большее количество браузеров, вы можете использовать метод mpnovizr mq, он поддерживает все браузеры, которые понимают медиа-запросы в CSS.

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

Ответ 2

Проверьте правило 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;
    }
}

Ответ 3

Возможно, из-за 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' ] };
}

Над кодом Источник

Ответ 4

да, это из-за полосы прокрутки. Правильный источник ответа: введите ссылку здесь

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' ] };
}

Ответ 5

Возможно, лучше не использовать 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");
    ...
});

Ответ 6

Используйте

window.innerWidth

Это решило мою проблему

Ответ 7

В последнее время я столкнулся с той же проблемой - также с 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");

Ответ 8

Вот альтернатива описанным выше методам, которые полагаются на изменение чего-либо с помощью 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.

Ответ 9

Javascript предоставляет несколько методов проверки ширины окна просмотра. Как вы заметили, innerWidth не включает ширину панели инструментов, а ширина панели инструментов будет различаться по всем системам. Существует также опция outerWidth, которая будет включать ширину панели инструментов. API Javascript Mozilla:

Window.outerWidth получает ширину внешней части окна браузера. Он представляет собой ширину всего окна браузера, включая боковую панель (если расширен), окно хром и окно изменения размеров границ/ручек.

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

outerWidth не поддерживается в старых мобильных браузерах, хотя он пользуется поддержкой в ​​основных настольных браузерах и самые новые браузеры смартфонов.

Как отметил ausi, matchMedia будет отличным выбором, поскольку CSS лучше стандартизован (matchMedia использует JS для чтения значений в режиме просмотра, обнаруженных CSS). Но даже с принятыми стандартами все еще существуют запаздывающие браузеры, которые игнорируют их (IE < 10 в этом случае, что делает matchMedia не очень полезным, по крайней мере, до тех пор, пока не умрет XP).

В резюме, если вы только разрабатываете браузеры для настольных компьютеров и новые мобильные браузеры, внешняя ширина должна предоставить вам то, что вы ищете, некоторые оговорки.

Ответ 10

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

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

Подробнее см. документацию Mozilla.

Ответ 11

Обходной путь, который всегда работает и синхронизируется с запросами мультимедиа CSS.

Добавить div в тело

<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)');
}

Как правило, вы можете проверить любой стиль, который изменяется, введя конкретный мультимедийный запрос.

Ответ 12

Лучшее кросс-браузерное решение - использовать 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 всегда возвращает false.

Ответ 13

Внедрение slick slider и отображение различных номеров слайдов в блоке в зависимости от разрешения (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,
      });
    }

Ответ 14

Попробуйте это

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

Для получения дополнительной справки нажмите здесь