【问题标题】:Are all CSS rules allowed on all HTML elements and can they all be inherited?是否所有 HTML 元素都允许所有 CSS 规则,它们都可以被继承吗?
【发布时间】:2020-07-07 15:53:55
【问题描述】:

鉴于某些 CSS 规则是针对特定 HTML 元素量身定制的(一些示例 - object-fit 用于 <img><video> 等;strokefill 和其他各种 SVG 元素的 SVG 规则)和在其他元素上使用时不太有意义:

  1. 将任何有效 CSS 规则应用于任何 HTML 元素是否合法?
  2. 可以继承任何规则吗?
  3. 什么是继承值,尤其是在继承自使用特定属性没有意义的元素的情况下?

我的具体问题是这个。我正在开发一个带有模块化 CSS 的按钮组件。在这个按钮内,我可能有一个用于显示图标的 SVG 元素。我希望能够从组件外部将某些样式应用于图标(即笔划和填充),同时保持适当的封装(所以深度选择器是不行的)。

为了解决这个问题,我将 SVG 设置为从按钮继承描边和填充。如果我现在将这些属性应用到按钮,图标会继承它们并且我会得到想要的结果!

但是,这让我想知道我所做的是否有效以及其他浏览器的行为是否相同。

这似乎是常识,但很难找到明确的答案。如果有人可以向我指出规范的摘录,甚至可能指向一些支持表,我会很高兴!


考虑到我编写代码的方式,显示一个 100% 准确的示例有点过分,但基本上我是在问这是否有效:

.icon {
  stroke: inherit;
  fill: inherit;
}

.button {
  stroke: #FFF;
  fill: #999;
}
<button class="button">
  <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
    <g stroke-width="2" transform="translate(1 1)">
      <path d="M14 2L2 14"/>
      <circle cx="8" cy="8" r="8"/>
    </g>
  </svg>
  <span>My button</span>
</button>

【问题讨论】:

    标签: html css specifications


    【解决方案1】:

    将任何有效的 CSS 规则应用于任何 HTML 元素仍然合法吗?

    是的,但如果它不受支持或不适用于此类元素,它可能会被您的浏览器忽略。

    此外,任何规则都可以继承吗?

    是的,但您应该注意,继承会考虑计算值,这会有所不同:

    inherit CSS 关键字导致指定它的元素从其父元素获取属性的计算值。它可以应用于任何 CSS 属性,包括 CSS 速记 all。 ref

    我没有与 SVG 相关的简单示例,但这里有另一个示例:

    .box {
      display:inline-block;
      float:left;
      width:200px;
      height:200px;
      border:1px solid red;
    }
    
    .box > div {
      display:inherit;
      border:1px solid green;
    }
    <div class="box">
      <div>text</div>
    </div>

    注意内部 div 的 display 将如何等于 block 而不是 inline-block 因为 float 会强制 display 的计算值被 .box 阻塞

    为避免处理继承问题,您可以考虑针对您的情况使用 CSS 变量:

    .icon {
      stroke: var(--s);
      fill: var(--f);
    }
    
    .button {
      --s: #FFF;
      --f: #999;
    }
    <button class="button">
      <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
        <g stroke-width="2" transform="translate(1 1)">
          <path d="M14 2L2 14"/>
          <circle cx="8" cy="8" r="8"/>
        </g>
      </svg>
      <span>My button</span>
    </button>

    【讨论】:

      【解决方案2】:

      Temani 的回答非常有帮助,并为我指明了正确的方向。经过一番研究后,我想我现在可以针对我自己的问题发布一个更详尽且参考正确的答案。

      将任何有效的 CSS 规则应用于任何 HTML 元素是否合法?

      是的,是的。这在 CSS2.1 规范中非常清楚地说明:https://www.w3.org/TR/CSS2/about.html#applies-to(CSS3 是 CSS2.1 的基于模块的向后兼容扩展,因此仍然适用)。它说:

      所有元素都被认为具有所有属性,但某些属性对某些类型的元素没有渲染效果。例如,“clear”属性只影响块级元素。

      所有元素都被认为具有所有属性隐式意味着可以在任何元素上设置任何属性。

      某些属性对某些元素没有渲染效果表示某些元素在渲染时只是忽略某些属性(这并不意味着它们不能被继承,请继续阅读)。

      可以继承任何规则吗?

      要回答这个问题,让我们看一下 CSS 值和单位模块第 3 级规范:https://www.w3.org/TR/css3-values/#common-keywords。它指出:

      所有 CSS 属性也接受 CSS 范围的关键字值作为其属性值的唯一组成部分。

      共有三个 CSS 范围的关键字值:initialinheritunset

      规范本质上是说任何属性都可以使用inherit 作为其值,因此问题的答案是。然而,重要的细节是如何确定继承值。正如 Temani 已经指出的那样,这并不像看起来那么简单。

      如何计算继承值?

      CSS Cascading and Inheritance Level 3 spec:https://www.w3.org/TR/css-cascade-3/ 是关于级联和继承的重要读物。它指出:

      元素属性的继承值是元素父元素属性的计算值。

      根据规范,这是我为任何元素上的任何属性确定计算值的过程的简化版本:

      1. 为元素上的属性收集所有声明的值 - 即在开发人员样式表和样式属性、用户代理样式表等中找到的所有相关且有效的 CSS 声明。

      2. 确定级联值 - 所有声明值的获胜值(这是优先考虑规则并且单个规则排在首位的地方)。

      3. 如果没有级联值,如果属性是继承的,则使用继承的值

      4. 如果该属性未被继承(有关默认继承的属性列表,请参阅此问题:Which CSS properties are inherited?),请使用初始值。根据规范,每个属性都有一个初始值(例如,初始font-sizemedium;值得注意的是它不是像16px 那样的绝对值!)。

      5. 此时,一个属性具有分配给它的一些值,但它可能是相对的值,即取决于其他一些 CSS 属性(例如,百分比值取决于某些绝对值,例如父级的绝对尺寸)。在此步骤中,将尽可能解析一个值,使其明确且准备好继承

        重要的是要注意,就像规范为每个属性定义了一个初始值,它还定义了如何导出计算值。例如。 MDN 为字体大小指定了这个计算值:

      按照规定,但将相对长度转换为绝对长度

      所以medium 仍然是medium,但是1.2em 变成了,比如说19.2px(如果父级的字体大小是16px)。

      重要的一点

      相同的级联和继承规范指出:

      即使属性不适用(如“适用于”行所定义),计算值仍然存在。但是,某些属性可能会根据属性是否应用于元素来更改它们确定计算值的方式。

      所以每个元素对于每个属性都会有一个计算值,但可能不会使用它(所谓的used value,即是计算值之后的下一步,是无)。计算出来的值就是要继承的。

      这对我的 SVG 按钮示例意味着什么:

      1. 我绝对可以在&lt;button&gt; 上设置strokefill。它会在呈现自身时忽略此属性,但如果需要,会将其传递给其子级。
      2. 子 SVG默认会继承这些属性(我什至不需要明确指定)。
      3. strokefill 的计算值没有任何警告,因此我可以预期会继承正确的颜色(确实如此!)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-10
        • 2011-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多