I have found out that when I have a matchMedia query based on width which is listening in a page, it is called when I print it.
Here is a snippet that would be more comprehensive :
<!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>
In my console I can see that window.innerWidth
has the value 555 when I print and then the mediaQuery is called right after this with the correct value of my window (which is bigger than 555).
Why does this happen, how can we disable this ?
It's probably because of only screen
which is the opposite of print
.
When you print the page , the query won't apply anymore and the matchMedia event is called
Just removing only screen
might fix your problem
Edit: An other idea might be to catch print requests with window.onberforeprint
(window.addEventListener("beforeprint", function(event) { ... });
) and set a boolean so you now the page is printed
It seems, that Chrome/Webkit reloads the page for the print preview, makes sense.
Why the fire the Event twice I can't say (once in print and once not in print), there are many contradicting article on the web. I assume it has to do with switching context between the preview and the normal browser window, but in any case here is a working solution with the matchMedia
.
Disclaimer: it is a bit hacky/verbose, but works.
Warning / Info: there is a edge case, when you close the print-window too fast/in the right second, that the second event won't fire. AND because of this the next normal event will be ignored. To remedy this, one could also add the line with a setTimeout
statment, that resets the _ignoreNext
property / variable. (I didn't include it in the code since it was already very long)
<!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>