5

深入学习 CSS 中的伪元素 ::before 和 ::after

 3 years ago
source link: https://my.oschina.net/lav/blog/5166892
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

深入学习 CSS 中的伪元素 ::before 和 ::after

深入学习 CSS 中的伪元素 ::before 和 ::after

CSS 伪元素用于为元素的指定部分设置样式,作为回顾,先来看下 Mozilla 开发者网站上的解释:

伪元素是一个附加至选择器末的关键词,允许你对被选择元素的特定部分修改样式。例如 ::first-line 伪元素可用于更改段落首行文字的样式。

可用的 CSS 伪元素不是很多,但是,作为前端工程师熟悉它们很重要,每一个都有特定的用途,它们可以极大地改进项目 UI 。

以下是常用的 CSS 伪元素:

  • ::after
  • ::before
  • ::first-letter
  • ::first-line
  • ::marker
  • ::selection

它们看起来都相当简单且不言自明。但是,它们将帮助您构建一些简洁而强大的布局。你觉得哪一款最酷?

::before::after 是迄今为止最常用的伪元素,它们能够在保持 HTML 和 CSS 最小化的同时做非常酷的事情。

在本文,通过实例回顾一下 ::before::after 常见的用途。

在开始之前,先来了解一下伪元素的一般语法:

selector::pseudo-element {
    property: value;
}

请注意上面的语法使用的是双冒号 (::) 而不是单个冒号 (:),这是 CSS3 语法。最初,CSS 的语法规范只有一个冒号(CSS2、CSS1)。

这一变化是由 W3C 推动的,主要目的是明确区分使用单个冒号的伪类。

它们之间有什么区别?简单来说,伪类是针对非呈现特征进行选择的;另一方面,伪元素是能够创建新的虚拟元素。为了向后兼容,CSS2 和 CSS1 中的单冒号语法在大多数浏览器中仍然被支持。

::before 和 ::after 如何工作?

这些伪元素用于在目标元素之前或之后添加内容,对内容的放置位置有一个常见的误解。许多人认为内容将放置在所选 HTML 标记之前或之后。相反,它将被放置在元素内容的前面或后面。 让看下面这个例子:

p::before {
    content: "DevPoint - ";
}
<p>天行无忌</p>

上面的 CSS 和 HTML 实现的效果等价于下面的 HTML:

<p>DevPoint - 天行无忌</p>
DevPoint - <p>天行无忌</p>

就像::before::after 在元素的内容之前添加内容一样。但有一个不能正常工作的标:<img /> ,作用于这个标签的时候不会在其中添加任何内容。它只是媒体内容的替代品,意味着它不能处理任何伪元素。

content 属性

对于伪元素,content 属性是最主要的,默认情况下,内容设置为无。意味着如果尝试在不添加该属性的情况下设置元素的样式,实际上什么也不会发生,如下代码:

p::before { 
    display:block;
    width: 100%;
    height: 50px;
    background-color: #ff0000;
}
<p>天行无忌</p>

上面的实例代码,对于CSS样式来说没有任何实际意义。

接着在样式表中增加 content 属性,如下:

p::before {
    display:block;
    width: 100%;
    height: 50px;
    content: "";
    background-color: #ff0000;
}

上面的代码就可以在段落内容前面看到红色的区块。

即使不想添加任何文本,content 属性仍然需要使用 "" ,这是使用伪元素时最容易犯的错误之一。

content 属性功能强大,可以添加各种类型的内容,使用这个属性可以在伪元素上显示任何东西,可以是文本、图片等,在使用的时候需要注意下面两点:

  1. content 默认显示为 display-inline ,而不是 display:block
  2. content 为字符串时,用户将无法选择,意味着用户将无法使用鼠标选择复制它。

content

可以直接使用类似 content:"DevPoint" 的文本值,如果有过多的内容需要写入到 content 中,直接写在样式表的方式不够灵活。这里介绍一种更加灵活的方式,通过变量传递,如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>CSS 伪元素</title>
        <meta charset="utf-8" />
        <style>
            p {
                padding: 1.25rem;
                font-weight: bold;
                font-size: 0.75rem;
            }

            p::before {
                content: attr(data-before-text);
                background-color: #00ffff;
                margin-right: 0.625rem;
                padding: 0.625rem;
            }
        </style>
    </head>
    <body>
        <p data-before-text="DevPoint">Hello World!</p>
    </body>
</html>

效果如下:

上面的代码,通过元素属性 data-before-text 来为 content 属性传递其值。同样 content 还可以是图片资源,如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>CSS 伪元素</title>
        <meta charset="utf-8" />
        <style>
            p {
                padding: 1.25rem;
                font-weight: bold;
                font-size: 0.75rem;
            }

            p::before {
                content: url(https://www.devpoint.cn/Apps/Site/View/devpoint/public/images/favicon.png);
                background-color: #00ffff;
                margin-right: 0.625rem;
                padding: 0.625rem;
            }
        </style>
    </head>
    <body>
        <p>Hello World!</p>
    </body>
</html>

效果如下:

除了url、属性和字符串之外,content 属性还可以包含多种属性,如 countersquoteslinear-gradient 等,更多内容可以查阅 MDN Web Docs 上完整的列表。

现在来看看 ::before::aftercontent 结合的常见实例效果。

主要实例之一主要用于修饰,可以使用它们为元素添加一些视觉效果,如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>CSS 伪元素</title>
        <meta charset="utf-8" />
        <style>
            h1 {
                font-weight: bold;
                text-align: center;
            }

            h1::after {
                content: "";
                display: block;
                background-color: #19b5fe;
                height: 0.2em;
                width: 100%;
            }

            h1::before {
                content: "";
                display: block;
                background-color: #19b5fe;
                height: 0.2em;
                width: 100%;
            }
        </style>
    </head>
    <body>
        <h1>DevPoint</h1>
    </body>
</html>

效果如下:

2. blockquote

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>CSS 伪元素</title>
        <meta charset="utf-8" />
        <style>
            blockquote {
                font-weight: bold;
                font-size: 1rem;
                font-style: italic;
            }

            blockquote::before {
                content: open-quote;
                font-style: normal;
                color: #585563;
            }

            blockquote::after {
                content: close-quote " —— " attr(data-author);
                font-style: normal;
                color: #585563;
            }
        </style>
    </head>
    <body>
        <blockquote data-author="卡耐基">
            机遇固然重要,但不能坐等机遇,不然机遇会白白地从身边溜走。
        </blockquote>
    </body>
</html>

3. 排序列表

创建自定义 HTML 有序列表,可以通过使用 counter-resetcounter-incrementcountercounter-name)来实现。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>CSS 伪元素</title>
        <meta charset="utf-8" />
        <style>
            ol {
                list-style: none;
                counter-reset: chapter_counter;
            }

            li {
                margin-bottom: 2.5em;
                margin-left: 2.5em;
                position: relative;
                line-height: 2em;
            }

            li::before {
                content: counter(chapter_counter);
                counter-increment: chapter_counter;
                position: absolute;
                left: -2.8em;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 50%;
                font-style: normal;
                font-size: 0.8em;
                width: 2em;
                height: 2em;
                color: white;
                background-color: #0566e6;
                border: 2px solid #0046a1;
            }
        </style>
    </head>
    <body>
        <ol>
            <li>机遇固然重要,但不能坐等机遇,不然机遇会白白地从身边溜走。</li>
            <li>除了你自己,没有别的能够带给你平静。</li>
            <li>
                一个积极进取的人,总是朝着更高奋斗目标前进,来实现自己的远大理想。
            </li>
        </ol>
    </body>
</html>

本文介绍了::before::after 两个伪元素基本知识和常见的用法。但并非本文介绍的用法,存在很多意想不到的效果,它们有助于减少不必要的标记并通过丰富元素来增加价值。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK