天天看點

深入研究 CSS 中的 ::before 和 ::after 僞元素

深入研究 CSS 中的 ::before 和 ::after 僞元素

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

讓我們看一下結果:

深入研究 CSS 中的 ::before 和 ::after 僞元素

請注意,我們如何使用屬性 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;
}      

讓我們看一下結果:

深入研究 CSS 中的 ::before 和 ::after 僞元素

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

讓我們看一下結果:

深入研究 CSS 中的 ::before 和 ::after 僞元素

隻需很少的代碼和額外的标記,我們就可以實作一個,否則需要大量工作的布局。

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>      

讓我們看一下結果:

深入研究 CSS 中的 ::before 和 ::after 僞元素

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>      

讓我們看一下結果:

深入研究 CSS 中的 ::before 和 ::after 僞元素

最後的想法

我們已經看到這兩個僞元素是多麼有趣。可能性是無止境。它們有助于減少不必要的标記并通過豐富你的元素來增加價值。

它們并不意味着被過度使用。正如我們所看到的,有一些特殊的用例确實很出色。在其他情況下,如果使用不當,它們可能會成為一種負擔。

我希望這篇文章能幫助你了解它們。

學習更多技能

請點選下方公衆号