原文 | https://betterprogramming.pub/mastering-css-before-and-after-ecf1d59d9a3d
翻譯 | 小愛
CSS 僞元素用于為元素的指定部分設定樣式。回顧一下,讓我們檢查一下 Mozilla 開發者網絡上的參考解釋:
“CSS 僞元素是添加到選擇器的關鍵字,可讓您設定所選元素的特定部分的樣式。例如,::first-line 可用于更改段落第一行的字型。” — MDN網絡文檔
可用的 CSS 僞元素清單不是很長。但是,熟悉它們很重要。每一個都有特定的目的。它們可以極大地改進你的 Web 代碼庫。
以下是所有 CSS 僞元素:
- ::after
- ::before
- ::first-letter
- ::first-line
- ::marker
- ::selection
它們看起來都相當簡單。它們可以建構一些簡潔而強大的布局。你覺得哪一款最酷?
::before 和 ::after 是我最喜歡的。它們能夠在保持 HTML 和 CSS 最小化的同時做非常酷的事情。
在本文中,我們可以用它建構所有很酷的東西。我們還将看到他們的常見用例是什麼。
文法
在深入研究之前,讓我們看一下僞元素的一般文法:
selector::pseudo-element {
property: value;
}
請注意我們需要使用雙冒号 (::) 而不是單個冒号 (:)。這就是 CSS3 文法。最初,他們的文法規範隻有一個冒号(CSS2、CSS1)。
這種變化是由 W3C 推動的。他們旨在明确區分那些使用單個冒号的僞類。
它們之間有什麼差別?簡而言之,僞類用于選擇非表現性特征。另一方面,僞元素使我們能夠建立新的虛拟元素。
請注意,出于向後相容性的考慮,大多數浏覽器仍接受來自 CSS2 和 CSS1 的單冒号文法。
::before 和 ::after 工作如何?
這些僞元素用于在目标元素之前或之後添加内容。
對内容的放置位置有一個常見的誤解。許多人認為内容将放置在標明的 HTML 标記之前或之後。相反,它将被放置在元素的内容之前或之後。
讓我們看看這個例子:
p::before {
content: "foo - ";
}
<p>text</p>
在原始 HTML 中,“輸出”将等同于:
✅ <p>foo - text</p>
而不是這個:
❌ foo - <p> text</p>
由于 ::before 和 ::after 在元素内容之前添加内容,是以有一個标簽不起作用:<img />,此标簽不會在其中添加内容。它隻是媒體内容的替代品。這意味着它不适用于任何僞元素。
内容屬性
對于僞元素,内容屬性至關重要。預設情況下,内容設定為無。這意味着如果你嘗試在不添加該屬性的情況下設定元素的樣式,實際上什麼也不會發生。
p::before {
width: 100px;
height: 100px;
background-color: red;
}
<p>text</p>
❌ Only the paragraph text will be displayed
讓我們通過添加一些内容來修複上面的示例:
p::before {
content: '';
width: 100px;
height: 100px;
background-color: red;
}
<p>text</p>
✅ The text paragraph + a box of 100x100 and red will be displayed
即使我們不想添加任何文本,我們仍然需要用 '' 填充該屬性。這是使用僞元素時最常見的錯誤之一。
現在我們已經看到了内容的重要性,讓我們通過檢視 MDN 來準确定義它是什麼:
“内容 CSS 屬性用生成的值替換元素。使用 content 屬性插入的對象是匿名替換元素。” — MDN 網絡文檔
content 屬性非常強大,讓我們可以添加來自許多不同來源的内容。當使用這個屬性在僞元素上顯示任何東西時,我們需要注意幾個怪癖:
預設情況下,内容将顯示為 display-inline 而不是 display:block。
如果内容是字元串,使用者将無法選擇。這意味着使用者将無法用滑鼠複制它。它應該是 atrezzo 而不是主要内容。
内容值
我們可以使用 content: 'foo' 直接添加字元串内容。如果我們希望文本可翻譯怎麼辦?如果我們直接在 CSS 樣式表中添加文本,将很難用适當的翻譯替換它。
對于該用例,我們可以将翻譯存儲在具有屬性的元素中。然後,我們可以通過引用該屬性将其與内容一起拉出。這将使我們的 CSS 保持動态,而不是靜态綁定到字元串。
讓我們看一個例子:
<!DOCTYPE html>
<html>
<style>
p {
padding: 1.25rem;
font-weight: bold;
font-size: 1.25rem;
}
p::before {
content: attr(data-before-text);
background-color: aqua;
margin-right: 0.625rem;
padding: 0.625rem;
}
</style>
<body>
<p data-before-text="foo">hello world</p>
</body>
</html>
讓我們看一下結果:
請注意,我們如何使用屬性 before-text 來提取文本:
p::before {
content: attr(data-before-text);
background-color: aqua;
margin-right: 0.625rem;
padding: 0.625rem;
}
content 屬性可以包含URL。讓我們看一個具有該用例的示例:
p::before {
content: url(https://unsplash.it/15/15);
margin-right: 0.625rem;
}
讓我們看一下結果:
除了 URL、屬性和字元串之外,内容屬性還可以包含各種屬性:計數器、引号、線性漸變等。你可以在 MDN Web Docs 上檢視完整清單。
我們不限于使用一處。我們可以将多個内容屬性合二為一。
p::before {
content: attr(data-details) "- more details -";
margin-right: 0.625rem;
}
示例
既然我們已經看到了 ::before 和 ::after 結合内容的強大功能,讓我們來看一些實際的例子。
1、化妝品
主要用例之一主要用于化妝品。你可以使用它們為元素添加一些視覺美感。
讓我們通過一個例子更好地了解它:
<!DOCTYPE html>
<html>
<style>
h1 {
font-weight: bold;
}
h1::after {
content: "";
display: block;
background-color: #73937e;
height: 0.2em;
width: 100%;
}
h1::before {
content: "";
display: block;
background-color: #73937e;
height: 0.2em;
width: 100%;
}
</style>
<body>
<h1>Header title</h1>
</body>
</html>
讓我們看一下結果:
隻需很少的代碼和額外的标記,我們就可以實作一個,否則需要大量工作的布局。
2、自定義塊引用
另一個很好的用法是建立你的自定義塊引用。讓我們自定義該 HTML5 标記,以使用 CSS 和自定義屬性建立一個可重用的元件。
讓我們看看它的代碼:
<!DOCTYPE html>
<html>
<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>
<body>
<blockquote data-author="Isaac Asimov">
I do not fear computers. I fear lack of them.
</blockquote>
</body>
</html>
讓我們看一下結果:
3、自定義排序清單
另一個用例是建立自定義 HTML 有序清單。這可以通過使用 counter-reset、counter-increment 和 counter(counter-name) 來實作。
讓我們看看它的代碼:
<!DOCTYPE html>
<html>
<style>
ol {
list-style: none;
counter-reset: chapter_counter;
}
li {
margin-bottom: 2.5em;
margin-left: 2.5em;
position: relative;
}
li::before {
content: counter(chapter_counter);
counter-increment: chapter_counter;
position: absolute;
left: -2.6em;
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>
<body>
<ol>
<li>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s.
</li>
<li>
Contrary to popular belief, Lorem Ipsum is not simply random text. It
has roots in a piece of classical Latin literature from 45 BC, making it
over 2000 years old.
</li>
<li>
Of the printing and typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s, when an unknown
printer took a galley of type and scrambled it to make a type specimen
book. It has survived not only five centuries, but
</li>
</ol>
</body>
</html>
讓我們看一下結果:
最後的想法
我們已經看到這兩個僞元素是多麼有趣。可能性是無止境。它們有助于減少不必要的标記并通過豐富你的元素來增加價值。
它們并不意味着被過度使用。正如我們所看到的,有一些特殊的用例确實很出色。在其他情況下,如果使用不當,它們可能會成為一種負擔。
我希望這篇文章能幫助你了解它們。
學習更多技能
請點選下方公衆号