$ (window) .width () não é o mesmo que consulta de mídia

186

Estou usando o Twitter Bootstrap em um projeto. Além dos estilos de inicialização padrão, também adicionei alguns dos meus

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

Também estou usando o jQuery para alterar a ordem de certos elementos na página quando a largura da janela de exibição é menor que 767px.

$(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"));
    }
}

O problema que estou tendo é que a largura calculada por $(window).width()e a largura calculada pelo CSS não parecem ser iguais. Quando $(window).width()retorna 767, o css calcula a largura da janela de visualização como 751, de modo que parece haver uma diferença de 16px.

Alguém sabe o que está causando isso e como eu poderia resolver o problema? As pessoas sugeriram que a largura da barra de rolagem não está sendo levada em consideração e o uso $(window).innerWidth() < 751é o caminho a percorrer. No entanto, idealmente, quero encontrar uma solução que calcule a largura da barra de rolagem e que seja consistente com minha consulta de mídia (por exemplo, onde ambas as condições estão verificando o valor 767). Porque certamente nem todos os navegadores terão uma largura de barra de rolagem de 16px?

Pattle
fonte
1
Tente algo se ($ ('html'). Width () <= 767) {// Faça alguma coisa} #
Vaibs_Cool 10/10
@Vaibs_Cool Obrigado pela sugestão, mas eu ainda obter o mesmo resultado
Pattle
Resposta aqui: [insira a descrição do link aqui] [1] [1]: stackoverflow.com/questions/11309859/…
Rantiev 19/02/02
"Document.documentElement.clientWidth" (em vez de "$ (window) .width ()") funciona como você deseja que ele funcione? Edit: Meu erro, só vi a resposta do Vaibs_Cool.
Joshhunt #

Respostas:

293

Se você não precisar dar suporte ao IE9, basta usar window.matchMedia()( documentação MDN ).

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

window.matchMediaé totalmente consistente com as consultas de mídia CSS e o suporte ao navegador é bastante bom: http://caniuse.com/#feat=matchmedia

ATUALIZAR:

Se você precisar dar suporte a mais navegadores, poderá usar o método mq do Modernizr , ele suporta todos os navegadores que entendem consultas de mídia em CSS.

if (Modernizr.mq('(max-width: 767px)')) {
    //...
} else {
    //...
}
ausi
fonte
8
Se você pode usar a biblioteca Modernizr, esta é a melhor resposta disponível.
richsinn
1
Esta solução é melhor: stackoverflow.com/a/19292035/1136132 (segundo código). Somente JS.
precisa saber é o seguinte
@joseantgv Minha solução também é apenas js. Você pode explicar por que a solução à qual você está vinculado é melhor?
Ausi
2
@edwardm Modernizr.mqretorna apenas um valor booleano, então você deve chamá-lo você mesmo em um onresizemanipulador de eventos.
Ausi
2
O @Bernig window.matchMediaé o caminho recomendado, porque não aciona um reflow , dependendo da frequência com que você chama a função, isso pode causar um problema de desempenho. Se você não quiser usar o Modernizr diretamente, poderá copiar o código fonte de src / mq.js e src / injectElementWithStyles.js .
ausi
175

Verifique uma regra CSS em que a consulta de mídia seja alterada. Isso é garantido para sempre funcionar.

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;
    }
}
NateS
fonte
9
Essa é uma solução mais elegante do que os hacks JS mencionados nas outras respostas.
René Roth
3
+1 isto é apenas inteligente. Eu gosto de como se você deseja alterar os pontos de interrupção, tudo o que você precisa fazer é alterar o css e não o javascript.
precisa saber é o seguinte
Esta solução funciona bem e acho que é mais elegante que o javascript proposto na resposta mais votada.
Andrés Meza-Escallón 16/04
2
Se você usa o bootstrap, pode fazê-lo sem css, como<div id="xs-indicator" class="xs-visible">
Čamo 23/11
33

Pode ser devido a scrollbar, use em innerWidthvez de widthcomo

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

Além disso, você pode obter o viewportgosto

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

Código acima Fonte

Rohan Kumar
fonte
Obrigado. Isso funcionará, mas de qualquer maneira eu posso usar o jquery para incluir a largura da barra de rolagem. Só estou pensando que a largura da barra de rolagem pode mudar em diferentes navegadores?
Pattle 10/10
1
Sim, use innerWidth()ou você pode usá-lo como $('body').innerWidth();Veja este stackoverflow.com/questions/8339377/…
Rohan Kumar
3
Quer dizer window.innerWidth, não no objeto jQuery $ (janela), $ (janela) .width () retorna incorretamente
EJanuszewski
1
window.innerWidthnão é consistente com as consultas de mídia CSS no Safari 8 se as barras de rolagem estiverem ativadas nas preferências do sistema OSX.
Ausi
10

sim, isso é devido à barra de rolagem. Fonte da resposta correta: insira a descrição do link aqui

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
fonte
4

Talvez seja uma prática melhor não escopo JS da largura do documento, mas algum tipo de alteração feita pela consulta css @media. Com esse método, você pode ter certeza de que a função JQuery e a alteração de css acontecem ao mesmo tempo.

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");
    ...
});
gramograma
fonte
3

Eu estava enfrentando o mesmo problema recentemente - também com o Bootstrap 3.

Nem $ .width () nem $ .innerWidth () funcionarão para você.

A melhor solução que encontrei - e é especificamente adaptada ao BS3 -
é verificar a largura de um .containerelemento.

Como você provavelmente sabe como o .containerelemento funciona,
é o único elemento que fornecerá a largura atual definida pelas regras BS css.

Então é algo como

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
fonte
3

Usar

window.innerWidth

Isso resolveu meu problema

user4451021
fonte
3

Aqui está uma alternativa aos métodos mencionados anteriormente, que dependem da alteração de algo via CSS e da leitura via Javascript. Este método não precisa window.matchMediaou Modernizr. Ele também não precisa de elemento HTML extra. Ele funciona usando um pseudoelemento HTML para 'armazenar' as informações do ponto de interrupção:

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";
  }
}

Eu usei bodycomo exemplo, você pode usar qualquer elemento HTML para isso. Você pode adicionar qualquer sequência ou número que desejar ao contentpseudoelemento. Não precisa ser 'móvel' e assim por diante.

Agora podemos ler essas informações do Javascript da seguinte maneira:

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

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

Dessa forma, sempre temos certeza de que as informações do ponto de interrupção estão corretas, pois são provenientes diretamente do CSS e não precisamos incomodar em obter a largura de tela correta via Javascript.

dschenk
fonte
Você não precisa usar querySelector()ou getPropertyValue(). Você também pode procurar aspas simples em regex (já que não é consistente). Este: window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, ''). E, para tornar isso um pouco mais barato, você pode colocá-lo em sublinhado / lodash ._debounce()com ~ 100ms de espera. Finalmente, anexar atributos a <html> torna a saída disponível para outras coisas, como cláusulas de desativação da dica de ferramenta à procura de sinalizadores / dados brutos fora dos vars. Exemplo: gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin
2

Javascript fornece mais de um método para verificar a largura da janela de exibição. Como você notou, innerWidth não inclui a largura da barra de ferramentas, e as larguras da barra de ferramentas diferem entre os sistemas. Há também a opção outerWidth , que incluirá a largura da barra de ferramentas. A API Javascript da Mozilla declara:

Window.outerWidth obtém a largura da parte externa da janela do navegador. Representa a largura de toda a janela do navegador, incluindo a barra lateral (se expandida), o cromo da janela e as bordas / alças de redimensionamento da janela.

O estado do javascript é tal que não se pode confiar em um significado específico para outerWidth em todos os navegadores em todas as plataformas.

outerWidthnão é bem suportado em navegadores móveis mais antigos , embora tenha suporte nos principais navegadores de desktop e nos navegadores de smartphones mais recentes.

Como ausi apontou, matchMediaseria uma ótima opção, pois o CSS é melhor padronizado (o matchMedia usa JS para ler os valores de viewport detectados pelo CSS). Mas mesmo com os padrões aceitos, ainda existem navegadores retardados que os ignoram (neste caso, IE <10, o que torna o matchMedia não muito útil pelo menos até a morte do XP).

Em resumo , se você estiver desenvolvendo apenas para navegadores de desktop e navegadores móveis mais recentes, a outerWidth deverá fornecer o que você está procurando, com algumas ressalvas .

fzzylogic
fonte
1

Aqui está um truque menos envolvido para lidar com consultas de mídia. O suporte a vários navegadores é um pouco limitante, pois não suporta o IE móvel.

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

Veja a documentação do Mozilla para mais detalhes.

user2128205
fonte
1

tente isso

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
      }
    )
}
DINESH Adhikari
fonte
0

Solução alternativa que sempre funciona e é sincronizada com consultas de mídia CSS.

Adicionar uma div ao corpo

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

Adicione estilo e altere-o inserindo uma consulta de mídia específica

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

Em seguida, no JS, verifique o estilo que você está alterando, inserindo na consulta de mídia

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

Portanto, geralmente você pode verificar qualquer estilo que está sendo alterado inserindo uma consulta de mídia específica.

Arsen Pyuskyulyan
fonte
0

A melhor solução para vários navegadores é usar o Modernizr.mq

link: https://modernizr.com/docs/#mq

Modernizr.mq permite verificar programaticamente se o estado atual da janela do navegador corresponde a uma consulta de mídia.

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

Nota O navegador não suporta consultas de mídia (por exemplo, IE antigo) mq sempre retornará false.

Sanjib Debnath
fonte
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);

        });

    }
Adam Colton
fonte
0

O que eu faço ;

<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>
...

e chame a variável aWidth em qualquer lugar posteriormente.

Você precisa colocar o getWidth () no corpo do documento para garantir que a largura da barra de rolagem seja contada; caso contrário, a largura da barra de rolagem do navegador subtraída de getWidth ().

Burkul
fonte
-1

Controle deslizante de implementação e exibir diferentes números de slides no bloco, dependendo da resolução (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
fonte
-2

Tente isto

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

Para mais referência clique aqui

Vaibs_Cool
fonte
Obrigado, isso ainda tem o mesmo resultado que
Pattle