重学 CSS 之 层叠、优先级和继承

简介: 重学 CSS 之 层叠、优先级和继承

层叠

CSS 本质上就是声明规则,即在各种条件下,我们希望产生特定的效果。如果某个元素有这个类,则应用这些样式。要想预测规则最终的效果,就需要理解 CSS 里的层叠。

::: demo [vanilla]

<html>
  <header id="demo0-header">
    <h1 id="demo0-page-title" class="demo0-title">Wombat Coffee Roasters</h1>
    <nav>
      <ul id="demo0-main-nav" class="demo0-nav">
        <li><a href="/">Home</a></li>
        <li><a href="/coffees">Coffees</a></li>
        <li><a href="/brewers">Brewers</a></li>
        <li><a href="/specials" class="demo0-featured">Specials</a></li>
      </ul>
    </nav>
  </header>
</html>
<script>
</script>
<style>
#demo0-header h1 {
  font-family: serif;
}
#demo0-header #demo0-page-title {
  font-family: sans-serif;
}
#demo0-header .demo0-title {
  font-family: monospace;
}
</style>

:::

层叠指的就是一系列规则。它决定了如何解决冲突,是CSS语言的基础。当声明冲突时,层叠会依据三种条件解决冲突:

  1. 样式表的来源:当声明冲突时,层叠会依据三种条件解决冲突。
  2. 选择器优先级:哪些选择器比另一些选择器更重要。
  3. 源码顺序:样式在样式表里的声明顺序。

样式表的来源

  • 作者样式

    • 用于覆盖用户代理的样式
  • 用户代理样式(即浏览器默认样式)

    • 不同浏览器实现有差异
  • !important 声明

    • 标记 !important 会被当做更高优先级的来源

因此,总体优先级由高到低排列:作者的 !important > 作者 > 用户代理。

::: demo [vanilla]

<html>
  <header id="demo1-header">
    <h1 id="demo1-page-title" class="demo1-title">Wombat Coffee Roasters</h1>
    <nav>
      <ul id="demo1-main-nav" class="demo1-nav">
        <li><a href="/">Home</a></li>
        <li><a href="/coffees">Coffees</a></li>
        <li><a href="/brewers">Brewers</a></li>
        <li><a href="/specials" class="demo1-featured">Specials</a></li>
      </ul>
    </nav>
  </header>
</html>
<script>
</script>
<style>
#demo1-header h1 {
  color: #2f4f4f;
  margin-bottom: 10px;
}
#demo1-main-nav {
  margin-top: 10px;
  list-style: none;
  padding-left: 0;
}
#demo1-main-nav li {
  display: inline-block;
}
#demo1-main-nav a {
  color: white;
  background-color: #13a4a4;
  padding: 5px;
  border-radius: 2px;
  text-decoration: none;
}
</style>

:::

理解优先级

浏览器将优先级分为两部分:HTML 的行内样式和选择器样式。

  • 行内样式

    • 用 HTML 的 style 属性写样式,这个声明只会作用于当前元素
    • 行内样式属于“带作用域的”声明,会覆盖任何来自样式表或者 <style> 标签的样式
    • 行内样式没有选择器,直接作用于所在的元素
    • 可以通过 !important 在样式表里覆盖行内声明

::: demo [vanilla]

<html>
  <header id="demo2-header">
    <h1 id="demo2-page-title" class="demo2-title">Wombat Coffee Roasters</h1>
    <nav>
      <ul id="demo2-main-nav" class="demo2-nav">
        <li><a href="/">Home</a></li>
        <li><a href="/coffees">Coffees</a></li>
        <li><a href="/brewers">Brewers</a></li>
        <li><a href="/specials" class="demo2-featured" style="background-color: orange;">Specials</a></li>
      </ul>
    </nav>
  </header>
</html>
<script>
</script>
<style>
#demo2-header h1 {
  color: #2f4f4f;
  margin-bottom: 10px;
}
#demo2-main-nav {
  margin-top: 10px;
  list-style: none;
  padding-left: 0;
}
#demo2-main-nav li {
  display: inline-block;
}
#demo2-main-nav a {
  color: white;
  background-color: #13a4a4;
  padding: 5px;
  border-radius: 2px;
  text-decoration: none;
}
</style>

:::

  • 选择器优先级

    • id 选择器比类选择器优先级高
    • 类选择器比标签选择器高
    • 伪类选择器(如:hover)和属性选择器(如[type="input"])与一个类选择器的优先级相同
    • 通用选择器(*)和组合选择器(>+~)对优先级没有影响
  • 优先级标记
    一个常用的表示优先级的方式是用数值形式来标记。如,1,2,2 表示选择器由 1 个 id、2 个类、2 个标签组成。

源码顺序

如果两个声明的来源和优先级相同,出现晚的(包括在样式表出现较晚或者位于页面较晚引入的样式表中)声明胜出。

最佳实践

  • 在选择器中不要使用 id

    • 当需要覆盖这个选择器时,通常找不到另一个有意义的 id,于是就会复制原来的选择器,然后加上另一个类
  • 不要使用 !important

    • 比 id 更难覆盖,一旦使用,需要覆盖原先的声明,就需要再加上一个 !important,而且依然要处理优先级问题
  • 创建一个用于分发的 JS 模块(如 NPM 包)时,强烈建议不要在 JS 里使用行内样式

    • 否则,使用者要么全盘接受,要么动用 !important 覆盖
    • 正确的做法是在包里包含一个样式表。如果组件要频繁修改样式,可以通过 JS 给元素添加或者删除类来实现。

继承

如果一个元素的某个属性没有层叠值,则可能会继承某个祖先元素的值。继承属性从DOM树的父节点传递到后代节点。

但不是所有的属性都能被继承。默认情况下,只有特定的一些属性能被继承,通常是我们希望被继承的那些。它们主要是跟文本相关的属性:colorfontfont-familyfont-sizefont-weightfont-variantfont-styleline-heightletter-spacingtext-aligntext-indenttext-transformwhite-space 以及 word-spacing

还有一些其他的属性也可以被继承,比如列表属性:list-stylelist-style-typelist-style-position 以及 list-style-image。表格的边框属性border-collapseborder-spacing 也能被继承。

特殊值

  • inherit 关键字

    • 用继承代替一个层叠值。可以用它来覆盖另一个值,这样该元素就会继承其父元素的值。
    • 还可以使用 inherit 关键字强制继承一个通常不会被继承的属性,比如边框和内边距。
  • initial 关键字

    • 撤销作用于某个元素的样式
    • 每一个 CSS 属性都有初始(默认)值。如果将 initial 值赋给某个属性,那么就会有效地将其重置为默认值,这种操作相当于硬复位了该值
相关文章
|
17天前
|
前端开发
CSS层叠性与继承性
CSS层叠性与继承性。
28 2
|
2月前
|
前端开发 JavaScript 算法
CSS【详解】样式选择器的优先级(含提升优先级的方法)
CSS【详解】样式选择器的优先级(含提升优先级的方法)
69 0
CSS【详解】样式选择器的优先级(含提升优先级的方法)
|
2月前
|
前端开发
CSS样式层叠
CSS样式层叠
23 0
CSS样式层叠
|
3月前
|
前端开发 开发者
深入解析CSS样式表的优先级
深入解析CSS样式表的优先级
|
3月前
|
前端开发 开发者
CSS基础-层叠与优先级
【6月更文挑战第10天】本文探讨了CSS中的层叠和优先级概念,解释了层叠上下文和特异性如何决定样式生效。常见问题包括误解后来居上的规则、特异性计算错误及过度使用`!important`。建议开发者理解特异性计算,合理使用层叠上下文,避免不必要的`!important`。通过示例展示了特异性与`!important`对样式的影响,强调实践和理解是提升CSS技能的核心。
27 1
|
3月前
|
前端开发
CSS 选择器优先级详解及实例演示
CSS 选择器优先级详解及实例演示
|
4月前
|
前端开发
CSS优先级:如何解决样式冲突?
CSS优先级:如何解决样式冲突?
|
前端开发 JavaScript 算法
【前端第三课】选择器类型的使用方法;CSS层叠与继承;盒子模型的概念;背景和边框
【前端第三课】选择器类型的使用方法;CSS层叠与继承;盒子模型的概念;背景和边框
【前端第三课】选择器类型的使用方法;CSS层叠与继承;盒子模型的概念;背景和边框
|
前端开发
CSS 中重要的层叠概念
最近在项目的过程中遇到了一个问题,menu-bar希望始终显示在最上面,而在之后的元素都显示在它之下,当时设置了 z-index 也没有效果,不知道什么原因,因此找了一下css有关层叠方面的资料,解决了这个问题,这里记录一下~ 屏幕是一个二维平面,然而HTML元素却是排列在三维坐标系中,x为水平位置,y为垂直位置,z为屏幕由内向外方向的位置,我们在看屏幕的时候是沿着z轴方向从外向内的;由此,元素在用户视角就形成了层叠的关系,某个元素可能覆盖了其他元素也可能被其他元素覆盖;
CSS 中重要的层叠概念
|
Web App开发 前端开发