There isn't a good way to make two px-based @media
rules mutually exclusive with no gap without repeating the same media query twice and using the not
keyword — which isn't very readable much less DRY — and the <
and >
syntax new to Media Queries 4 isn't widely supported yet. As you've seen in my answer to the linked question, a viewport that is (in this example) exactly 576px wide will match both max-width: 576px
and min-width: 576px
simultaneously, which can cause issues (some cascading some not) as properties from both rules will be applied. Most authors therefore choose to have min- and max- constraints with a difference of 1 pixel, or less if they're worried about high-resolution displays with non-integer pixel densities that don't scale every CSS pixel to full device pixels (e.g. 1.5).
Indeed, cross-browser compatibility is the reason: according to Bootstrap's source, 0.02px is used "rather than 0.01px to work around a current rounding bug in Safari. See https://bugs.webkit.org/show_bug.cgi?id=178261" (that, predictably, as of July 2018 still hasn't been fixed). Starting from line 31 of _breakpoints.scss:
// Maximum breakpoint width. Null for the largest (last) breakpoint.
// The maximum value is calculated as the minimum of the next one less 0.02px
// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.
// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max
// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
// See https://bugs.webkit.org/show_bug.cgi?id=178261
//
// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 767.98px
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
$next: breakpoint-next($name, $breakpoints);
@return if($next, breakpoint-min($next, $breakpoints) - .02px, null);
}