Bug: Behavior of comparison functions is unintuitive and makes smallest breakpoint useless for logic.
Hello,
thanks for providing this library. Unfortunately I ran into an issue with it and it does not behave exactly as I would expect it to do.
So I am currently struggling with the following issues.
I have a couple of breakpoints defined and want some logic to only apply for mobile devices. As far as I could see in the code the comparisons are made on an index level rather than on a per pixel basis. This leads to some very weird and unexpected behavior.
Let's suppose we have defined the following 3 breakpoints:
mobile: 320
tablet: 768
desktop: 992
Now we want to build some logic that e.g. shows some part of the UI only on mobile. However the comparison functions do not work properly for doing that.
Screen width 769px
viewport.isLessThan('tablet'): false
viewport.isLessOrEquals('tablet'): true
viewport.isGreaterThan('mobile'): true
viewport.isGreaterOrEquals('mobile'): true
viewport.isLessThan('mobile'): false
viewport.isLessOrEquals('mobile'): false
However already at screen width 760px it gets weird, because the isLessThan('mobile') already shows true.
Screen width 760px (same result at 321px)
viewport.isLessThan('tablet'): true
viewport.isLessOrEquals('tablet'): true
viewport.isGreaterThan('mobile'): false (expected: true)
viewport.isGreaterOrEquals('mobile'): true
viewport.isLessThan('mobile'): false
viewport.isLessOrEquals('mobile'): true (expected: false)
However at 300px the result is exactly the same as at 321px. meaning the mobile breakpoint in this case is completely useless for any logic.
viewport.isLessThan('tablet'): true
viewport.isLessOrEquals('tablet'): true
viewport.isGreaterThan('mobile'): false
viewport.isGreaterOrEquals('mobile'): true (expected: false, because 300px < 320px)
viewport.isLessThan('mobile'): false (expected: true, because 300px < 320px)
viewport.isLessOrEquals('mobile'): true (expected: false, because 300px < 320px)
Intuitively it would make more sense to make the comparison pixel based, because
Proposed solution:
- either make the comparison pixel based
- add a fake breakpoint automatically
A current workaround is to add a "fake breakpoint" e.g. mobileFake: 319 to the configuration to get the desired result.
Hi, @twatzl!
// nuxt.config.ts
{
viewport: {
breakpoints: {
mobile: 320,
tablet: 768,
desktop: 992,
},
},
}
However already at screen width 760px it gets weird, because the isLessThan('mobile') already shows true.
What do expect to have as a breakpoint, when is less then the smallest one? I originally designed this library so that there could not be nullable breakpoint value.
Ok. So I looked into this again and thought about it because it is tricky.
First I wanna apologize, because I did a mistake. I wrote the following
However already at screen width 760px it gets weird, because the isLessThan('mobile') already shows true.
but instead of isLessThan I meant at 760px it already says isLessThanOrEquals is true.
Anyway the problem remains. No matter if you are at 321px or 319px with the given settings the queries return the same result. This means the "breakpoint" at 320px is not breaking anything.
isLessThan('smallestBreakpoint') can never become true with the current logic. However when using the library this would be the expectation.
So in my opinion the logic must be changed, so that isLessThan('smallestBreakpoint') can actually become true at some point. There are possibly different ways how to achieve this. Maybe at least for the internal logic an imaginary breakpoint at 1px is needed so this logical evaluation returns the correct value?
Can you please explain your case, where it's breaking for you? When do you need to render anything less than the mobile breakpoint?
So I would expect to see isLessThan('mobile') change to true if the viewport is smaller than 320px.
It is very simple. If the screen is less than 320px then it is smaller than the mobile breakpoint, right? So I would expect it to behave as follows
window.width = 319 => isLessThan('mobile') = true
window.width = 320 => isLessThan('mobile') = false
window.width = 321 => isLessThan('mobile') = false
same as one gets
window.width = 767 => isLessThan('tablet') = true
window.width = 768 => isLessThan('tablet') = false
window.width = 769 => isLessThan('tablet') = false
@twatzl Try using maxWidth feature for this.
https://github.com/mvrlin/nuxt-viewport?tab=readme-ov-file#feature
Ok. I have to check this when I find some time.
@twatzl Hey! Do have any updates on that?
I think it looks good. I cannot remember the exact issue, I had back then, anymore, but I tried it and I think for now it's solved.