- Some JavaScript libraries relies on window
innerWidth
andinnerHeight
to do their calculations window.innerWidth
is not 100% reliable, which may lead to bugsmatchMedia().matches
is 100% accurate but it returns a boolean value- come around: use
matchMedia
to verifywindow.innerWidth
value; if it returns false usematchMedia
to do a binary search until it finds the correct value
I faced that issue with some libs that relies on window.innerWidth
. In cases where I had some media queries the return value of window.innerWidth
used by the library would be off and that library would have issues with incorrect value.
I've seen that matchMedia().matches
always return the correct value, but it returns a boolean value, not the width value. I've not seen a solution so far for that (maybe some of you know a better solution?), so I came up with a solution using matchMedia
.
I created a function getCorrectDimension
that performs a binary search around the window innerWidth
(or innerHeight
) to find the correct value if its value is wrong as you can see below:
const binarySearch = dim => function bin(start, end) {
const guess = Math.floor((start + end)/2)
// this checks if we have the correct value, if not it will keep calling itself until there's a match
if(window.matchMedia(`(${dim}: ${guess}px)`).matches) {
return guess
}
// since it is not a match, then we need to recalibrate the range and call again.
// for that we check the boolean value using with min-width (height) rule.
return window.matchMedia(`(min-${dim}: ${guess}px)`).matches
? bin(guess, end)
: bin(start, guess)
}
const getCorrectDimension = (dim = 'width', range = 300) => {
if(dim !== 'width' && dim !== 'height') {
throw Error('`getCorrectDimension` accepts "width" or "height" as parameter')
}
let prop = 'inner' + dim.charAt(0).toUpperCase() + dim.slice(1)
// here checks if the window.innerWidth or Height it's the correct one
if(window.matchMedia(`(${dim}: ${window[prop]}px)`).matches) {
return window[prop]
}
// here, since the value is wrong we use binarySearch to find its correct value
const start = window[prop] - range >= 0 ? window[prop] - range : 0
const end = window[prop] + range
return binarySearch(dim)(start, end)
}