虛擬元素選擇器 ( 偽元素 )
所謂的「虛擬元素」也稱為「偽元素」,表示不存在於真實的 HTML 元素,可能是「想像的元素」或根據現有元素進行「想像分類」,而「虛擬元素選擇器」就是專門針對這些「想像元素或分類」的選擇器,例如 ::before、::after、::first-letter、::first-line、::marker 等等,這篇教學會深入介紹這些虛擬元素選擇器的用法。
虛擬元素選擇器
虛擬元素選擇器開頭使用兩個冒號「::
」,雖然也支援一個冒號,但為了避免和使用一個冒號的「虛擬類別選擇器」產生誤會,仍強烈建議使用兩個冒號 ( 目前支援一個冒號是為了向下相容,但不能保證哪天瀏覽器就不支援了 )。
使用虛擬元素選擇器時,需要注意以下幾點:
- 所有的虛擬元素選擇器都必須放在選擇器的「最末端」。
- 一個選擇器裡只會出現「一個虛擬元素」。
下方列出常用的虛擬元素選擇器 ( 支援度 All 表示主流瀏覽器都支援 ),:
虛擬元素選擇器 | 說明 | 支援度 |
---|---|---|
::before、::after | 元素前方或後方的虛擬元素。 | All |
::first-letter、::first-line | 元素內容的第一個字或第一行。 | All |
::marker | 清單標記圖示。 | IE 不支援 |
::selection | 選取的文字。 | 部分瀏覽器不支援 |
::placeholder | 未輸入內容時的顯示文字。 | All |
::file-selector-button | 開啟檔案的按鈕。 | All |
::spelling-error | 英文拼字錯誤。 | 部分瀏覽器不支援 |
::before、::after
「::before
」和「::after
」表示「元素前方或後方的想像元素」,是使用頻率非常高的虛擬元素,只要搭配主元素使用,就會自動在元素的前方或後方添加一個 display 為「inline」的虛擬元素,此外,這兩個虛擬元素必須搭配「content
」樣式屬性來呈現內容。
下方的範例執行後,會在所有的元素前方加上紅色的「123」,以及在後方加上綠色的「456」。
<!-- HTML 程式碼 -->
<h2>oxxo</h2>
<h3>hello world</h3>
<div>我是 DIV</div>
<ul>
<li>oxxo</li>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ul>
<!-- CSS 程式碼 -->
<style>
body *::before {
content: "123";
color: red;
}
body *::after {
content: "456";
color: green;
}
</style>
::before
和 ::after
的 content 屬性除了可以設定內容,也可以使用「attr(屬性)
」語法,「讀取主要元素的屬性」,下方的範例執行後,::before
會讀取並顯示主元素的 b 屬性,::after
會讀取並顯示主元素的 f 屬性,如果沒有讀到屬性也是會產生一個虛擬元素 ( 例如 ul 的 ::after
),但長寬會是 0x0 ( 等同於不可見 )。
<!-- HTML 程式碼 -->
<h2 b="123" f="456">oxxo</h2>
<h3 b="789" f="ABC">hello world</h3>
<div b="DEF" f="GH">我是 DIV</div>
<ul>
<li b="IJK" f="XYZ">oxxo</li>
<li b="QQQ" f="PPP">apple</li>
<li b="123" f="456">banana</li>
<li b="123" f="456">orange</li>
</ul>
<!-- CSS 程式碼 -->
<style>
body *::before {
content: "(" attr(b) ")"; /* 顯示 b 屬性內容,並與括號結合 */
color: red;
}
body *::after {
content: attr(f); /* 顯示 f 屬性內容 */
color: green;
}
</style>
如果使用「url(網址)
」語法,也能讓 ::before
和 ::after
顯示圖片,不過需要注意這個方式無法使用正規的方法改變圖片尺寸,圖片多大就會顯示多大。
<!-- HTML 程式碼 -->
<ul>
<li>oxxo</li>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ul>
<!-- CSS 程式碼 -->
<style>
li::after {
content: url(圖片網址); /* 顯示圖片 */
}
</style>
::before
和 ::after
常與「使用者互動」有關,與「:hover
」虛擬類別互相搭配的應用更是屢見不鮮,下方的範例除了會讀取主元素的 note 屬性,更會搭配虛擬類別,當滑鼠懸停在 a 元素上方時,就會顯示由 ::before
和 ::after
所構成的提示方塊 ( 不需要太過深入理解範例程式碼,此處主要強調虛擬元素選擇器 )。
<!-- HTML 程式碼 -->
<nav>
<a href="#" note="張小彥">oxxo</a>
<a href="#" note="紅蘋果">apple</a>
<a href="#" note="黃香蕉">banana</a>
<a href="#" note="橘橘子">orange</a>
</nav>
<!-- CSS 程式碼 -->
<style>
a {
position:relative; /* 設定 a 的位置屬性 */
}
a::before {
content: attr(note); /* 顯示屬性 */
display:block; /* 改變為 block 顯示類型 */
position:absolute; /* 絕對定位 */
left:0;
top:30px; /* 設定位置 */
width:max-content; /* 使用內容作為寬度 */
padding:3px 5px; /* 設定內邊距 */
color: white; /* 文字白色 */
background: black; /* 背景黑色 */
border-radius:5px; /* 圓角 */
opacity: 0; /* 全透明 */
}
a::after {
content:""; /* 不顯示內容 */
display:block; /* 改變為 block 顯示類型 */
position:absolute; /* 絕對定位 */
left:10px;
top:20px; /* 設定位置 */
width:0;
height:0; /* 寬高設為 0 */
border-width:5px; /* 邊框 5px */
border-color: rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,1); /* 下邊框黑色,其他都是透明 */
border-style: solid; /* 邊框樣式為實心 */
opacity: 0; /* 全透明 */
}
a:hover::before, a:hover::after {
opacity: 1; /* 滑鼠懸停時改成不透明 */
}
</style>
::first-letter、::first-line
::first-letter
和 ::first-line
會選取內容的「第一個字母」或「第一行」,不過這兩個虛擬元素只能使用下列的樣式屬性:
::first-letter 支援屬性 | ::first-line支援屬性 |
---|---|
所有 font 樣式 | 所有 font 樣式 |
所有 text 樣式 | 所有 text 樣式 |
所有 background 樣式 | 所有 background 樣式 |
所有 border 樣式 | 所有 border 樣式 |
color | color |
box-shadow | margin |
inline layout | padding |
opacity | opacity |
開啟下方的範例後,第一個字會是 100px 的紅色文字,第一行則會是綠色文字,就算縮放螢幕後第一行字數有變動,還是會只有第一行的文字是綠色的。
<!-- HTML 程式碼 -->
<p>
CSS 教學會透過一系列的文章和許多由淺入深的範例,介紹 CSS 的相關知識,從 CSS 的基本概念、選擇器的應用一直到排版佈局、動畫效果都有完整介紹,希望對於網頁初學者、網頁設計師、甚至是網頁前端工程師,提供非常有幫助的知識內容。
</p>
<!-- CSS 程式碼 -->
<style>
p::first-letter {
color: red;
font-size:100px;
}
p::first-line {
color: green;
}
</style>
::marker
::marker
是針對「清單標記圖示」的虛擬元素,可以修改使用清單元素時,自動產生的標記圖示,使用時需要搭配「content
」屬性,屬性內容可以使用符號、url(圖片)
或 attr(屬性)
。
::marker
只支援下列的樣式屬性:所有 font 樣式、color、white-space、animation 和 transition。
下方的範例開啟後,三組清單分別會將清單標記替換為純文字符號、屬性內容和圖片。
<!-- HTML 程式碼 -->
<ul class="a">
<li>oxxo</li>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ul>
<ul class="b">
<li icon="$">oxxo</li>
<li icon="$">apple</li>
<li icon="$">banana</li>
<li icon="$">orange</li>
</ul>
<ul class="c">
<li>oxxo</li>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ul>
<!-- CSS 程式碼 -->
<style>
.a li::marker {
content: ">> ";
color: green;
}
.b li::marker {
content: attr(icon) ".";
color: red;
}
.c li::marker {
content: url(圖片網址) " - ";
}
</style>
::selection
::selection
是針對「選取的文字」的虛擬元素,可以修改選取的文字樣式,由於是選取的文字樣式,樣式屬性只支援 color
、background-color
、text-decoration
和 text-shadow
這幾種,下方的範例開啟後,使用滑鼠選擇一段文字,這段文字就會呈現紅底白字。
<!-- HTML 程式碼 -->
<p>
CSS 教學會透過一系列的文章和許多由淺入深的範例,介紹 CSS 的相關知識,從 CSS 的基本概念、選擇器的應用一直到排版佈局、動畫效果都有完整介紹,希望對於網頁初學者、網頁設計師、甚至是網頁前端工程師,提供非常有幫助的知識內容。
</p>
<!-- CSS 程式碼 -->
<style>
p::selection {
background: red;
color: white;
}
</style>
::placeholder
::placeholder
是針對「未輸入內容時的顯示文字」的虛擬元素,只會對「輸入元素」有作用,下方的範例開啟後,有使用 placeholder 屬性的輸入元素,就會呈現紅底白字,開始輸入文字後,就會恢復原本的樣式。
<!-- HTML 程式碼 -->
<form action="/test.aspx" method="post">
<input type="text" placeholder="你的 id">
<br>
<input type="text" placeholder="你的姓名">
</form>
<!-- CSS 程式碼 -->
<style>
input::placeholder {
background: red;
color: white;
}
</style>
::file-selector-button
::file-selector-button
是針對「開啟檔案的按鈕」的虛擬元素,只會對「input 的 file 類型」有作用,下方的範例開啟後,開啟檔案的按鈕就會變成指定的樣式。
<!-- HTML 程式碼 -->
<form action="/test.aspx" method="post">
<input type="file" accept=".jpg">
</form>
<!-- CSS 程式碼 -->
<style>
input::file-selector-button {
background: red;
color: white;
padding:10px;
}
</style>
::spelling-error
::spelling-error
是針對「英文拼字錯誤」的虛擬元素,只會對「有設定 spellcheck="true"
的輸入元素」有作用,因為只針對文字,所以只支援 inline 行內元素相關的樣式屬性,下方的範例開啟後,在多行輸入欄位裡輸入一些英文,當發生拼字錯誤時,拼錯的字就會出現對應的樣式 ( 注意 textarea 有設定 spellcheck="true"
的屬性 )。
<!-- HTML 程式碼 -->
<form action="/test.aspx" method="post">
<textarea spellcheck="true" cols="30" rows="10"> </textarea>
</form>
<!-- CSS 程式碼 -->
<style>
::spelling-error {
color: red;
background: pink;
}
</style>
小結
其實 W3C 還定義了許多有趣的虛擬元素,例如 ::backdrop
( dialog 背景 )、::cue
( 影片字幕樣式 )、::highlight()
( 文字高光樣式 )、::grammar-error
( 文法拼寫錯誤 ) 等等,但可惜目前支援度仍然不高且不太實用,如果未來瀏覽器陸續支援,或許可以發現其中的奧妙之處吧。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~