nuxt-viewport icon indicating copy to clipboard operation
nuxt-viewport copied to clipboard

Bug: Behavior of comparison functions is unintuitive and makes smallest breakpoint useless for logic.

Open twatzl opened this issue 1 year ago • 6 comments

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.

twatzl avatar Dec 27 '24 23:12 twatzl

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.

image image

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.

mvrlin avatar Dec 28 '24 18:12 mvrlin

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?

twatzl avatar Dec 28 '24 23:12 twatzl

Can you please explain your case, where it's breaking for you? When do you need to render anything less than the mobile breakpoint?

mvrlin avatar Dec 29 '24 09:12 mvrlin

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 avatar Jan 03 '25 20:01 twatzl

@twatzl Try using maxWidth feature for this. https://github.com/mvrlin/nuxt-viewport?tab=readme-ov-file#feature

mvrlin avatar Jan 04 '25 06:01 mvrlin

Ok. I have to check this when I find some time.

twatzl avatar Jan 13 '25 11:01 twatzl

@twatzl Hey! Do have any updates on that?

mvrlin avatar Aug 27 '25 16:08 mvrlin

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.

twatzl avatar Aug 27 '25 20:08 twatzl