如果媒体查询不影响特异性,那么为什么样式会在放置在顶部时生效?

huangapple go评论70阅读模式
英文:

If media queries do not affect specificity, how come the style is being applied even when placed on top

问题

我期望颜色是红色。然而,实际上是蓝色,我对此没有解释。在Chrome上测试过。在其他浏览器中颜色是红色。

英文:

With this style

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

div {
  @media (min-width: 0px) {
     color: blue;
  }
  color: red;
}

<!-- language: lang-html -->

&lt;div&gt;
hello
&lt;/div&gt;

<!-- end snippet -->

I expect the color to be red. However, it's actually blue and I have no explanation for this. Tested on Chrome. The color is red in other browsers.

答案1

得分: 1

以下是翻译好的内容:

这是因为嵌套的@rule实际上展开为:

@rule {
  & {
    /* ... */
  }
}

这在规范的这一段中有解释,甚至包含了指出这种情况的示例

.foo {
  display: grid;

  @media (orientation: landscape) {
    grid-auto-flow: column;
  }
}
/* 等效于
   .foo {
     display: grid;

     @media (orientation: landscape) {
       & {
         grid-auto-flow: column;
       }
     }
   }
*/

如果我们将&选择器添加到color: red规则中,我们将得到相同的特异性:

div {
  @media (min-width: 0px) {
    color: blue;
  }
  & { color: red; }
}

请注意,您的代码目前在非Chromium浏览器中会产生红色输出,因为它们仍不支持CSS嵌套,所以它们只会将这里的@media规则视为无效规则,并继续解析div规则。如果要支持所有浏览器,您必须手动展开这些规则:

@media (min-width: 0px) {
  div { color: blue; }
}
div {
  color: red;
}
英文:

This is because the nested @rule actually unwraps to

@rule {
  &amp; {
    /* ... */
  }
}

This is explained in this paragraph of the specs, which even contains an example pointing out this case:

> css
&gt; .foo {
&gt; display: grid;
&gt;
&gt; @media (orientation: landscape) {
&gt; grid-auto-flow: column;
&gt; }
&gt; }
&gt; /* equivalent to
&gt; .foo {
&gt; display: grid;
&gt;
&gt; @media (orientation: landscape) {
&gt; &amp; {
&gt; grid-auto-flow: column;
&gt; }
&gt; }
&gt; }
&gt; */
&gt;

And if we do add the &amp; selector to the color: red rule, we get the same specificity:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

div {
  @media (min-width: 0px) {
     color: blue;
  }
  &amp; { color: red; }
}

<!-- language: lang-html -->

&lt;div&gt;
hello
&lt;/div&gt;

<!-- end snippet -->

And note that your code currently produces a red output in non Chromium browsers because they still don't support CSS nesting, so they just treat the @media rule here as an invalid rule and go on to parse the div one.
If you want to support all browsers, you have to manually unwrap these rules:

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-css -->

@media (min-width: 0px) {
  div { color: blue; }
}
div {
  color: red;
}

<!-- language: lang-html -->

&lt;div&gt;
hello&lt;!-- will be red everywhere --&gt;
&lt;/div&gt;

<!-- end snippet -->

答案2

得分: 1

我将使用另一个示例来说明您的问题:

<!-- 开始代码片段: js 隐藏: false 控制台: true Babel: false -->

<!-- 语言: lang-css -->
div {
  & {
    color: blue;
  }
  color: red;
}

<!-- 语言: lang-html -->
<div>
  hello
</div>

<!-- 结束代码片段 -->

我们混合了“嵌套规则”和“声明”,规范定义了这种行为,将“嵌套规则”移动到最后。因此,浏览器会将您的代码更改为以下形式:

<!-- 开始代码片段: js 隐藏: false 控制台: true Babel: false -->

<!-- 语言: lang-css -->
div {
  color: red;
  & {
    color: blue;
  }
}

<!-- 语言: lang-html -->
<div>
  hello
</div>

<!-- 结束代码片段 -->

然后变成这样:

<!-- 开始代码片段: js 隐藏: false 控制台: true Babel: false -->

<!-- 语言: lang-css -->
div {
  color: red;
}

div {
  color: blue;
}

<!-- 语言: lang-html -->
<div>
  hello
</div>

<!-- 结束代码片段 -->

所以,始终从“声明”开始,然后是“嵌套规则”。

英文:

I will use another example to illustrate your issue:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

div {
  &amp; {
    color: blue;
  }
  color: red;
}

<!-- language: lang-html -->

&lt;div&gt;
hello
&lt;/div&gt;

<!-- end snippet -->

We are mixing "nested rules" and "declarations" and the Specification defines such behavior by moving the "nested rules" at the end.

So the browser will change your code to this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

div {
  color: red;
  &amp; {
    color: blue;
  }
}

<!-- language: lang-html -->

&lt;div&gt;
hello
&lt;/div&gt;

<!-- end snippet -->

And then to this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

div {
  color: red;
}

div {
  color: blue;
}

<!-- language: lang-html -->

&lt;div&gt;
hello
&lt;/div&gt;

<!-- end snippet -->

So always start with the "declarations" then the "nested rules"

huangapple
  • 本文由 发表于 2023年6月8日 17:17:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76430337.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定