【问题标题】:Media queries running weird because of non-integer width由于非整数宽度,媒体查询运行异常
【发布时间】:2017-05-17 21:32:15
【问题描述】:

不能说这是一个真正的问题还是我只是偏执,但媒体查询的这种行为真的让我在过去的几个小时里发疯了。

让我们考虑一下这个非常简单的 CSS。

 body {background:yellow}

 @media (max-width:399px) {
   body {background:red}
 }

 @media (min-width:400px) {
   body {background:blue}
 }

当宽度为 399.333px 时会出现问题!(或任何介于 399 和 400 整数之间的浮点值)

我的逻辑是,使用这种 CSS 样式页面永远不会变黄,对吧?当视口大小小于 400px 宽度时它应该是红色的,当它大于 400px 时它应该是蓝色的。

当页面放大时,Windows 上的 Opera 浏览器(我目前使用的是 36.0)会发生奇怪的行为。我知道视口宽度是使用实际视口宽度和当前缩放级别计算的,此值应始终为整数。但是……

看起来 Opera 不会对影响整个页面的值进行舍入/下限/上限。当 Opera 发现 viewport-width 不是 399px 或 400px 但 它是 399.333px 时,我得到黄色背景!?所以没有一个媒体查询满足条件。

我已经尝试在这里和网络范围内找到答案,但没有什么能解决这个问题。当我使用em 单位时,这个问题已经发生在我身上,所以我可以解决并将它们转换为像素,但我不能影响用户对使用浏览器缩放功能的决定。

我能做些什么来防止这种情况发生吗?

模拟这种行为的最简单方法是点击CTRL,+ 三次,而不是在对象检查器中轻松移动垂直滑块。

更新:

是的,我可以通过将每个媒体断点链接到前一个断点来使用“移动/桌面优先”的方法来修复它,但这不是我的问题的一部分。此外,默认的body 样式在这里仅作为视觉辅助,更改并不能真正解决问题。

【问题讨论】:

  • 确保不会出现这种情况的一种方法是简单地设计移动优先(首先声明小屏幕的样式,然后在下面将更宽屏幕的样式放在一系列递增的@ 987654325@ 查询)或桌面优先(反之:从最宽屏幕的样式开始,然后在其下方一系列递减的@media (max-width... 查询)。
  • 这个问题有实际应用吗?您可以删除background:yellow,并将background:red 置于其媒体查询之外。
  • @MrLister 是的,我正在使用这种方法,但是对于每个断点都有很多 css 需要以这种方式重写,所以我的想法是在范围级别上编写整个 css 以改进表演。这当然是 B 计划。为什么 Opera 不舍入这个值真的让我很生气。
  • 移动/桌面优先是当前开发实践中的最佳实践。这是避免此问题的唯一方法。
  • @zsawaf 请您用一些相关来源备份您的声明。我只需要 100% 确定这一点,并且在 Opera 的文档中找不到任何内容。也许我错过了什么。

标签: css media-queries zooming


【解决方案1】:

一个简单的解决方案可能如下:

 body {background:yellow}

 @media (max-width:400px) {
   body {background:red}
 }

 @media (min-width:400px) {
   body {background:blue}
 }

最后一个媒体查询中的规则将简单地覆盖之前存在的任何参数,只是因为顺序。

这样就不会有这两个媒体查询未涵盖的情况/宽度:399.9999以下的所有内容...(无论如何)都满足第一个条件,400以上的所有内容都将满足第二个条件,并且如果宽度恰好为 400,则第二个媒体查询中的规则将根据其顺序覆盖之前的规则。

【讨论】:

    【解决方案2】:

    类似的布局

    这个问题的答案应该是完全避免这个问题,简单地将其中一个媒体查询排除在外,让一个媒体查询覆盖另一个:

    body {background: red;}
    
    @media (min-width: 400px)
    {
        body {background: blue;}
    }
    

    但是,当您需要一个完全不同的布局时,这将导致大量额外的代码简单地从另一个案例中重置一个案例。如下例所示:

    .some-element {background-color: red;border-left: 30px;}
    
    @media (max-width: 399px)
    {
        .some-element {border-left: none;padding-bottom: 40px;}
    }
    

    而写起来会更短更优雅:

    .some-element {background-color: red;}
    
    @media (min-width: 400px)
    {
        .some-element {border-left: 30px;}
    }
    
    @media (max-width: 399px)
    {
        .some-element {padding-bottom: 40px;}
    }
    

    但如果宽度为399.5px,则最后一个示例代码中的任何媒体查询都不会生效。如果您仍然希望编写具有完美覆盖率的此类代码,请阅读此答案的下一部分。

    使用浮点数

    不幸的是,对于 min-width 和 max-width 值的媒体查询总是包含在内。浏览器在具有缩放功能时使用分数像素。因此,此问题的一个简单解决方案是将阈值像素值400px 以尽可能低的分数递增,例如400.00001px。然而,关键问题仍然存在,最低的分数是多少?

    The CSS specification 没有说明使用哪些数据类型来存储数字:

    <number> 可以是 <integer>,也可以是零个或多个数字,后跟一个点 (.),后跟一个或多个数字。

    但是根据'Why does Bootstrap use a 0.02px difference between screen size thresholds in its media queries?'的回答:

    确实,跨浏览器兼容性是原因:根据 Bootstrap 的消息来源,“使用 0.02px 而不是 0.01px 来解决 Safari 中当前的舍入错误。

    显然,bootstrap 是一个广泛使用的框架,在这种特定情况下使用 0.02 似乎是正确的值。

    在您的情况下,为了完美覆盖您的媒体查询 - 从而防止黄色背景,解决方案如下所示:

    body {background: yellow;}
    
    @media (max-width:400px) {
        body {background: red;}
    }
    
    @media (min-width:400.02px) {
        body {background: blue;}
    }
    

    使用 CSS4

    从 CSS4 开始,您可以对媒体查询使用直观的运算符,例如 >=<=,而不是 min-max-,更重要的是,您还可以使用排他运算符,例如 > 和 @ 987654341@立即解决问题(see here)。

    但是,它可能不会被广泛支持。不幸的是,this feature is not yet on Can I Use 检查浏览器支持。您可以使用this codepen 自行检查。它似乎可以在最新版本的 Firefox 中使用。

    那么解决方案就很简单了:

    body {background: yellow;}
    
    @media (width <= 400px) {
        body {background: red;}
    }
    
    @media (width > 400px) {
        body {background: blue;}
    }
    

    【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2021-12-11
    • 1970-01-01
    • 2012-05-05
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2011-12-30
    相关资源
    最近更新 更多