Subpixel Rendering and Media Query Boundaries
Reported by
jmsig...@gmail.com,
Feb 6 2017
|
|||||||||
Issue description
UserAgent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Steps to reproduce the problem:
When using CSS media queries that have boundaries differing by a pixel, it's possible to render between these breakpoints due to subpixel rendering usually encountered when zooming the browser.
Steps to reproduce are roughly,
1. Create a site that utilizes CSS media queries that have breakpoints differing by a single pixel. As a crude example,
@media (min-width: 0) and (max-width: 1279) {
.hide {
display: none;
}
}
@media (min-width: 1280) {
.hide {
display: none;
}
}
2. Resize the browser to a width of 1024px.
3. Zoom out to 80%.
Issue illustrated on codepen with angular-material CSS here,
http://codepen.io/jvmccarthy/pen/oBMjQL
and without angular-material here,
http://codepen.io/jvmccarthy/pen/zNLqOz
What is the expected behavior?
The browser should reasonably round the calculated width when rendering or should at least consistently report the width in window.innerWidth.
What went wrong?
The browser renders CSS at the subpixel level between the two media queries. In the case of angular-material (and bootstrap), this causes elements to be shown that should be hidden.
In this case, the calculated width comes out to 1279.999980926514px, which is so close to 1280px that a meaningful CSS breakpoint at the subpixel level would have to be max-width: 1279.99999px, which doesn't seem practical.
Also, the browser reports the window.innerWidth at 1280, so there is no simple way to detect the discrepancy between the rendered CSS width and the width reported in JavaScript.
Did this work before? N/A
Chrome version: 56.0.2924.87 Channel: stable
OS Version: 10.0
Flash Version: Shockwave Flash 24.0 r0
An issue was filed in twbs/bootstrap about this (https://github.com/twbs/bootstrap/issues/21552). As linked in this issue, a corresponding issue has been field in w3c/csswg-drafts (https://github.com/w3c/csswg-drafts/issues/984) to address the media query endpoints. Perhaps this issue cannot be resolved until the W3C handles this topic. However, I am unable to reproduce this issue in Firefox and the discrepancy between the reported width and rendered width as well as the current required workarounds is cause for concern.
Also, I don't understand the complexity involved in devicePixelRatio calculations and would greatly appreciate some pointers on the topic. In particular, why is a zoom of 80% calculated to be devicePixelRatio=0.800000011920929 on a 1920x1080 display? Why not just 0.8? The amount of significant digits is intriguing.
Thank you for the time and consideration.
,
Feb 8 2017
,
Feb 8 2017
****Bulk Edit**** Setting as P1 for test team to prioritize in triaging.
,
Feb 9 2017
Not quite sure what the right solution is here, rounding to the nearest pixel isn't great as that would break min-width: 12.5px and similar but perhaps that is the best we can do? In that case using the pixel snapped values for media queries would make sense. Another option would be to round to the nearest LayouUnit. That would round 1279.999980926514 to 1280 while still allowing subpixel queries. Over to CSS team for triage.
,
Feb 12 2017
Rounding to the nearest LayoutUnit sounds reasonable. It would be good to confirm what other browsers do in this case for predictability.
,
Feb 13 2017
,
Feb 22 2017
We've also run into this problem. I've reproduced on OSX with a different constraint: media queries between 639px and 640px at 80% zoom. Test page URL: https://sigusrone.com/misc/crbug-689096.html Screenshot showing different behavior between Chrome (Version 56.0.2924.87 (64-bit)) and consistent behavior between Firefox (50.1.0) and Safari (10.0.3 (11602.4.8.0.1)): https://sigusrone.com/misc/crbug-689096.png It appears that Firefox and Safari show the same behavior of rounding to the nearest px unit to calculate media query width.
,
May 29 2017
Adding support for Media Query Level 4 syntax would give a solution to this problem.
This has a (problematic) gap:
@media (max-width: 1279) {}
@media (min-width: 1280) {}
This does not:
@media (width < 1280) {}
@media (width >= 1280) {}
https://www.w3.org/TR/2017/WD-mediaqueries-4-20170519/#mq-range-context
,
Nov 27 2017
Rounding to nearest pixel seems approachable, but implementing that part of Media Query Level 4 might be more difficult.
,
Dec 6 2017
,
Jan 2 2018
Issue 798119 has been merged into this issue.
,
Jan 23 2018
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/6208e4e123e2fd293bf9fd221aaa136c34a5f4e9 commit 6208e4e123e2fd293bf9fd221aaa136c34a5f4e9 Author: Chris Nardi <hichris123@gmail.com> Date: Tue Jan 23 19:17:14 2018 Use LayoutUnit::Epsilon as the precision of media query lengths After zooming, the calculated length of a value can sometimes be less than or equal to a LayoutUnit away from the true value. Because of this, a page can sometimes be in between two precise values of a media query. Use LayoutUnit::Epsilon to avoid this issue. Bug: 689096 Change-Id: Ibce686fb10e2dd0eaca142fadd65331ebe7b35a1 Reviewed-on: https://chromium-review.googlesource.com/879235 Reviewed-by: Emil A Eklund <eae@chromium.org> Commit-Queue: Emil A Eklund <eae@chromium.org> Cr-Commit-Position: refs/heads/master@{#531296} [modify] https://crrev.com/6208e4e123e2fd293bf9fd221aaa136c34a5f4e9/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp [modify] https://crrev.com/6208e4e123e2fd293bf9fd221aaa136c34a5f4e9/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
,
Jan 25 2018
Marking this as fixed. Media queries should no longer be able to be in this state, and I can only reproduce devicePixelRatio having a large number of significant digits on zoom levels of 66% and 33%. If this can be reproduced on non-repeating zoom levels, a new bug should be filed for that. |
|||||||||
►
Sign in to add a comment |
|||||||||
Comment 1 by nyerramilli@chromium.org
, Feb 7 2017