如何避免媒体查询重叠?

Posted

技术标签:

【中文标题】如何避免媒体查询重叠?【英文标题】:How can I avoid media query overlap? 【发布时间】:2012-11-18 00:44:30 【问题描述】:

级联使 CSS 变得特别而强大。但在媒体查询的情况下,重叠可能似乎有问题。

考虑以下 CSS(继续 rules for CSS media query overlap):

/* Standard - for all screens below 20em */

body  color: black; font-size: 1em; 

/* Query A - slightly wider, mobile viewport */

@media (min-width: 20em) and (max-width: 45em) 
    body  color: red;  /* supposed to be unique for this width */


/* Query B - everything else */

@media (min-width: 45em) 
    body  font-size: larger;  /* because viewport is bigger */

所以当屏幕正好是 45em 宽时,根据标准 CSS 层叠在 45em will be treated 处重叠:

将首先应用所有max-width: 45em 定义, 之后将应用所有min-width: 45em

考虑这两个条件:

所有文本通常都是black,但查询A是唯一的并且具有color: red。 由于 查询 B 用于更大的视口,它的文本具有 CSS font-size: larger

因此,在正好 45em 的宽度上,我们会得到大而红色的文本避免这种情况的最佳解决方案是什么?


我看到了两种可能性:

    查询 B 中重新声明文本以具有 color: black,但是如果您选择在将来更改 color,那么您将管理两个声明。 (当然,这一行代码没有这样的问题,但想象一下还有很多其他的声明和选择器。)

    通过使用像max-width: 799pxmin-width: 800px这样的像素值来避免重叠,但是你使用的是像素——我猜它们可能分别是49.9375em和50em。虽然如果默认值不再是 16em 并且某些东西被四舍五入怎么办?我们是still not certain 在那个间隙发生了什么。 (打破时空连续性的黑洞?)

两者都有各自的缺点......还有其他想法吗?

【问题讨论】:

你分析过度了:你永远不会写出那样的样式。媒体查询通常用于处理相关视口的元素。没有理由选择像 49.9375em 这样的数字作为断点而不是 49.99999em。 @cimmanon,我的意思更多是作为一个侧面(随意忽略奇怪的em 值,只是为了保持问题的一致性——我考虑在@987654335 中写下整个问题@但我更喜欢em) @Baumr--我认为 cimmanon 的观点是你应该使用你的#2 解决方案,但在max-width 上将值设置为49.99999em,这样你就不应该有“差距”处理(就像你可能处理的49.9375em)。 浏览器在计算像素值时会四舍五入,据我所知,50em 仍然适用。 【参考方案1】:

为任何给定的媒体查询创建两个互斥的@media 块的唯一可靠方法是在其中一个块中使用not 来否定它。不幸的是,这意味着对每个@media 块重复一次媒体查询。所以,而不是这个,例如:

@media (max-width: 49.9375em) 
    body 
        color: red;
    


@media (min-width: 50em) 
    body 
        font-size: larger;
    

你会得到这个:

/* 
 * Note: Media Queries 4 still requires 'not' to be followed by a
 * media type (e.g. 'all' or 'screen') for reasons I cannot comprehend.
 */
@media not all and (min-width: 50em) 
    body 
        color: red;
    


@media (min-width: 50em) 
    body 
        font-size: larger;
    

Interactive jsFiddle demo

这对于缩小与widthheight 等范围媒体功能之间的差距非常有效,因为它本质上将这变成了一个非此即彼的场景。但是,就像您的前两个选项一样,它并不完美:如前所述,您必须重复两次相同的媒体查询,并将not 添加到其中一个。 @media 没有 if/else 构造,如 Conditional Rules 3 中所述。


虽然我在回答您之前的问题时提到了这一点:

从我的实验来看,ios 上的 Safari 似乎会对所有小数像素值进行四舍五入,以确保 max-width: 799pxmin-width: 800px 中的任何一个都匹配,即使视口确实是 799.5 像素(显然与前者匹配)。

仍然应该指出,在舍入时我注意到了一些怪癖。也就是说,我还没有找到一个可以规避 both 媒体查询并最终无法从任何一组规则中接收样式的小数值(顺便说一句,这是最糟糕的发生,所以不要担心可能会造成时空裂痕)。这一定意味着浏览器——至少,我测试过的 Safari——会做一个合理的工作来确保它们满足媒体查询,即使你的值不同(正好 1 个 CSS 像素)。

当涉及到可以在桌面浏览器上观察到的具有较大间隙的单位时,例如 ems,误差范围要大得多。例如,一条评论建议使用 49.99999em 而不是比 49.9375em 更随意的东西,但显然存在差异,至少默认字体大小为 16px。

我简化了您的代码,将媒体查询更改为使用十进制值,并将代码放入 jsFiddle:

@media (max-width: 49.9375em) 
    body 
        color: red;
    


@media (min-width: 50em) 
    body 
        font-size: larger;
    

如果您将“结果”窗格的大小调整为 800 像素(文本将更新以指导您),您实际上最终会得到不同的结果,具体取决于是 @media (max-width: 49.9375em) is used 还是 @media (max-width: 49.99999em) is used(我也对此感到惊讶) ...

无论哪种方式,您都是对的:选项 2 也有其缺点。老实说,我并不是特别喜欢它,因为我不想在我无法控制的设备和用户代理怪癖上大发雷霆。如果您像我一样,我想最好还是以对您的代码更加警惕为代价(?)来重新声明您的规则的不便,因为这至少仍在您作为作者的控制范围内。

【讨论】:

谢谢!在您的第一段中,我是否理解正确:做我在问题中所做的事情应该没问题?只是为了澄清。此外,毫无疑问,您对重新声明规则的建议是简单情况下的一种选择,但如果这些查询变得更加复杂,那么对于大型网站(目前不是我的情况)可能会出现问题。我开始觉得这是min-widthmax-width 在媒体查询中使用的限制。或许像 below-widthabove-width 这样的声明可能对有用——允许选择高于某个特定值的所有值,除了它。 @Baumr:您对below-widthabove-width 的建议给了我一个想法,但我不确定它是否符合您的要求。完成后查看编辑。 哇,真是个好答案!我正在考虑创建另一个帐户并再次对其进行投票;D 谢谢博尔特! @Baumr:暂停这样的事情会非常尴尬 :) 你总是可以奖励赏金! 有关于这个话题的消息吗?浏览器是否开始在缩放方面以相同的方式处理 px 和 em 媒体查询?是否找到了重叠问题的解决方案?谢谢!【参考方案2】:

对我来说,最好的办法是保持0.01em的差距:

@media (min-width: 20em) and (max-width: 44.99em) 
    body  color: red;  /* supposed to be unique for this width */

@media (min-width: 45em) 
    body  font-size: larger;  /* because viewport is bigger */

我建议您阅读这篇文章以了解详细信息以及different solutions to prevent media query overlapping的比较。

干杯, 托马斯。

【讨论】:

以上是关于如何避免媒体查询重叠?的主要内容,如果未能解决你的问题,请参考以下文章

Styled Components - 内联样式与媒体查询样式重叠

CSS 媒体查询 - 对重叠和顺序感到困惑

如何以 90% 的页面缩放级别编写媒体查询

如何将 CSS 媒体查询应用于视频海报?

我可以在内部 CSS 中使用媒体查询,它会避免加载我定义的背景图像吗?

如何使用媒体查询或运算符使 SASS 嵌套嵌套媒体查询工作