$ (window) .width () différent de la requête multimédia


187

J'utilise Twitter Bootstrap sur un projet. En plus des styles d'amorçage par défaut, j'ai également ajouté certains de mes propres styles

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

J'utilise également jQuery pour modifier l'ordre de certains éléments sur la page lorsque la largeur de la fenêtre d'affichage est inférieure à 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"));
    }
}

Le problème que j'ai est que la largeur calculée par $(window).width()et la largeur calculée par le CSS ne semblent pas être les mêmes. Lorsque $(window).width()renvoie 767, le CSS calcule la largeur de la fenêtre comme 751, il semble donc y avoir un 16px différent.

Quelqu'un sait-il ce qui cause cela et comment je pourrais résoudre le problème? Les gens ont suggéré que la largeur de la barre de défilement n'est pas prise en compte et que l'utilisation $(window).innerWidth() < 751est la voie à suivre. Cependant, idéalement, je veux trouver une solution qui calcule la largeur de la barre de défilement et qui soit cohérente avec ma requête multimédia (par exemple, où les deux conditions sont vérifiées par rapport à la valeur 767). Parce que tous les navigateurs n'auront sûrement pas une largeur de barre de défilement de 16px?


1
Essayez quelque chose si ($ ('html'). Width () <= 767) {// Faites quelque chose}
Vaibs_Cool

@Vaibs_Cool Merci pour la suggestion mais j'obtiens toujours le même résultat
Pattle


Répondez ici [entrez la description du lien ici] [1] [1]: stackoverflow.com/questions/11309859/…
Rantiev

"Document.documentElement.clientWidth" (au lieu de "$ (window) .width ()") fonctionne-t-il comme vous le souhaitez? Edit: Mon erreur, je viens de voir la réponse de Vaibs_Cool.
joshhunt

Réponses:


294

Si vous n'avez pas à prendre en charge IE9, vous pouvez simplement utiliser window.matchMedia()( documentation MDN ).

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

window.matchMediaest parfaitement compatible avec les requêtes multimédias CSS et la prise en charge du navigateur est assez bonne: http://caniuse.com/#feat=matchmedia

METTRE À JOUR:

Si vous devez prendre en charge plus de navigateurs, vous pouvez utiliser la méthode mq de Modernizr , elle prend en charge tous les navigateurs qui comprennent les requêtes multimédias en CSS.

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

8
Si vous pouvez vous permettre d'utiliser la bibliothèque Modernizr, c'est la meilleure réponse.
richsinn

1
Cette solution est meilleure: stackoverflow.com/a/19292035/1136132 (2ème code). Seulement JS.
joseantgv

@joseantgv Ma solution est également js uniquement. Pouvez-vous expliquer pourquoi la solution à laquelle vous vous êtes associé est meilleure?
ausi

2
@edwardm Modernizr.mqne renvoie qu'une valeur booléenne, vous devez donc l'appeler vous-même dans un onresizegestionnaire d'événements.
ausi

2
@Bernig window.matchMediaest la méthode recommandée, car elle ne déclenche pas redistribution , en fonction de la fréquence à laquelle vous appelez la fonction, cela peut entraîner un problème de performances. Si vous ne souhaitez pas utiliser Modernizr directement, vous pouvez copier le code source depuis src / mq.js et src / injectElementWithStyles.js .
ausi

175

Vérifiez une règle CSS que la requête multimédia change. Ceci est garanti pour toujours fonctionner.

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
C'est une solution plus élégante que les hacks JS mentionnés dans les autres réponses.
René Roth

3
+1 c'est juste intelligent. J'aime le fait que si vous voulez changer les points d'arrêt, tout ce que vous avez à faire est de changer le css et non le javascript.
JoeMoe1984

Cette solution fonctionne bien et je la trouve plus élégante que le hack javascript proposé dans la réponse la plus votée.
Andrés Meza-Escallón

2
Si vous utilisez bootstrap, vous pouvez le faire sans css comme<div id="xs-indicator" class="xs-visible">
Čamo

33

Cela peut être dû à scrollbar, utilisez innerWidthplutôt que widthcomme

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

Vous pouvez également obtenir le viewportsemblable

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

Source du code ci-dessus


Merci. Cela fonctionnera, mais est-ce que je peux utiliser jquery pour inclure la largeur de la barre de défilement. Je pense juste que la largeur de la barre de défilement pourrait changer sur différents navigateurs?
Pattle

1
Oui utilisez innerWidth()ou vous pouvez l'utiliser comme $('body').innerWidth();Voir ce stackoverflow.com/questions/8339377/…
Rohan Kumar

3
Vous voulez dire window.innerWidth, pas sur l'objet jQuery $ (window), $ (window) .width () le renvoie incorrectement
EJanuszewski

1
window.innerWidthn'est pas compatible avec les requêtes multimédias CSS dans Safari 8 si les barres de défilement sont activées dans les préférences système OSX.
ausi

10

oui, c'est dû à la barre de défilement. Bonne réponse: entrez la description du lien ici

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

Il est peut-être préférable de ne pas définir avec JS la largeur du document, mais une sorte de changement effectué par la requête css @media. Avec cette méthode, vous pouvez être sûr que la fonction JQuery et le changement css se produisent en même temps.

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

J'étais confronté au même problème récemment - également avec Bootstrap 3.

Ni $ .width () ni $ .innerWidth () ne fonctionneront pour vous.

La meilleure solution que j'ai trouvée - et est spécifiquement adaptée à BS3 -
est de vérifier la largeur d'un .containerélément.

Comme vous savez probablement comment fonctionne l' .containerélément,
c'est le seul élément qui vous donnera la largeur actuelle définie par les règles BS css.

Donc ça va quelque chose comme

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

Voici une alternative aux méthodes mentionnées précédemment qui reposent sur la modification de quelque chose via CSS et la lecture via Javascript. Cette méthode n'a pas besoin window.matchMediaou Modernizr. Il n'a également besoin d'aucun élément HTML supplémentaire. Cela fonctionne en utilisant un pseudo-élément HTML pour `` stocker '' les informations de point d'arrêt:

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

J'ai utilisé bodycomme exemple, vous pouvez utiliser n'importe quel élément HTML pour cela. Vous pouvez ajouter n'importe quelle chaîne ou nombre de votre choix dans contentle pseudo-élément. N'a pas besoin d'être «mobile» et ainsi de suite.

Nous pouvons maintenant lire ces informations à partir de Javascript de la manière suivante:

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

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

De cette façon, nous sommes toujours sûrs que les informations sur les points d'arrêt sont correctes, car elles proviennent directement de CSS et nous n'avons pas à nous soucier d'obtenir la bonne largeur d'écran via Javascript.


Vous n'avez pas besoin d'utiliser querySelector()ou getPropertyValue(). Vous pouvez également rechercher des guillemets simples dans l'expression régulière (car ce n'est pas cohérent). Ceci: window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, ''). Et, pour rendre cela un peu moins cher, vous pouvez l'envelopper dans un trait de soulignement / lodash ._debounce()avec ~ 100 ms d'attente. Enfin, l'ajout d'attribs à <html> rend la sortie disponible pour d'autres éléments tels que les clauses de désactivation de l'info-bulle recherchant des indicateurs / données bruts en dehors des vars. Exemple: gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin le

2

Javascript fournit plus d'une méthode pour vérifier la largeur de la fenêtre. Comme vous l'avez remarqué, innerWidth n'inclut pas la largeur de la barre d'outils et les largeurs de la barre d'outils diffèrent selon les systèmes. Il existe également l' option externalWidth , qui inclura la largeur de la barre d'outils. L' API Mozilla Javascript déclare:

Window.outerWidth obtient la largeur de l'extérieur de la fenêtre du navigateur. Il représente la largeur de toute la fenêtre du navigateur, y compris la barre latérale (si développée), le chrome de la fenêtre et les bordures / poignées de redimensionnement de la fenêtre.

L'état de javascript est tel que l'on ne peut pas se fier à une signification spécifique pour externalWidth dans chaque navigateur sur chaque plate-forme.

outerWidthn'est pas bien pris en charge sur les anciens navigateurs mobiles , bien qu'il bénéficie d'une prise en charge sur les principaux navigateurs de bureau et la plupart des navigateurs de téléphones intelligents les plus récents.

Comme l'ausi l'a souligné, ce matchMediaserait un excellent choix car CSS est mieux standardisé (matchMedia utilise JS pour lire les valeurs de la fenêtre détectées par CSS). Mais même avec les normes acceptées, il existe encore des navigateurs retardés qui les ignorent (IE <10 dans ce cas, ce qui rend matchMedia peu utile au moins jusqu'à la mort de XP).

En résumé , si vous développez uniquement pour des navigateurs de bureau et des navigateurs mobiles plus récents, externalWidth devrait vous donner ce que vous recherchez, avec quelques mises en garde .


1

Voici une astuce moins complexe pour traiter les requêtes des médias. La prise en charge de plusieurs navigateurs est un peu limitative car elle ne prend pas en charge IE mobile.

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

Consultez la documentation de Mozilla pour plus de détails.


1

essaye ça

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

Solution de contournement qui fonctionne toujours et est synchronisée avec les requêtes multimédias CSS.

Ajouter un div au corps

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

Ajoutez du style et modifiez-les en entrant dans une requête multimédia spécifique

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

Ensuite, dans JS, vérifiez le style que vous modifiez en entrant dans la requête multimédia

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

Donc, généralement, vous pouvez vérifier n'importe quel style qui est modifié en entrant dans une requête multimédia spécifique.


0

La meilleure solution multi-navigateurs consiste à utiliser Modernizr.mq

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

Modernizr.mq vous permet de vérifier par programme si l'état actuel de la fenêtre du navigateur correspond à une requête multimédia.

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

Remarque Le navigateur ne prend pas en charge les requêtes multimédias (par exemple, l'ancien IE) mq retournera toujours 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

Ce que je fais ;

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

et appelez une variable Width n'importe où par la suite.

Vous devez mettre getWidth () dans le corps de votre document pour vous assurer que la largeur de la barre de défilement est comptée, sinon la largeur de la barre de défilement du navigateur soustraite de getWidth ().


-1

Slick de mise en œuvre et affichage de différents nombres de diapositives dans le bloc en fonction de la résolution (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

Essaye ça

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

Pour plus de références, cliquez ici


Merci, cela a toujours le même résultat
Pattle
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.