$ (finestra) .width () non è lo stesso della media query


187

Sto usando Twitter Bootstrap su un progetto. Oltre agli stili di bootstrap predefiniti ne ho anche aggiunti alcuni

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

Sto anche usando jQuery per cambiare l'ordine di alcuni elementi nella pagina quando la larghezza del viewport è inferiore a 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"));
    }
}

Il problema che sto riscontrando è che la larghezza calcolata da $(window).width()e la larghezza calcolata dal CSS non sembra essere la stessa. Quando $(window).width()restituisce 767, il CSS calcola la larghezza della finestra come 751, quindi sembra che ci sia un 16px diverso.

Qualcuno sa cosa sta causando questo e come potrei risolvere il problema? Le persone hanno suggerito che la larghezza della barra di scorrimento non viene presa in considerazione e l'utilizzo $(window).innerWidth() < 751è la strada da percorrere. Comunque idealmente voglio trovare una soluzione che calcoli la larghezza della barra di scorrimento e che sia coerente con la mia media query (ad es. Dove entrambe le condizioni stanno verificando rispetto al valore 767). Perché sicuramente non tutti i browser avranno una larghezza della barra di scorrimento di 16 px?


1
Prova qualcosa se ($ ('html'). Width () <= 767) {// Fai qualcosa}
Vaibs_Cool

@Vaibs_Cool Grazie per il suggerimento ma ottengo sempre lo stesso risultato
Pattle


Risposta Ho qui [inserire descrizione collegamento qui] [1] [1]: stackoverflow.com/questions/11309859/...
Rantiev

"Document.documentElement.clientWidth" (invece di "$ (window) .width ()") funziona come vuoi che funzioni? Modifica: errore mio, ho appena visto la risposta di Vaibs_Cool.
joshhunt,

Risposte:


294

Se non devi supportare IE9 puoi semplicemente usare window.matchMedia()( documentazione MDN ).

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

window.matchMediaè pienamente coerente con le query multimediali CSS e il supporto del browser è abbastanza buono: http://caniuse.com/#feat=matchmedia

AGGIORNARE:

Se devi supportare più browser, puoi utilizzare il metodo mq di Modernizr , che supporta tutti i browser che comprendono le query multimediali nei CSS.

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

8
Se puoi permetterti di usare la libreria Modernizr, questa è la migliore risposta là fuori.
Richsinn,

1
Questa soluzione è migliore: stackoverflow.com/a/19292035/1136132 (2 ° codice). Solo JS.
joseantgv,

@joseantgv La mia soluzione è anche solo per js. Puoi spiegare perché la soluzione a cui ti sei collegato è migliore?
ausi,

2
@edwardm Modernizr.mqrestituisce solo un valore booleano, quindi devi chiamarlo tu stesso in un onresizegestore eventi.
ausi,

2
@Bernig window.matchMediaè il modo consigliato, perché non attiva un riflusso , a seconda della frequenza con cui si chiama la funzione ciò può causare un problema di prestazioni. Se non si desidera utilizzare Modernizr direttamente, è possibile copiare il codice sorgente da src / mq.js e src / injectElementWithStyles.js .
ausi,

175

Controlla una regola CSS che cambi la media query. Questo è garantito per funzionare sempre.

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
Questa è una soluzione più elegante rispetto agli hack di JS citati nelle altre risposte.
René Roth,

3
+1 questo è solo intelligente. Mi piace come se si desidera modificare i punti di interruzione, tutto ciò che si deve fare è cambiare il CSS e non JavaScript.
JoeMoe1984,

Questa soluzione funziona bene e la trovo più elegante dell'hack JavaScript proposto nella risposta più votata.
Andrés Meza-Escallón,

2
Se usi bootstrap puoi farlo senza css come<div id="xs-indicator" class="xs-visible">
Čamo,

33

Potrebbe essere dovuto a scrollbar, utilizzare innerWidthinvece di widthcome

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

Inoltre puoi ottenere il viewportlike

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

Codice sopra la fonte


Grazie. Funzionerà ma c'è comunque che posso usare jquery per includere la larghezza della barra di scorrimento. Sto solo pensando che la larghezza della barra di scorrimento potrebbe cambiare su diversi browser?
Pattle,

1
Sì, usa innerWidth()o puoi usarlo come $('body').innerWidth();Vedi questo stackoverflow.com/questions/8339377/…
Rohan Kumar

3
Intendi window.innerWidth, non sull'oggetto jQuery $ (window), $ (window) .width () lo restituisce in modo errato
EJanuszewski,

1
window.innerWidthnon è coerente con le query multimediali CSS in Safari 8 se le barre di scorrimento sono abilitate nelle preferenze di sistema OSX.
ausi,

10

sì, è dovuto alla barra di scorrimento. Fonte risposta corretta: inserisci qui la descrizione del link

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

Forse è una pratica migliore non JS-scope la larghezza del documento, ma una sorta di modifica apportata dalla query css @media. Con questo metodo puoi essere sicuro che la funzione JQuery e la modifica css avvengono contemporaneamente.

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

Di recente ho riscontrato lo stesso problema, anche con Bootstrap 3.

Né $ .width () né $ .innerWidth () funzioneranno per te.

La migliore soluzione che mi è venuta in mente - ed è specificamente adattata a BS3 -
è quella di controllare la larghezza di un .containerelemento.

Come probabilmente sai come funziona l' .containerelemento,
è l'unico elemento che ti darà la larghezza corrente impostata dalle regole BS css.

Quindi va qualcosa del genere

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

Ecco un'alternativa ai metodi menzionati in precedenza che si basano sulla modifica di qualcosa tramite CSS e la lettura tramite Javascript. Questo metodo non ha bisogno window.matchMediao Modernizr. Inoltre, non richiede alcun elemento HTML aggiuntivo. Funziona utilizzando uno pseudo-elemento HTML per "archiviare" le informazioni sui breakpoint:

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

Ho usato bodycome esempio, puoi usare qualsiasi elemento HTML per questo. È possibile aggiungere qualsiasi stringa o numero desiderato nello contentpseudo-elemento. Non deve essere "mobile" e così via.

Ora possiamo leggere queste informazioni da Javascript nel modo seguente:

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

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

In questo modo siamo sempre sicuri che le informazioni sul punto di interruzione siano corrette, poiché provengono direttamente dai CSS e non dobbiamo preoccuparci di ottenere la larghezza dello schermo corretta tramite Javascript.


Non è necessario utilizzare querySelector()o getPropertyValue(). Puoi anche cercare una singola citazione in regex (poiché non è coerente). Questo: window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, ''). E, per renderlo un po 'meno costoso, puoi avvolgerlo in underscore / lodash ._debounce()con ~ 100ms di attesa. Infine, l'aggiunta di attributi a <html> rende l'output disponibile ad altre cose come clausole di disabilitazione dei tooltip che cercano flag / dati non elaborati al di fuori di var. Esempio: gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin

2

Javascript fornisce più di un metodo per controllare la larghezza della finestra. Come hai notato, innerWidth non include la larghezza della barra degli strumenti e la larghezza della barra degli strumenti differirà tra i sistemi. C'è anche l' opzione outerWidth , che includerà la larghezza della barra degli strumenti. L' API Javascript di Mozilla afferma:

Window.outerWidth ottiene la larghezza dell'esterno della finestra del browser. Rappresenta la larghezza dell'intera finestra del browser, inclusi la barra laterale (se espansa), i bordi e le maniglie di ridimensionamento della finestra e della finestra.

Lo stato di javascript è tale che non si può fare affidamento su un significato specifico per outerWidth in ogni browser su ogni piattaforma.

outerWidthnon è ben supportato sui browser mobili meno recenti , sebbene goda del supporto sui principali browser desktop e sulla maggior parte dei browser per smartphone più recenti.

Come ha sottolineato ausi, matchMediasarebbe un'ottima scelta in quanto CSS è meglio standardizzato (matchMedia utilizza JS per leggere i valori di viewport rilevati da CSS). Ma anche con gli standard accettati, esistono ancora browser ritardati che li ignorano (IE <10 in questo caso, il che rende matchMedia non molto utile almeno fino alla morte di XP).

In sintesi , se stai sviluppando solo per browser desktop e browser mobili più recenti, outerWidth dovrebbe darti quello che stai cercando, con alcuni avvertimenti .


1

Ecco un trucco meno complicato per gestire le query dei media. Il supporto cross-browser è un po 'limitante in quanto non supporta IE mobile.

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

Vedi la documentazione di Mozilla per maggiori dettagli.


1

prova questo

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

Soluzione alternativa che funziona sempre ed è sincronizzata con le query multimediali CSS.

Aggiungi un div al corpo

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

Aggiungi stile e modificali accedendo a media query specifiche

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

Quindi, in JS, controlla lo stile che stai modificando accedendo alla media query

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

Quindi, in generale, è possibile controllare qualsiasi stile che viene modificato accedendo a media query specifiche.


0

La migliore soluzione cross-browser è utilizzare Modernizr.mq

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

Modernizr.mq consente di verificare a livello di codice se lo stato della finestra del browser corrente corrisponde a una query multimediale.

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

Nota Il browser non supporta le query multimediali (ad es. IE precedenti). Mq restituirà sempre 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

Quello che faccio ;

<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 in seguito chiama una variabile Larghezza ovunque.

È necessario inserire getWidth () nel corpo del documento per assicurarsi che venga conteggiata la larghezza della barra di scorrimento, altrimenti la larghezza della barra di scorrimento del browser sottratta da getWidth ().


-1

Cursore scorrevole di implementazione e visualizza diversi numeri di diapositive nel blocco in base alla risoluzione (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

Prova questo

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

Per ulteriori riferimenti clicca qui


Grazie, questo ha comunque lo stesso risultato
Pattle,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.