Descubrí que cuando tengo una consulta de matchMedia basada en el ancho que está escuchando en una página, se llama cuando la imprimo.
Aquí hay un fragmento que sería más completo:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no,viewport-fit=cover" /> </head> <body> <div>Open me in chrome, look at the console and print the page</div> <script> const mediaQuery = window.matchMedia('only screen and (min-width: 768px)') mediaQuery.addEventListener('change', () => { console.log('change width event', { innerWidth: window.innerWidth, outerWidth: window.outerWidth }) }) </script> </body> </html>
En mi consola puedo ver que window.innerWidth
tiene el valor 555 cuando imprimo y luego se llama a mediaQuery justo después de esto con el valor correcto de mi ventana (que es mayor que 555).
¿Por qué sucede esto, cómo podemos desactivar esto?
Probablemente se deba only screen
que es lo opuesto a la print
. Cuando imprima la página, la consulta ya no se aplicará y se llamará al evento matchMedia
Simplemente quitar only screen
podría solucionar su problema
Editar: otra idea podría ser capturar solicitudes de impresión con window.onberforeprint
( window.addEventListener("beforeprint", function(event) { ... });
) y establecer un valor booleano para que ahora la página se imprima
Parece que Chrome/Webkit vuelve a cargar la página para la vista previa de impresión, tiene sentido.
No puedo decir por qué el evento se disparó dos veces (una vez impresa y otra no impresa), hay muchos artículos contradictorios en la web. Supongo que tiene que ver con cambiar el contexto entre la vista previa y la ventana normal del navegador, pero en cualquier caso, aquí hay una solución que funciona con matchMedia
.
Descargo de responsabilidad: es un poco complicado/prolijo, pero funciona.
Advertencia/Información: hay un caso límite, cuando cierra la ventana de impresión demasiado rápido/en el segundo correcto, que el segundo evento no se activará. Y debido a esto, se ignorará el próximo evento normal. Para remediar esto, también se podría agregar la línea con una declaración setTimeout
, que restablece la propiedad/variable _ignoreNext
. (No lo incluí en el código porque ya era muy largo)
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no,viewport-fit=cover" /> </head> <body> <div>Open me in chrome, look at the console and print the page</div> <script> const mediaQuery = window.matchMedia('(only screen and (min-width: 768px))'); mediaQuery.addEventListener('change', () => { // check if the current state is for media Query "print" let matchtesPrint = window.matchMedia('print').matches; // mq._ignoreNext is a helper Variable, to catch the second Event triggered if(mq._ignoreNext && !matchtesPrint){ // reset everything to "normal" mq._ignoreNext = false; } else if(matchtesPrint){ // if in print mode set helper variable, so that second event can be skipped mq._ignoreNext = true; } else { // normal mediaMatch console.log('change width event', { innerWidth: window.innerWidth, outerWidth: window.outerWidth }); } }) </script> </body> </html>