CSS:让网页生动起来的魔法

138 阅读13分钟

对于一个网站来说,HTML是它的骨架,而CSS则是赋予这个骨架生命与个性的关键。让我们一起探索CSS的魅力吧!

什么是CSS?

CSS全称为Cascading Style Sheets(层叠样式表),它是一种用来控制网页布局、外观的设计语言。通过使用CSS,我们可以轻松地改变文字的颜色、大小、字体等属性,以及调整页面元素的位置和布局。下面是一个简单的例子:

/* 这是一条CSS规则 */
h1 { /* 选择器 */
  color: red; /* 声明:设置颜色为红色 */
  text-align: center; /* 声明:居中对齐 */
}

在这段代码中,h1是选择器,它指定了哪一部分HTML内容将被这条规则影响;大括号内的部分被称为声明块,其中包含了具体的样式声明。

CSS的工作原理

  • 依附于HTML:CSS本身不能独立运行,它必须与HTML文档相结合才能发挥作用。

  • 选择DOM元素并应用样式:CSS通过特定的选择器来定位HTML文档中的元素,并为其添加样式。

  • 引入方式

    • 内联样式:直接在HTML标签内部使用style属性定义样式。
    • 外部样式:创建单独的.css文件并通过<link>标签链接到HTML文档中。
    • 行内样式:直接写入HTML元素的style属性,如 <p style="color: pink;"></p>

浏览器首先下载所有需要的资源,然后解析HTML形成DOM树,接着根据CSS规则构建渲染树,最后由渲染引擎将这些信息转化为用户可见的网页。

样式优先级

当多个CSS规则同时作用于同一个元素时,浏览器会根据一定的规则决定采用哪个规则。这里涉及到几个关键点:

  • 基础权重:从低到高依次为标签(1) < 类名(10) < ID(100) < 行内样式(1000) < !important(最大)。
  • 复杂选择器的权重计算:当选择器包含多个部分时,其总权重等于各部分权重之和。
  • 优先级顺序:行内样式 > 内部样式 > 外部样式。

例如,对于选择器.container ul li:nth-child(odd),其权重为22 (类名10 + 标签1 + 后代选择器1 + 伪类选择器10)。

CSS选择器种类

CSS选择器是CSS中非常重要的组成部分,它们允许开发者精确地定位HTML文档中的元素,并为其应用样式。CSS选择器种类繁多,可以满足各种复杂的需求。下面我将详细介绍CSS的主要选择器类型:

1. 基础选择器

  • 标签选择器:直接使用HTML标签名作为选择器,如pdiv等。
  • 类选择器:通过.class_name形式来选择具有特定类属性的元素。
  • ID选择器:通过#id_name形式来选择拥有特定ID的元素。
  • 通配符选择器:用*表示,可以选择所有元素。

2. 组合选择器

  • 后代选择器(空格):例如div p会选择所有位于<div>内部的<p>元素。
  • 子元素选择器(>):例如div > p仅选择直接子元素为<p><div>
  • 相邻兄弟选择器(+):例如h1 + p选择紧跟在<h1>之后的第一个<p>元素。
  • 普通兄弟选择器(~):例如h1 ~ p选择与<h1>处于同一父元素下的所有后续<p>元素。

3. 伪类选择器

伪类用于定义元素的特定状态:

  • 动态伪类::hover:active:focus
  • 目标伪类::target
  • 结构伪类::first-child:last-child:nth-child(n):only-child:empty

4. 伪元素选择器

伪元素用于选取并设置元素的特定部分:

  • ::before 和 ::after:用于在内容前或后插入生成的内容。
  • ::first-line 和 ::first-letter:分别作用于段落的第一行和第一个字母。
  • ::selection:用于设置用户选中文本时的样式。

5. 属性选择器

基于元素的属性值来选择元素:

  • [attribute]:选择有指定属性的元素。
  • [attribute=value]:选择属性值完全匹配的元素。
  • [attribute~=value]:选择包含以空格分隔的多个值之一的元素。
  • [attribute^=value][attribute$=value][attribute*=value]:分别选择属性值以指定字符串开头、结尾或包含指定字符串的元素。

下面是针对每种选择器类型的具体代码示例:

1. 基础选择器

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>基础选择器示例</title>
<style>
  /* 标签选择器:选择所有<p>标签 */
  p {
    color: blue; /* 设置文字颜色为蓝色 */
  }

  /* 类选择器:选择所有带有class属性值为"highlight"的元素 */
  .highlight {
    background-color: yellow; /* 设置背景颜色为黄色 */
  }

  /* ID选择器:选择ID为"special"的唯一元素 */
  #special {
    font-weight: bold; /* 设置字体加粗 */
  }

  /* 通配符选择器:选择文档中的所有元素 */
  * {
    margin: 0; /* 清除所有元素的外边距 */
    padding: 0; /* 清除所有元素的内边距 */
  }
</style>
</head>
<body>
  <p>这是一个普通的段落。</p>
  <p class="highlight">这个段落有高亮背景。</p>
  <p id="special">这个段落使用了ID选择器。</p>
  <div>所有的元素都有默认的外边距和内边距被清除。</div>
</body>
</html>

2. 组合选择器

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>组合选择器示例</title>
<style>
  /* 后代选择器:选择所有位于<div>内的<p>标签 */
  div p {
    color: green; /* 设置文字颜色为绿色 */
  }

  /* 子元素选择器:选择直接子元素为<p>的<div> */
  div > p {
    font-style: italic; /* 设置斜体 */
  }

  /* 相邻兄弟选择器:选择紧跟在<h1>之后的第一个<p> */
  h1 + p {
    text-decoration: underline; /* 添加下划线 */
  }

  /* 普通兄弟选择器:选择与<h1>处于同一父元素下的所有后续<p> */
  h1 ~ p {
    border: 1px solid black; /* 添加黑色边框 */
  }
</style>
</head>
<body>
  <div>
    <h1>标题</h1>
    <p>这是直接子元素。</p>
    <section>
      <p>这是后代元素。</p>
    </section>
  </div>
  <h1>另一个标题</h1>
  <p>这是相邻兄弟元素。</p>
  <p>这也是普通兄弟元素之一。</p>
  <p>这也是普通兄弟元素之一。</p>
</body>
</html>

3. 伪类选择器

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>伪类选择器示例</title>
<style>
  /* 未访问过的链接 */
  a:link {
    color: blue; /* 设置链接颜色为蓝色 */
  }

  /* 已访问过的链接 */
  a:visited {
    color: purple; /* 设置链接颜色为紫色 */
  }

  /* 鼠标悬停时的链接 */
  a:hover {
    color: red; /* 设置链接颜色为红色 */
  }

  /* 链接被激活(点击)时 */
  a:active {
    color: orange; /* 设置链接颜色为橙色 */
  }

  /* 第一个子元素 */
  p:first-child {
    font-size: 1.5em; /* 设置第一个段落的文字大小为1.5倍 */
  }

  /* 奇数行列表项 */
  li:nth-child(odd) {
    background-color: lightgray; /* 设置奇数行列表项的背景颜色为浅灰色 */
  }
</style>
</head>
<body>
  <a href="#">链接文本</a>
  <p>第一个段落,字体较大。</p>
  <p>第二个段落。</p>
  <ul>
    <li>列表项1</li>
    <li>列表项2</li>
    <li>列表项3</li>
  </ul>
</body>
</html>

4. 伪元素选择器

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>伪元素选择器示例</title>
<style>
  /* 段落的第一行 */
  p::first-line {
    font-weight: bold; /* 设置第一行文字加粗 */
  }

  /* 段落的第一个字母 */
  p::first-letter {
    font-size: 2em; /* 设置第一个字母的字体大小为2倍 */
  }

  /* 在段落前插入内容 */
  p::before {
    content: "开始 -> "; /* 插入的内容 */
    color: red; /* 设置插入内容的颜色为红色 */
  }

  /* 在段落后插入内容 */
  p::after {
    content: " <- 结束"; /* 插入的内容 */
    color: blue; /* 设置插入内容的颜色为蓝色 */
  }

  /* 用户选中的文本 */
  ::selection {
    background: yellow; /* 设置选中文本的背景颜色为黄色 */
    color: black; /* 设置选中文本的颜色为黑色 */
  }
</style>
</head>
<body>
  <p>这是一个测试段落,用于展示伪元素的效果。</p>
  <p>尝试选中一些文本看看效果。</p>
</body>
</html>

5. 属性选择器

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>属性选择器示例</title>
<style>
  /* 任何带有data-type属性的元素 */
  [data-type] {
    color: green; /* 设置文字颜色为绿色 */
  }

  /* data-type属性值为"important"的元素 */
  [data-type="important"] {
    font-weight: bold; /* 设置字体加粗 */
  }

  /* data-type属性值包含"note"(以空格分隔)的元素 */
  [data-type~="note"] {
    background-color: lightyellow; /* 设置背景颜色为浅黄色 */
  }

  /* href属性以"http"开头的<a>标签 */
  [href^="http"] {
    color: blue; /* 设置链接颜色为蓝色 */
  }

  /* href属性以".pdf"结尾的<a>标签 */
  [href$=".pdf"] {
    color: red; /* 设置链接颜色为红色 */
  }

  /* href属性包含"example"的<a>标签 */
  [href*="example"] {
    text-decoration: none; /* 移除下划线 */
  }
</style>
</head>
<body>
  <p data-type="important note">这是一条重要信息。</p>
  <a href="http://example.com">访问示例网站</a>
  <a href="document.pdf">下载文档</a>
  <a href="https://another-example.org">另一个示例链接</a>
</body>
</html>

具体例子

下面我们举几个例子让你更加直观的理解CSS的魔法

例1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>css</title>
    <style>
        /* 1 */
        p {
            color: blue !important;
        }
/* !important 优先级最高 */
        /* 11 */
        .container p {
            color: red;
        }

        /* 101 */
        #main p {
            color: green;
        }
    </style>
</head>

<body>
    <!-- attribute 属性 -->
    <div id="main" class="container">
        <p style="color: pink;">这是一段文字</p>
        <!-- 行内样式1000 -->

    </div>
</body>

</html>

这段HTML代码展示了不同CSS选择器的优先级以及!important声明的效果。让我们解释这段代码:

优先级分析

  1. 行内样式 (style="color: pink;"):

    • 优先级:1000
    • 通常情况下,行内样式的优先级是最高的。
  2. ID选择器 (#main p):

    • 优先级:100 + 1
    • 如果没有更高的优先级样式,<p>标签的文字颜色会是绿色。
  3. 类选择器 (.container p):

    • 优先级:10 + 1
    • 如果没有更高的优先级样式,<p>标签的文字颜色会是红色。
  4. 标签选择器 (p):

    • 优先级:1
    • 但是这里使用了 !important,所以它的实际优先级非常高。

重要性声明 !important

  • !important 使得该规则的优先级高于普通CSS规则,即使在其他规则有更高优先级的情况下也是如此。
  • 在本例中,p { color: blue !important; } 的优先级被提升到最高级别,甚至高于行内样式的优先级(1000)。

最终结果

由于 p { color: blue !important; } 使用了 !important,它将覆盖所有其他样式,包括行内样式 style="color: pink;"。因此,最终显示的文字颜色将是蓝色。

image.png

结论

  • 行内样式虽然通常具有最高的优先级(1000),但在遇到带有 !important 的声明时,会被 !important 声明覆盖。
  • 因此,最终 <p> 标签的文字颜色是蓝色。

例2

<!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 {
            color: red;
        }

        /* 普通兄弟选择器 选择前面有某元素的所有兄弟元素。*/
        h1~p {
            color: blue;
        }

        /* 子元素选择器 选择作为某元素直接子元素的元素。*/
        .container>p {
            font-weight: bold;
        }

        /* 后代元素选择器 选择作为某元素后代元素的元素。*/
        .container p {
            text-decoration: underline;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>标题</h1>
        <p>这是第一段文字</p>
        <p>这是第二段文字</p>
        <a href="">链接</a>
        <span>这是一个span元素</span>
        <div class="inner">
            <p>这是一个内部的段落</p>
        </div>
    </div>
</body>

</html>

选择器效果分析

  1. 相邻兄弟选择器 (h1 + p) :

    • 选择紧跟在<h1>之后的第一个<p>元素。
    • 适用元素:<p>这是第一段文字</p>
    • 效果:文字颜色为红色。
  2. 普通兄弟选择器 (h1 ~ p) :

    • 选择所有与<h1>在同一父元素下的<p>元素。
    • 适用元素:<p>这是第一段文字</p> 和 <p>这是第二段文字</p>
    • 效果:文字颜色为蓝色。
  3. 子元素选择器 (container > p) :

    • 选择类名为container的元素内的所有直接子<p>元素。
    • 适用元素:<p>这是第一段文字</p> 和 <p>这是第二段文字</p>
    • 效果:字体加粗。
  4. 后代元素选择器 (container p) :

    • 选择类名为container的元素内的所有后代<p>元素。
    • 适用元素:<p>这是第一段文字</p><p>这是第二段文字</p> 和 <p>这是一个内部的段落</p>
    • 效果:添加下划线。

优先级分析

  • h1 + p { color: red; } 的优先级是11。
  • h1 ~ p { color: blue; } 的优先级也是11。
  • .container > p { font-weight: bold; } 的优先级是11。
  • .container p { text-decoration: underline; } 的优先级是11。

最终结果

  • <p>这是第一段文字</p>:

    • 文字颜色:由于h1 + ph1 ~ p都设置了颜色,且它们的优先级相同,所以根据CSS规则,后定义的样式会覆盖前定义的样式。因此,最终文字颜色为蓝色。
    • 字体加粗:由.container > p决定。
    • 添加下划线:由.container p决定。
  • <p>这是第二段文字</p>:

    • 文字颜色:由h1 ~ p决定,为蓝色。
    • 字体加粗:由.container > p决定。
    • 添加下划线:由.container p决定。
  • <p>这是一个内部的段落</p>:

    • 文字颜色:默认颜色(未被任何选择器改变)。
    • 字体不加粗:因为它不是直接子元素,而是后代元素。
    • 添加下划线:由.container p决定。

总结

  • <p>这是第一段文字</p>: 蓝色,加粗,带下划线。
  • <p>这是第二段文字</p>: 蓝色,加粗,带下划线。
  • <p>这是一个内部的段落</p>: 默认颜色,不加粗,带下划线。

image.png

例3

<!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>
        /* 伪类选择器 */
        button:active {
            background-color: red;
            color: white;
        }

        p:hover {
            background-color: yellow;
        }

        /*伪类选择器 */
        ::selection {
            background-color: yellow;
            color: white;
        }

        input:focus {
            border: 5px solid blue;
        }

        input:checked+label {
            color: blue;
        }

        li:nth-child(odd) {
            background-color: lightgray;
        }

        /* 除了最后一个元素外,所有的li元素都有一个底部外边距。 */
        li:not(:last-child) {
            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>

伪类选择器效果分析

button:active

  • 选择器button:active
  • 适用元素<button>点击我</button>
  • 效果: 当按钮被激活(即鼠标按下时),按钮的背景颜色变为红色,文字颜色变为白色。

p:hover

  • 选择器p:hover
  • 适用元素<p>鼠标悬浮在这里</p>
  • 效果: 当鼠标悬浮在段落上时,段落的背景颜色变为黄色。

::selection

  • 选择器::selection
  • 适用元素: 选中的任何文本
  • 效果: 当用户选中页面上的任何文本时,选中文本的背景颜色变为黄色,文字颜色变为白色。

input:focus

  • 选择器input:focus
  • 适用元素<input type="text" placeholder="输入框">
  • 效果: 当输入框获得焦点(即用户点击或使用Tab键导航到输入框时),输入框的边框变为5像素宽的蓝色实线。

input:checked + label

  • 选择器input:checked + label
  • 适用元素<input type="checkbox" id="option1" checked> 和紧跟在其后的 <label for="option1">选项1</label>下面选项2的也如此
  • 效果: 当复选框被选中时,紧跟在其后的<label>标签的文字颜色变为蓝色。

li:nth-child(odd)

  • 选择器li:nth-child(odd)

  • 适用元素<ul> 中的奇数位置的<li>列表项

  • 效果: 选择所有奇数位置的<li>列表项,并将其背景颜色设置为浅灰色。

    • 适用元素:<li>列表项1</li> 和 <li>列表项3</li>

li:not(:last-child)

  • 选择器li:not(:last-child)

  • 适用元素<ul> 中除了最后一个<li>以外的所有<li>列表项

  • 效果: 选择所有不是最后一个子元素的<li>列表项,并为其添加10像素的底部外边距。

    • 适用元素:<li>列表项1</li><li>列表项2</li> 和 <li>列表项3</li>

最终结果

<button>点击我</button>

  • 效果:当按钮被激活(鼠标按下时),背景颜色变为红色,文字颜色变为白色。

<p>鼠标悬浮在这里</p>

  • 效果:当鼠标悬浮在段落上时,背景颜色变为黄色并且选中任何文本时文字背景颜色变成黄色,文字演示变成白色。

<input type="text" placeholder="输入框">

  • 效果:当输入框获得焦点时,边框变为5像素宽的蓝色实线。

<input type="checkbox" id="option1"> 和 <label for="option1">选项1</label>

  • 效果:当复选框未选中时,<label>标签的文字颜色保持默认。

<input type="checkbox" id="option2" checked> 和 <label for="option2">选项2</label>

  • 效果:当复选框被选中时,<label>标签的文字颜色变为蓝色。

<ul> 中的 <li> 列表项

  • 效果

    • 奇数位置的<li>列表项的背景颜色为浅灰色。

      • 适用元素:<li>列表项1</li> 和 <li>列表项3</li>
    • 除了最后一个<li>列表项外,其他每个<li>列表项都有10像素的底部外边距。

      • 适用元素:<li>列表项1</li><li>列表项2</li> 和 <li>列表项3</li>

image.png

总结

  • 按钮:当按钮被激活时,背景颜色变为红色,文字颜色变为白色。

  • 段落:当鼠标悬浮在段落上时,背景颜色变为黄色。

  • 选中文本:当用户选中页面上的任何文本时,选中文本的背景颜色变为黄色,文字颜色变为白色。

  • 输入框:当输入框获得焦点时,边框变为5像素宽的蓝色实线。

  • 复选框:当复选框被选中时,紧跟在其后的<label>标签的文字颜色变为蓝色。

  • 列表项

    • 奇数位置的列表项的背景颜色为浅灰色。
    • 除了最后一个列表项外,其他每个列表项都有10像素的底部外边距。

例4

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    /* 只有当 <p> 元素正好是其父元素的第三个子元素时,才会被选中。第三个孩子不是p所以不生效 */
    /* 如果是:nth-child(3) 那么第三个子元素会被选中 */
    .container p:nth-child(3) {
        background-color: yellow;
        color: black;
    }

    /* 选择作为其父元素的第n个特定类型的子元素 */
    .container p:nth-of-type(3) {
        background-color: lightblue;
        color: black;
    }
</style>

<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>

选择器效果分析

.container p:nth-child(3)

  • 选择器.container p:nth-child(3)
  • 适用元素: 无
  • 效果: 该选择器试图选择作为其父元素(.container)的第三个子元素的<p>标签。然而,在这个例子中,第三个子元素是<div>这是一个div</div>,而不是<p>标签,因此这个选择器不会生效。

.container p:nth-of-type(3)

  • 选择器.container p:nth-of-type(3)
  • 适用元素<p>这是第三个段落</p>
  • 效果: 该选择器选择作为其父元素(.container)的第三个<p>类型的子元素。在这个例子中,第三个<p>标签是<p>这是第三个段落</p>,因此这个选择器会生效,将背景颜色设置为浅蓝色,文字颜色设置为黑色。

最终结果

<p>这是第一个段落</p>

  • 效果:没有特殊样式。

<div>这是一个div</div>

  • 效果:没有特殊样式。

<p>这是第二个段落</p>

  • 效果:没有特殊样式。

<p>这是第三个段落</p>

  • 效果

    • 背景颜色:浅蓝色(由.container p:nth-of-type(3)决定)。
    • 文字颜色:黑色(由.container p:nth-of-type(3)决定)。

<div>这是第二个div</div>

  • 效果:没有特殊样式。

image.png

总结

  • .container p:nth-child(3) :

    • 适用元素: 无
    • 效果: 由于第三个子元素不是<p>标签,所以这个选择器不会生效。
  • .container p:nth-of-type(3) :

    • 适用元素<p>这是第三个段落</p>
    • 效果: 背景颜色变为浅蓝色,文字颜色变为黑色。

进阶技巧

如果去掉 .container p:nth-of-type(3) 中的p他会选择作为其父元素(.container)的第三个所有类型的子元素。

效果如图

image.png

希望这篇介绍能帮助你更好地理解CSS的基础知识!如果你有任何问题或者想要了解更多细节,请随时留言交流。别忘了关注我获取更多技术分享哦~