Pourquoi la fenêtre.largeur inférieure à celle définie dans les requêtes médias

je suis assez perplexe et savent toujours pas comment l'expliquer en mots appropriés. Jusqu'à présent, j'ai utilisé ma requêtes de média avec point d'arrêt. Une variable Breakpoint utilisée ressemble par exemple à:

$menustatictofixed: min-width 900px;

$point d'arrêt à l'ems est définie sur true. J'ai présenté la page avec toutes ses variables de point de rupture basées sur les valeurs des pixels de l'extrait suivant de jQuery:

$('body').append('<div style="position: fixed; bottom: 0; right: 0; display: inline-block; font-weight: bold; padding: 5px 7px; border-radius: 5px 0 0 0; background: green; color: white; z-index: 9999;">Viewport width <span id="width"></span> px</div>');
var viewportWidth = $(window).width()
$('#width').text(viewportWidth);
$(window).resize(function() {
  var viewportWidth = $(window).width();
    $('#width').text(viewportWidth);
});

tout avait l'air propre et propre. Mais au cours de la dernière ou des deux jours j'ai eu des problèmes à mettre en place les derniers points de rupture pour un modèle et d'obtenir les choses se comportent prévisible. D'une certaine façon, les choses qui semblaient s'additionner proprement et bien en premier lieu, ce dont je doute fort logiquement maintenant, sont en fait impropres et en quelque sorte un gâchis. Parce que si vous jetez un coup d'oeil à la screenshot ci-dessous, la largeur de la fenêtre (en Chrome) diffère en quelque sorte de la largeur de la fenêtre jQuery snippet utilisant.largeur. Il n'y a pas de différence si je remplace fenêtre.la largeur de la fenêtre.innerWidth pour éliminer éventuellement scrollbars. La seule façon de recevoir des résultats corrects est d'ajouter 15 pixels à l'équation:

var viewportWidth = $(window).width() + 15;

est la seule question dans toute l'équation cette fenêtre.la largeur est le mauvais choix de la fonction, et il serait préférable d'aller avec par exemple un document.documentElement.clientWidth ou autre chose ... ? Et pour ce que les 15 pixels représentent qui a corrigé le problème ci-dessus d'une manière un peu hacky? Meilleures salutations Ralf

23
demandé sur rpk 2013-08-31 12:16:36

7 réponses

la réponse est scrollbars, et la solution est délicate.

les requêtes des médias sont intéressantes. Ils ne se comportent pas exactement de la même façon à travers le navigateur, ce qui signifie que leur utilisation peut parfois ne pas être si facile. In-webkit / - blink sur OS X et IE10 sur Win8 par exemple, les barres de défilement sont superposées sur la page. In-moz, cependant, les barres de défilement sont et non superposées sur la page. La meilleure façon d'obtenir la "zone visible de la page est le suivant JavaScript vanille (en supposant que vous avez un document HTML valide):

document.body.parentNode.clientWidth

ce que cela va faire est de trouver l'élément body , trouver son parent (qui dans un document valide sera l'élément html ), puis trouver sa largeur après le rendu. Cela vous donnera la largeur que vous êtes intéressé à voir. c'est aussi une largeur inutile d'avoir .

pourquoi, vous demandez-vous, est-ce que la largeur réelle du client est inutile? C'est pas parce qu'elle varie d'un navigateur à l'autre, parce qu'il n'. C'est parce que ce n'est pas ce que testent les requêtes des médias width ! Ce que width "media queries test est window.innerWidth , qui est ce que vous utilisez essentiellement maintenant.

alors quelle est la solution à ce problème? Eh bien, je dirais que la solution est d'utiliser des requêtes médias basées sur le contenu au lieu de requêtes médias basées sur le périphérique et être OK avec un peu de marge de manœuvre dans vos requêtes (surtout si la marge de manœuvre est d'environ. 15px ). Si vous ne l'avez pas déjà fait, lisez les articles vexing Viewports et A Pixel Identity Crisis pour vous faire une idée de pourquoi un potentiel 15px shimmer dans vos définitions MQ n'est pas la pire chose au monde (il y a probablement de plus gros poissons à frire).

donc, en conclusion continuez à utiliser $breakpoint-to-ems: true et choisissez vos requêtes médias en fonction de quand le contenu casse à window.innerWidth car c'est la seule façon saine de gérer les problèmes de navigation croisée. D'un coup d'oeil rapide de diverses questions, il semble que si la plupart des navigateurs et des os se déplacent à une barre de défilement superposée (à partir de Firefox 24 chaque navigateur OS X aura un, Ubuntu Unity UI les a présenté ), donc dans un effort pour être l'avenir convivial, je suggérerais de ne pas se soucier de la barre de défilement offset et être OK avec des sites regardant légèrement différent à travers le navigateur. Rappeler, comme L'a si bien dit Ethan Marcotte:

Le Web est une Intrinsèquement Instable Moyen

24
répondu Snugug 2013-08-31 12:40:52

C'est ce qui a fonctionné pour moi: les requêtes de média CSS et JavaScript largeur de la fenêtre ne correspond pas à .

au lieu d'utiliser $(window).width(); qui inclut les barres de défilement obtenir la largeur intérieure comme ceci:

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

var vpWidth = viewport().width; // This should match your media query
45
répondu Justin 2017-05-23 12:18:25

c'est à cause du scrollbar's

la solution la plus correcte que j'ai trouvée est d'utiliser les requêtes Médias pour passer la taille réelle de la fenêtre À Javascript. Vous devez suivre ces étapes:

  • Ajouter un élément caché à votre page,
  • utiliser des requêtes Médias pour modifier la max-width propriété de cet élément,
  • Lire max-width propriété de l'élément à l'aide de Javascript.

par exemple, ajoutez l'élément suivant à votre page:

<div id="currentMedia"></div>

puis écrivez les règles CSS suivantes:

#currentMedia {
    display: none;
}

@media (max-width: 720px) {
    // Make arrows in the carousel disappear...

    #currentMedia {
        max-width: 720px;
    }
}

alors, du côté Javascript, vous pouvez écrire:

if (parseInt(jQuery("#currentMedia").css("max-width"), 10) <= 720) {
    // Code HERE..
}

et il sera précis quelle que soit la taille de la barre de défilement, puisque la valeur provient de la même requête multimédia qui déclenche la disparition du Carrousel.

j'ai testé cette solution sur tous les principaux navigateurs récents, et il donne des résultats corrects.

vous trouverez le grand résumé de ce que les propriétés sont prises en charge sur ce que les navigateurs sur cette page sur quirksmode.org .

votre meilleur pari est probablement de saisir un élément dans la page (en utilisant le document.organisme, s'il est appuyé, ou document.getElementById ou n'importe quoi d'autre), parcourir sa chaîne offsetParent pour trouver l'élément le plus élevé, puis examiner cet élément de clientWidth et clientHeight.

innerWidth documentation

la méthode .innerWidth() ne s'applique pas aux objets window et document ; pour ces objets, utilisez plutôt .width() .

5
répondu Tushar Gupta 2013-08-31 08:35:58

similaire à la réponse de @Snugugugugs mais qui a fonctionné mieux pour mon cas d'utilisation:

CSS (notez que j'utilise moins de so @tabletMin et @desktopMin traduire pour les variables de point de rupture que j'ai mis ailleurs:

    #cssWidth {
        display:none;
        content:'mobile';
    }

    /* Responsive styles (Tablet) */
    @media (min-width: @tabletMin) {
        #cssWidth {
            content:'tablet';
        }
        /* Other tablet CSS... */
    }
    /* Responsive styles (Desktop) */
    @media (min-width: @desktopMin) {
        #cssWidth {
            content:'desktop';
        }
        /* Other Desktop CSS... */
    }

puis en JS:

    getView = function() {
        // If #cssWidth element does not exist, create it and prepend it do body
        if ($('#cssWidth').length === 0) {
            $('body').prepend($(document.createElement('div')).attr('id', 'cssWidth'));
        }
        // Return the value of the elements 'content' property
        return $('#cssWidth').css('content');
    };

la fonction getView() retournera alors la chaîne de caractères 'mobile', 'tablet' ou 'desktop' dépendant de la largeur du media queries see.

cela pourrait être étendu pour s'adapter à plus de largeurs de viewport, il suffit d'ajouter plus de règles dans le CSS avec d'autres valeurs.

1
répondu Gruffy 2015-03-05 09:47:27

la réponse de @Snugug donne une très bonne explication quant à la raison pour laquelle cela se produit, et @TusharGupta a une bonne solution aussi bien que des références à la largeur détectée par mediaquery en javascript. La solution ci-dessous va dans l'autre sens en utilisant la largeur détectée par javascript pour déclencher des changements de mise en page.

dans le cas où vous avez besoin de synchroniser les médiaqueries avec votre Détection de largeur de pixel javascript, une façon d'aborder le problème est de déclencher la mise en page css modifications basées sur les classes que vous ajoutez avec javascript.

donc, au lieu d'écrire des médiaqueries, écrivez ces déclarations emboîtées dans une classe, dites:

html.myMobileBP { ... }

et dans votre javascript/jQuery, Ajoutez cette classe comme:

if ($(window).width() < myMobileBPPixelSize) {
    $("html").addClass("myMobileBP");
}

pour aller encore plus loin, vous pourriez vouloir considérer le manque de support javascript. Définir les médiaqueries qui sont en outre enveloppées dans une classe html.no-js , puis avec javascript supprimer le Classe .no-js et appliquer la solution ci-dessus en ajoutant des points de rupture via des classes javascript.

0
répondu kontur 2014-07-02 08:26:28

suivez ce lien

function getWindowWidth() {
    var windowWidth = 0;
    if (typeof(window.innerWidth) == 'number') {
        windowWidth = window.innerWidth;
    }
    else {
        if (document.documentElement && document.documentElement.clientWidth) {
            windowWidth = document.documentElement.clientWidth;
        }
        else {
            if (document.body && document.body.clientWidth) {
                windowWidth = document.body.clientWidth;
            }
        }
    }
    return windowWidth;
}
0
répondu Amidou Zabre 2015-11-17 12:42:05

utilisez des classes sur le corps pour définir si vous êtes sur mobile, tablette ou bureau à la place en utilisant des pixels.

pour moi ça n'a pas fonctionné document.body.clientWidth ou innerWidth . Ma fonctionnalité s'écrase entre 1023-1040px même si mon code js doit faire cette déclaration:

if($(window).width()<1024)

la solution était de mettre sur le corps une nouvelle classe pour moins de 1024 et l'appeler "small-res" et l'utiliser que dans mon code au lieu de pixels vérification:

if($(body).hasClass('small-res')) 

je vous le recommande aussi.

-1
répondu Potoroaca Anamaria 2017-05-20 11:58:09