web-dev-qa-db-fra.com

Les requêtes multimédia CSS et la largeur de la fenêtre JavaScript ne correspondent pas

Pour un modèle réactif, j'ai une requête média dans mon CSS:

@media screen and (max-width: 960px) {
 body{
 /*  something */
 background:red;
 }
}

Et, j'ai fait une fonction jQuery sur redimensionner à la largeur du journal:

$(window).resize(function() {
 console.log($(window).width());
 console.log($(document).width()); /* same result */
 /* something for my js navigation */
}

Et il y a une différence avec la détection CSS et le résultat JS, j'ai cette méta:

<meta content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" name="viewport"/> 

Je suppose que c'est dû à la barre de défilement (15 px). Comment puis-je faire mieux?

50
benoît

Vous avez raison sur la barre de défilement, c'est parce que le CSS utilise la largeur du périphérique, mais le JS utilise la largeur du document.

Ce que vous devez faire est de mesurer la largeur de la fenêtre d'affichage dans votre code JS au lieu d'utiliser la fonction de largeur jQuery.

Ce code provient de http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/

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

J'ai trouvé le code suivant sur http://www.w3schools.com/js/js_window.asp :

var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

Pratiquement, cela fonctionne de la même manière que la réponse dans la réponse de @Michael Bird, mais c'est plus facile à lire.

Edit: Je cherchais une méthode pour donner exactement la même largeur que celle utilisée pour les requêtes de médias CSS. Mais celui suggéré ne fonctionne pas parfaitement sur Safari avec des barres de défilement, désolé. J'ai fini par utiliser modernizr.js dans une fonction centrale et dans le reste du code, je vérifie simplement si le type d'affichage est mobile, tablette ou ordinateur de bureau. Comme je ne suis pas intéressé par la largeur, cela fonctionne bien pour moi:

getDisplayType = function () {
  if (Modernizr.mq('(min-width: 768px)')){
    return 'desktop';
  }
  else if (Modernizr.mq('(min-width: 480px)')){
    return 'tablet'
  }
  return 'mobile';
};
7
LarS

window.innerWidth est ce dont vous avez besoin.

if (window.innerWidth <768) fonctionne pour le point d'arrêt 768 en CSS

4
Ross

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

Ajouter un div au corps

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

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

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

Ensuite, dans le style de vérification JS 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, en général, vous pouvez vérifier tout style en cours de modification en entrant dans une requête multimédia spécifique.

1

Bonjour, j'utilise cette petite astuce pour faire fonctionner facilement JS et CSS sur des pages réactives:

Testez la visibilité d'un élément affiché ou non sur une condition de taille CSS @media. En utilisant bootstrap CSS, je teste la visibilité d'un élément de classe hidden-xs

var msg = "a message for U";

/* At window load check initial size  */
if ( $('#test-xsmall').is(':hidden')  ) {
  /* This is a CSS Xsmall situation ! */
  msg = "@media CSS < 768px. JS width = " + $(window).width() + " red ! ";
  $('.redthing-on-xsmall').addClass('redthing').html(msg);

} else {
  /* > 768px according to CSS  */
  msg = "@media CSS > 767px. JS width = " + $(window).width() + " not red ! ";
  $('.redthing-on-xsmall').removeClass('redthing').html(msg);
}


/* And again when window resize  */

$(window).on('resize', function() {
  if ($('#test-xsmall').is(':hidden')) {
    msg = "@media CSS < 768px. JS width = " + $(window).width() + " red ! ";
    $('.redthing-on-xsmall').addClass('redthing').html(msg);
  } else {
    msg = "@media CSS > 767px. JS width = " + $(window).width() + " not red ! ";
    $('.redthing-on-xsmall').removeClass('redthing').html(msg);
  }
});
@media (min-width: 768px) {
  .hidden-xs {
    display: block !important;
  }
}
@media (max-width: 767px) {
  .hidden-xs {
    display: none !important;
  }
}
.redthing-on-xsmall {
  /* need a scrollbar to show window width diff between JS and css */
  min-height: 1500px;
}
.redthing {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- the CSS managed Element that is tested by JS --> 
<!-- class hidden-xs hides on xsmall screens (bootstrap) -->

<span id="test-xsmall" class="hidden-xs">THIS ELEMENT IS MANAGED BY CSS  HIDDEN on @media lower than 767px</span>


<!-- the responsive element managed by Jquery  -->
<div class="redthing-on-xsmall">THIS ELEMENT IS MANAGED BY JQUERY RED on @media max width 767px </div>
1
fr-info

D'après mon expérience, la largeur de la requête multimédia suit document.body.clientWidth. En raison d'une barre de défilement verticale qui va et vient, la vérification de la largeur du document, de la fenêtre ou de la fenêtre viewport () pourrait entraîner l'exécution tardive de mon Javascript - après le changement de la règle de requête multimédia, en fonction de la hauteur de la fenêtre.

La vérification de document.body.clientWidth a permis à mon code de script de s'exécuter de manière cohérente en même temps que la règle de requête multimédia prenait effet.

@media (min-width: 873px) {
//certaines règles
}
...

if (document.body.clientWidth> = 873) {
// du code
}

Le code d'Andy Langton m'a mis là-dessus - merci!

1
Jim