Perché window.width è più piccola della larghezza della viewport impostata nelle media query

Sono abbastanza perplesso e ancora incerto su come spiegarlo in parole appropriate. Finora ho usato e impostato le mie query multimediali con Breakpoint. Una variabile Breakpoint utilizzata assomiglia ad esempio:

$menustatictofixed: min-width 900px; 

$ breakpoint-to-ems è impostato su true. Ho disposto la pagina con tutte le sue variabili Breakpoint in base ai valori dei pixel del seguente frammento di jQuery:

 $('body').append('
Viewport width px
'); var viewportWidth = $(window).width() $('#width').text(viewportWidth); $(window).resize(function() { var viewportWidth = $(window).width(); $('#width').text(viewportWidth); });

Tutto sembrava corretto e pulito. Ma negli ultimi uno o due giorni ho avuto problemi nell’impostare gli ultimi punti di interruzione per un modello e far sì che le cose si comportassero in modo prevedibile. In qualche modo le cose che sembravano chiare e pulite in primo luogo, che logicamente dubito fortemente ora, sono in realtà improprie e in qualche modo un disastro. Perché se dai un’occhiata alla seguente schermata in qualche modo la larghezza della finestra (in Chrome) è diversa dalla larghezza dello snippet jQuery che utilizza window.width. Non c’è anche differenza se sostituirò window.width con window.innerWidth per escludere eventualmente le scrollbar. L’unico modo per ricevere risultati appropriati è aggiungere 15 pixel all’equazione:

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

L’unico problema in tutta l’equazione è che window.width è la scelta sbagliata di funzione e sarebbe meglio andare con eg document.documentElement.clientWidth o qualcos’altro o …? E per quali sono i 15 pixel per cui è stato risolto il problema sopra in modo un po ‘hacky? Cordiali saluti Ralf

La risposta è scrollbar e la soluzione è complicata.

Le query sui media sono interessanti. Non si comportano esattamente allo stesso modo attraverso il browser, il che significa che il loro utilizzo a volte non può essere così facile. Ad esempio, in -webkit / -blink su OS X e IE10 su Win8, le barre di scorrimento sono sovrapposte alla pagina. In -moz, tuttavia, le barre di scorrimento non sono sovrapposte alla pagina. Il modo migliore per ottenere “l’area visibile” della pagina è la seguente riga di vaniglia JavaScript (presupponendo che tu disponga di un documento HTML valido):

 document.body.parentNode.clientWidth 

Ciò che questo farà è trovare l’elemento body , trovare il suo genitore (che in un documento valido sarà l’elemento html ), e poi trovare la sua larghezza dopo il rendering. Questo ti darà la larghezza che ti interessa vedere. È anche una larghezza inutile da avere .

Perché, si potrebbe chiedere, sta avendo l’effettiva larghezza del client inutile? Non è perché varia da browser a browser, perché lo fa. È perché non è quello che le query sui media di width stanno effettivamente testando! Quel test della width media test è window.innerWidth , che è quello che stai essenzialmente usando ora.

Quindi qual è la soluzione a questo problema? Bene, direi che la soluzione è utilizzare le query multimediali basate sul contenuto invece delle query multimediali basate su dispositivo e andare bene con qualche spazio di manovra nelle tue query (specialmente se quella stanza di prova è di circa 15px ). Se non lo hai già fatto, leggi gli articoli Vexing Viewports e A Pixel Identity Crisis per avere un’idea del perché un potenziale luccichio di 15px nelle definizioni MQ non sia la cosa peggiore al mondo (ci sono probabilmente pesci più grandi da friggere) .

Quindi, in conclusione, continua a utilizzare $breakpoint-to-ems: true e scegli le tue query multimediali in base a quando il contenuto si interrompe a window.innerWidth quanto è l’unico modo corretto per gestire i problemi relativi a più browser. Da uno sguardo superficiale a vari problemi, sembra che la maggior parte dei browser e dei sistemi operativi passino a una barra di scorrimento sovrapposta (a partire da Firefox 24 ogni browser OS X ne avrà uno, l’interfaccia utente di Unity di Ubuntu li ha introdotti ), quindi nel tentativo di essere amici del futuro , Suggerirei di non preoccuparmi dell’offset della barra di scorrimento e di essere a posto con siti leggermente diversi da un browser all’altro. Ricorda, come Ethan Marcotte ha messo in modo eloquente:

Il Web è un mezzo intrinsecamente instabile

Questo è ciò che ha funzionato per me: le query sui supporti CSS e la larghezza della finestra JavaScript non corrispondono .

Invece di usare $(window).width(); che include barre di scorrimento per ottenere la larghezza interna come questa:

 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 

È a causa della scrollbar's

La soluzione più corretta che ho trovato è quella di utilizzare le query multimediali per passare la dimensione effettiva della finestra a Javascript. Devi seguire questi passaggi:

  • Aggiungi un elemento nascosto alla tua pagina,
  • Utilizza le query multimediali per modificare la proprietà di max-width di quell’elemento,
  • Leggi la proprietà della max-width di quell’elemento tramite Javascript.

Ad esempio, aggiungi il seguente elemento alla tua pagina:

 

Quindi scrivi le seguenti regole CSS:

 #currentMedia { display: none; } @media (max-width: 720px) { // Make arrows in the carousel disappear... #currentMedia { max-width: 720px; } } 

Quindi, dal lato Javascript, puoi scrivere:

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

E sarà accurato indipendentemente dalla dimensione della barra di scorrimento, poiché il valore deriva dalla stessa query multimediale che triggers la scomparsa del carosello.

Ho provato questa soluzione su tutti i principali browser recenti e fornisce risultati corretti.

Troverai il grande riepilogo di quali proprietà sono supportate su quali browser in questa pagina su quirksmode.org .

La cosa migliore è probabilmente prendere un elemento nella pagina (usando document.body dove supportato, o document.getElementById o qualsiasi altra cosa), cammina la sua catena offsetParent per trovare l'elemento più in alto, quindi esamina clientWidth e clientHeight di quell'elemento.

documentazione di innerWidth

.innerWidth() metodo .innerWidth() non è applicabile agli oggetti window e document ; per questi, usa invece .width() .

Simile alla risposta di @ Snugugs, ma ha funzionato meglio per il mio caso d’uso:

CSS (Nota Sto usando MENO così @tabletMin e @desktopMin traducono in variabili breakpoint che ho impostato altrove:

  #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... */ } 

E poi in 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 funzione getView () restituirà quindi la stringa “mobile”, “tablet” o “desktop” in base alla larghezza che vedono le media query .

Questo può essere esteso per adattarsi a più larghezze di viewport, basta aggiungere più regole nel CSS con altri valori.

La risposta di @Sugend fornisce una spiegazione molto buona del perché questo sta accadendo, e @TusharGupta ha una buona soluzione che fa riferimento alla larghezza rilevata da mediaquery a javascript. Sotto soluzione va il contrario utilizzando la larghezza rilevata javascript per triggersre le modifiche al layout.

Nel caso in cui sia necessario sincronizzare mediaquery con il rilevamento della larghezza di pixel javascript, un modo per affrontare il problema è di triggersre le modifiche al layout css in base alle classi aggiunte con javascript.

Quindi, invece di scrivere mediaqueries, scrivi quelle dichiarazioni annidate sotto una class, dì:

 html.myMobileBP { ... } 

E nella tua javascript / jQuery, aggiungi questa class come:

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

Per fare ancora di più, potresti voler considerare la mancanza di supporto per JavaScript. Definire mediaqueries che sono inoltre avvolti in una class html.no-js , quindi con javascript rimuovere la class .no-js e applicare la soluzione di cui sopra per aggiungere punti di interruzione tramite classi javascript.

segui questo link

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

Utilizza le classi sul corpo per definire se sei su cellulare, tablet o desktop utilizzando invece i pixel.

Per me non ha funzionato document.body.clientWidth o innerWidth . La mia funzionalità si blocca tra 1023-1040px anche se il mio codice js deve eseguire questa istruzione:

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

La soluzione era di mettere sul corpo una nuova class per meno di 1024 e chiamarla "small-res" e usarla piuttosto che nel mio codice invece della verifica dei pixel:

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

Lo consiglio anche a te.