$ (ventana) .width () no es lo mismo que una consulta de medios

187

Estoy usando Twitter Bootstrap en un proyecto. Además de los estilos de arranque predeterminados, también he agregado algunos de los míos.

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

También estoy usando jQuery para cambiar el orden de ciertos elementos en la página cuando el ancho de la ventana gráfica es inferior 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"));
    }
}

El problema que tengo es que el ancho calculado por $(window).width()y el ancho calculado por el CSS no parece ser el mismo. Cuando $(window).width()devuelve 767, el CSS calcula el ancho de la ventana gráfica como 751, por lo que parece haber un 16px diferente.

¿Alguien sabe qué está causando esto y cómo podría resolver el problema? La gente ha sugerido que el ancho de la barra de desplazamiento no se tiene en cuenta y el uso $(window).innerWidth() < 751es el camino a seguir. Sin embargo, idealmente quiero encontrar una solución que calcule el ancho de la barra de desplazamiento y que sea coherente con mi consulta de medios (por ejemplo, donde ambas condiciones se comparan con el valor 767). ¿Porque seguramente no todos los navegadores tendrán un ancho de barra de desplazamiento de 16px?

Pattle
fuente
1
Pruebe algo si ($ ('html'). Width () <= 767) {// Hacer algo}
Vaibs_Cool
@Vaibs_Cool Gracias por la sugerencia, pero sigo obteniendo el mismo resultado
Pattle
Responda aquí [ingrese la descripción del enlace aquí] [1] [1]: stackoverflow.com/questions/11309859/…
Rantiev
¿"Document.documentElement.clientWidth" (en lugar de "$ (window) .width ()") funciona como desea que funcione? Editar: Mi error, acabo de ver la respuesta de Vaibs_Cool.
joshhunt

Respuestas:

294

Si no tiene que soportar IE9, simplemente puede usar window.matchMedia()( documentación de MDN ).

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

window.matchMedia es totalmente coherente con las consultas de medios CSS y el soporte del navegador es bastante bueno: http://caniuse.com/#feat=matchmedia

ACTUALIZAR:

Si tiene que admitir más navegadores, puede usar el método mq de Modernizr , es compatible con todos los navegadores que entienden las consultas de medios en CSS.

if (Modernizr.mq('(max-width: 767px)')) {
    //...
} else {
    //...
}
ausi
fuente
8
Si puede permitirse el lujo de usar la biblioteca Modernizr, esta es la mejor respuesta que existe.
richsinn
1
Esta solución es mejor: stackoverflow.com/a/19292035/1136132 (segundo código). Solo JS.
joseantgv
@joseantgv Mi solución también es solo js. ¿Puedes explicar por qué la solución que vinculaste es mejor?
ausi
2
@edwardm Modernizr.mqsolo devuelve un valor booleano, por lo que debe llamarlo usted mismo en un onresizecontrolador de eventos.
ausi
2
@Bernig window.matchMediaes la forma recomendada, ya que no activa un reflujo , dependiendo de la frecuencia con la que llame a la función, esto puede causar un problema de rendimiento. Si no desea utilizar Modernizr directamente, puede copiar el código fuente de src / mq.js y src / injectElementWithStyles.js .
ausi
175

Verifique una regla CSS que cambia la consulta de medios. Esto está garantizado para trabajar siempre.

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;
    }
}
Nates
fuente
9
Esa es una solución más elegante que los hacks JS mencionados en las otras respuestas.
René Roth
3
+1 esto es simplemente inteligente. Me gusta cómo si quieres cambiar los puntos de interrupción, todo lo que tienes que hacer es cambiar el CSS y no JavaScript.
JoeMoe1984
Esta solución funciona bien y me parece más elegante que el truco de JavaScript propuesto en la respuesta más votada.
Andrés Meza-Escallón
2
Si usa bootstrap puede hacerlo sin css como<div id="xs-indicator" class="xs-visible">
Čamo
33

Puede deberse a scrollbar, usar en innerWidthlugar de widthcomo

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

También puedes obtener el me viewportgusta

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

Código anterior Fuente

Rohan Kumar
fuente
Gracias. Esto funcionará, pero de todos modos puedo usar jquery para incluir el ancho de la barra de desplazamiento. ¿Solo estoy pensando que el ancho de la barra de desplazamiento podría cambiar en diferentes navegadores?
Pattle
1
Sí, úselo innerWidth()o úselo como $('body').innerWidth();Vea este stackoverflow.com/questions/8339377/…
Rohan Kumar
3
Te refieres a window.innerWidth, no en el objeto jQuery $ (window), $ (window) .width () lo devuelve incorrectamente
EJanuszewski
1
window.innerWidthno es consistente con las consultas de medios CSS en Safari 8 si las barras de desplazamiento están habilitadas en las preferencias del sistema OSX.
ausi
10

Sí, eso se debe a la barra de desplazamiento. Fuente de respuesta correcta: ingrese la descripción del enlace aquí

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

Tal vez sea una mejor práctica no aplicar un alcance JS al ancho del documento, sino algún tipo de cambio realizado por la consulta css @media. Con este método puede estar seguro de que la función JQuery y el cambio de CSS ocurren al mismo tiempo.

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");
    ...
});
gramo
fuente
3

Estaba enfrentando el mismo problema recientemente, también con Bootstrap 3.

Ni $ .width () ni $ .innerWidth () funcionarán para usted.

La mejor solución que se me ocurrió, y está específicamente diseñada para BS3,
es verificar el ancho de un .containerelemento.

Como probablemente sepa cómo funciona el .containerelemento,
es el único elemento que le dará el ancho actual establecido por las reglas BS css.

Entonces va algo como

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");
usuario3041539
fuente
3

Utilizar

window.innerWidth

Esto resolvió mi problema

usuario4451021
fuente
3

Aquí hay una alternativa a los métodos mencionados anteriormente que se basan en cambiar algo a través de CSS y leerlo a través de Javascript. Este método no necesita window.matchMediani Modernizr. Tampoco necesita ningún elemento HTML adicional. Funciona mediante el uso de un pseudo-elemento HTML para 'almacenar' información de punto de interrupción:

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

He utilizado bodycomo un ejemplo, se puede utilizar cualquier elemento HTML para esto. Puede agregar cualquier cadena o número que desee en contentel pseudo-elemento. No tiene que ser 'móvil', etc.

Ahora podemos leer esta información de Javascript de la siguiente manera:

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

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

De esta manera, siempre estamos seguros de que la información del punto de interrupción es correcta, ya que proviene directamente de CSS y no tenemos que preocuparnos por obtener el ancho de pantalla correcto a través de Javascript.

dschenk
fuente
No necesita usar querySelector()o getPropertyValue(). También puede buscar comillas simples en regex (ya que no es consistente). Este: window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, ''). Y, para que sea un poco menos costoso, puede envolverlo en subrayado / lodash ._debounce()con ~ 100ms de espera. Finalmente, agregar atributos a <html> hace que la salida esté disponible para otras cosas, como las cláusulas de desactivación de información sobre herramientas que buscan indicadores / datos sin procesar fuera de vars. Ejemplo: gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin el
2

Javascript proporciona más de un método para verificar el ancho de la ventana gráfica. Como notó, innerWidth no incluye el ancho de la barra de herramientas, y los anchos de la barra de herramientas diferirán entre los sistemas. También está el opción externalWidth , que incluirá el ancho de la barra de herramientas. La API de Javascript de Mozilla dice:

Window.outerWidth obtiene el ancho del exterior de la ventana del navegador. Representa el ancho de toda la ventana del navegador, incluida la barra lateral (si está expandida), el cromo de la ventana y los bordes / controles de redimensionamiento de la ventana.

El estado de javascript es tal que no se puede confiar en un significado específico para externalWidth en cada navegador en cada plataforma.

outerWidthno es compatible con navegadores móviles más antiguos , aunque goza de soporte en los principales navegadores de escritorio y en la mayoría de los navegadores de teléfonos inteligentes más nuevos.

Como señaló Ausi, matchMediasería una gran opción ya que CSS está mejor estandarizado (matchMedia usa JS para leer los valores de viewport detectados por CSS). Pero incluso con los estándares aceptados, todavía existen navegadores retrasados ​​que los ignoran (IE <10 en este caso, lo que hace que matchMedia no sea muy útil al menos hasta que XP muera).

En resumen , si solo está desarrollando para navegadores de escritorio y navegadores móviles más nuevos, externalWidth debería darle lo que está buscando, con algunas advertencias .

fzzylogic
fuente
1

Aquí hay un truco menos complicado para lidiar con las consultas de los medios. La compatibilidad entre navegadores es un poco limitante, ya que no es compatible con IE móvil.

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

Consulte la documentación de Mozilla para más detalles.

usuario2128205
fuente
1

prueba esto

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
      }
    )
}
DINESH Adhikari
fuente
0

Solución alternativa que siempre funciona y se sincroniza con las consultas de medios CSS.

Agregar un div al cuerpo

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

Agregue estilo y cámbielos ingresando en una consulta de medios específica

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

Luego, en JS, verifique el estilo que está cambiando al ingresar a la consulta de medios

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

Por lo tanto, generalmente puede verificar cualquier estilo que se esté modificando ingresando en una consulta de medios específica.

Arsen Pyuskyulyan
fuente
0

La mejor solución entre navegadores es usar Modernizr.mq

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

Modernizr.mq le permite verificar mediante programación si el estado actual de la ventana del navegador coincide con una consulta de medios.

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

Nota El navegador no admite consultas de medios (p. Ej., IE antiguo) mq siempre devolverá falso.

Sanjib Debnath
fuente
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);

        });

    }
Adam Colton
fuente
0

Lo que hago ;

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

y llame a aWidth variable en cualquier lugar después.

Debe colocar getWidth () en el cuerpo del documento para asegurarse de que se cuenta el ancho de la barra de desplazamiento; de lo contrario, el ancho de la barra de desplazamiento del navegador se restará de getWidth ().

burkul
fuente
-1

Deslizador deslizante de implementación y muestra diferentes números de diapositivas en el bloque dependiendo de la resolución (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,
      });
    }
Vitalii
fuente
-2

Prueba esto

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

Para más referencia haga clic aquí

Vaibs_Cool
fuente
Gracias, esto todavía tiene el mismo resultado
Pattle