理解CSS层叠与选择器:打造高效网页样式的钥匙

32 阅读6分钟

CSS 底层基础解析

何为CSS?

CSS,全称Cascading Style Sheets(层叠样式表),是用于描述HTML或XML文档外观的一种样式表语言。它通过一系列的规则集(Ruleset)来定义网页元素的样式。一个典型的规则集由两部分组成:选择器(Selector)和声明块(Declaration Block)。选择器用来指定要应用样式的HTML元素,而声明块则包含了具体如何改变这些元素样式的属性和值。

   /* css rules */
   /* 规则集Ruleset */
   h1 { /* 选择器 */
        color: red;/* 声明 */
        text-align: center;/* 声明 */
   }

在这个例子中,h1 是选择器,表示所有 <h1> 元素将被这个规则集所影响;colortext-align 则是声明,它们分别设置了文本颜色和对齐方式。

CSS为什么叫“层叠”样式表?

渲染过程

整个渲染过程大致如下:

  1. 下载样式:浏览器从服务器获取所有必要的CSS文件。
    dom + css = rander tree(显示页面 数据结构) 渲染树
  2. 解析DOM:同时,浏览器解析HTML代码,构建出DOM树。
  3. 构造渲染树:一旦样式和DOM准备就绪,浏览器就会结合两者创建渲染树。在这个阶段,非显示元素(如<script>标签或带有display: none;样式的元素)不会被加入到渲染树中。
  4. 布局计算:接下来,浏览器根据渲染树中的信息计算每个元素的位置和尺寸。
  5. 绘制页面:最后一步是绘制,浏览器将渲染树转化为屏幕上的像素,完成页面的实际显示。

css——style示例:

 <style>
        /* css_Ruleset */
        /* 1分 */
        p{
            /* important权重值最高 */
            color:blue !important;
        }
        /* 101分 */
        .container p {
            color:red;
        }
        /* 11分 */
        #main p{
            color:green;
        }
        /* 111分 */
        #main.container p{
            color:yellow;
        }
        /* 
           标签优先级为1
           class 优先级为10
           id 优先级为100 
           important 优先级为无穷大
           权重值相等 就近原则
        */
    </style>

查找相应标签的css样式大致流程如下:

image.png

样式引入方式

CSS可以通过以下几种方式引入到HTML文档中:

  • 内联样式:直接在HTML标签内使用style属性定义样式。
  • 外联样式:通过<link>标签链接外部样式表文件。
  • @import:在样式表内部导入其他样式表,注意这种方式可能会影响加载性能。
  • 行内样式:与内联样式类似,但在某些情况下,它指的是在JavaScript中动态设置元素的样式属性。

优先级机制

CSS有一套严格的优先级计算规则,用于决定当多个规则应用于同一元素时哪一个应该生效。优先级从低到高排列如下:

  • 标签选择器:1分
  • 类选择器:10分
  • ID选择器:100分
  • 行内样式:1000分
  • !important:强制最高优先级,10000分

如果选择器组合变得复杂,优先级会相应地累加。例如,.container ul li:nth-child(odd) 这个选择器总共有22分的优先级(类选择器10分 + 标签选择器2分 + 伪类选择器10分)。
这里需要注意的是选择器都是选择最后的元素,在这里是 li"

CSS选择器分类

CSS选择器大致可以分为几大类:

  • 基础选择器

    • 标签选择器:匹配特定类型的HTML标签。
    • 类选择器:匹配拥有特定类名的元素。
    • ID选择器:匹配具有唯一ID属性的元素。
    • 通配选择器:匹配所有元素,但不推荐频繁使用,因为它可能会导致性能问题。
  • 组合选择器

    • 后代选择器:通过空格分隔两个选择器,表示后者是前者的后代。
    • 子选择器:使用>符号,表示后者是前者的直接子元素。
    • 相邻兄弟选择器:使用+符号,表示后者紧跟在前者之后。
    • 普通兄弟选择器:使用~符号,表示两者同级但不必紧邻。 示例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>选择器</title>
  <style>
    /* 相邻兄弟选择器 h1下面的那个p */
    h1 + p{ 
        color: red;
    }
    /* 通用兄弟选择器 */
    h1 ~ p{
      color: blue;
    }
    /* 后代选择器 */
   .container p{
      color: green;
    }
    /* 直接子元素选择器 */
   .container > p{
      color: pink;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>标题</h1>
    <p>这是第一段文字</p>
    <p>这是第二段文字</p>
    <span>这是一个span元素</span>
    <div class="inner">
      <p>这是一个内部的段落</p>
    </div>
  </div>
</body>
</html>

效果图:

image.png
需要注意的是,这里的.container p.container > p优先级是一样的,所以后面的会覆盖上面的样式。

 /* 后代选择器 */
.container p{
      color: green;
    }
/* 直接子元素选择器 */
.container > p{
      color: pink;
    }
  • 伪类选择器

    • 动态伪类:例如:active:hover:focus,::selection等,用于匹配处于特定状态下的元素。
    • 结构性伪类:如:first-child:nth-child(),nth-of-type()等,基于元素在其父元素中的位置进行选择。

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>伪类选择器示例</title>
    <style>
        /* 伪类选择不同的 */
        button:active{
            background-color: red;
            color: white;
        }
        /* 鼠标覆盖 */
        p:hover{
            background-color: yellow;
        }
        /* ::选中文字 */
        ::selection{ 
            background-color: blue;
            /* 背景颜色 */
            color: white; 
            /* 字体颜色 */
        }
        /* focus是一个伪类选择器,用于选择当前具有焦点的元素。 */
        input:focus{
            border:5px solid blue;
        }
        input:checked + label{
            color: blue;
        }
        li:nth-child(odd){ 
            background-color: silver;
        } 
        /* 除了最后一个 */
        li:not(:last-child){ 
            border-bottom: 1px solid red;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>伪类选择器示例</h1>
        <button>点击我</button>
        <p>鼠标悬浮在这里</p>
        <input type="text" placeholder="输入框">
        <input type="checkbox" id="option1">
        <label for="option1">选项1</label>
        <input type="checkbox" id="option2" checked>
        <label for="option2">选项2</label>
        <ul>
          <li>列表项1</li>
          <li>列表项2</li>
          <li>列表项3</li>
          <li>列表项4</li>
        </ul>
      </div>
</body>
</html>

效果展示:

image.png button:active:

image.png

p:hover:

image.png

::selection:

image.png

input:focus 和 input:checked + label:

image.png

li:nth-child(odd) 和 li:not(:last-child):

image.png

注意哦!在结构性伪类中,nth-child()nth-of-type()是有区别的 这里将给出讲解。 示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /*p:nth-child顺序选择 选择子元素,且要满足是p标签,否则不会显示 */
        .container p:nth-child(3){
            background-color: yellow;
            color: black;
        }
        /*p:of-type根据选择子元素(p)的类型来选择该元素 */
        .container p:nth-of-type(3){
            background-color: lightblue;
            color: black;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>nt-child vs nth-of-type 例子</h1>
        <p>这是第一个段落</p>
        <div>这是一个div</div>
        <p>这是第二段落</p>
        <p>这是第三段落</p>
        <div>这是第二个div</div>
    </div>
</body>
</html>

效果如下:

image.png

  • 这里为什么没有显现 p:nth-child(3)里面的属性呢,是因为在.container容器里面的第三个元素是div,而不是p所以不满足查找需求,不显示。
    • 这里如果把p:nth-child(3)替换成div:nth-child(3)或者把p去掉可以显示效果,因为第三个元素是div,而去掉p那就无论是哪个元素都显示效果。
  • 反之这里的p:nth-of-type(3)显示是因为在.container容器里面存在三个p元素类型标签,所以就显示了效果。
    • 那我们会想如果把p去掉,是不是就显示第三个.container容器里面所有的元素。这里博主试过了显然显示效果没变。为什么?因为把p去掉后,选择器会查找里面所有类型的第三的元素,然后显示效果。
    • 这里我们添加上第三个<div>元素试试。

修改

<body>
    <div class="container">
        <h1>nt-child vs nth-of-type 例子</h1>
        <p>这是第一个段落</p>
        <div>这是一个div</div>
        <p>这是第二段落</p>
        <p>这是第三段落</p>
        <div>这是第二个div</div>
        <div>这是第三个div</div>
    </div>
</body>

显示效果:

image.png

  • 属性选择器

    • 根据元素的属性及其值来选择元素,提供了更精确的选择能力。

理解这些基础知识对于任何想要深入学习CSS的人来说都是至关重要的。掌握它们可以帮助开发者更好地控制网页布局和设计,创造出既美观又高效的用户界面。