New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve rounding #715
Improve rounding #715
Conversation
Yeah, line 1243... Perhaps we need to take into account the odd/even width then. When I resize the window using PR code:
When I resize the window always using Math.round():
Can you reproduce that? |
Yes I can repro |
I think this is the pattern:
This still only applies to horizontal placement and the left/right values |
Check the CodePen when the above is taken into account, I can't see jitters anymore |
|
It appears so yes. Horizontally it appears flush with the reference, and you can change the code at the very bottom to However I just noticed that |
Please, let's make sure the behavior is consistent across browsers also. |
This might be getting stranger by the second.. If both are odd width, then we need left: toInteger(bothOddWidth && !isVariation ? popper.left - 1 : popper.left), I'm going to check Firefox and Safari now |
Considering the number of edge cases you are finding I think it would make sense to write some tests to make sure everything is working as expected. |
On Firefox it looks like the element is positioned on a half pixel, no matter what if we use a full pixel then it can't be positioned correctly. My suggestion there would be not to round if the screen is HiDPI (so there won't be blurriness). If you don't round at all, FF appears perfect, same with Safari. Something like |
this thing is getting complex 😅 may we limit this PR to the most basic use case (non HiDPI screens) and think about the HiDPI screens in a new one? |
Yeah it's kinda crazy for something that should be simple.. FWIW here is what it would look like to check for that: const isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
const isVariation = data.placement.indexOf('-') !== -1;
const sameWidthOddness = reference.width % 2 === popper.width % 2;
const bothOddWidth = reference.width % 2 === 1 && popper.width % 2 === 1;
const isHiDPIScreen = window.devicePixelRatio >= 2;
const noRound = v => v;
// We don't need to round if the device has a high pixel density
const horizontalToInteger = isHiDPIScreen
? noRound
: isVertical || isVariation || sameWidthOddness
? Math.round
: Math.floor;
const verticalToInteger = isHiDPIScreen ? noRound : Math.round;
const offsets = {
left: horizontalToInteger(
bothOddWidth && !isVariation && !isHiDPIScreen
? popper.left - 1
: popper.left
),
top: verticalToInteger(popper.top),
bottom: verticalToInteger(popper.bottom),
right: horizontalToInteger(popper.right)
}; And yes I agree it needs tests due to all the logic 😅 Edit: Aand Chrome prefers to be rounded.... 🤣 so it needs:
|
if you add the tests I'll merge it 😜 |
Will try to write some tests in a sec |
fe6fac5
to
08a05a7
Compare
@FezVrasta are the tests appropriate? |
Thanks yes they look solid! |
Fixes #713
It appears that
Math.round()
is always preferred except with placementstop
andbottom
(not a variation) and whereMath.floor()
is preferred (and only on theleft
andright
values)...See the playground: https://codepen.io/anon/pen/Pxjdoo