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

187

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

Pattle
источник
1
Попробуйте что-то, если ($ ('html').
Width
@Vaibs_Cool Спасибо за предложение, но я все еще получаю тот же результат
Паттл
Ответьте мне здесь [введите описание ссылки здесь] [1] [1]: stackoverflow.com/questions/11309859/…
Рантьев
Работает ли «document.documentElement.clientWidth» (вместо «$ (window) .width ()») так, как вы хотите, чтобы он работал? Изменить: Моя ошибка, только что видел ответ Vaibs_Cool.
joshhunt

Ответы:

294

Если вам не нужно поддерживать 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 {
    //...
}
ausi
источник
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
Если вы используете <div id="xs-indicator" class="xs-visible">
начальную
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/…
Рохан Кумар
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' ] };
}
Rantiev
источник
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");
    ...
});
gramgram
источник
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");
user3041539
источник
3

использование

window.innerWidth

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

user4451021
источник
3

Вот альтернатива упомянутым ранее методам, которые полагаются на изменение чего-либо с помощью CSS и чтение этого с помощью Javascript. Этот метод не нужен window.matchMediaили модернизр. Это также не нуждается в дополнительном элементе 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.

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

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

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

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

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

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

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

fzzylogic
источник
1

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

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

См. Документацию Mozilla для более подробной информации.

user2128205
источник
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.

Добавить 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)');
}

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

Арсен Пюскюлян
источник
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 всегда возвращает false.

Санджиб Дебнатх
источник
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 ().

burkul
источник
-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,
      });
    }
Vitalii
источник
-2

Попробуй это

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

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

Vaibs_Cool
источник
Спасибо, это все еще имеет тот же результат
Паттл