大家好,我是 Eric。
昨天我們正式進入佈景主題的核心之一,CSS。除了內嵌樣式之外,在網站開發時,最常用的仍然是 CSS 檔案,以及 <style>
標籤兩種做法。原因無他,就是要方便管理。
然而,不同於內嵌樣式,我們要透過 CSS 選擇器 (CSS Selector) 的方法,來指定要變更樣式的元素。
今天,我們就要透過 Twenty Twenty 這個佈景主題的 style.css 檔案,來解釋各種選擇器的概念。
首先,先補充一下,我們通常會將在 HTML 的篇章中提到的語意化標籤所包覆的整個區塊,稱為一個「元素」(element)。
我們先看第 116 行:
/* style.css Line 116 */
html {
font-size: 62.5%; /* 1rem = 10px */
}
這段語法的功能,在重新定義網站的字型大小 (root em,是字型大小的單位,後面章節會再做說明),使 1rem 等於 16px * 62.5% = 10px。
我們再來看看第 946 行:
/* style.css Line 946 */
section {
padding: 5rem 0;
width: 100%;
}
這段語法代表所有的 <section>
區塊的上下編框間距 (padding) 為 5rem,而左右編框間距為 0。
基本語法:
#元素 ID {
樣式名稱: 樣式值;
}
在 HTML 的章節中,我們提到,每個元素必定通用的屬性 (attributes) 之一,就是 id
。舉例來說,我們再度回到 header.php 的第 33 行:
<!-- header.php Line 33 -->
<header id="site-header" class="header-footer-group" role="banner">
<div class="header-inner section-inner">
<div class="header-titles-wrapper">
我們可以看到,在 Twenty Twenty 中,我們的頁首 ID 是 site-header
。
那要如何選擇頁首呢?我們使用的是 #
選擇器。我們可以參考 style.css 的第 1314 行:
#site-header {
background: #fff;
position: relative;
}
透過這個選擇器,我們告訴瀏覽器,具有 ID site-header
的元素,他的背景會是白色的,而該元素對上層元素的定位方式,是透過相對位置 (position: relative
,由上而下、由左而右堆疊) 的方式來定位。其他定位方式會在後續章節詳細說明。
透過 ID 選擇器的最大好處,就是每個頁面中,ID 不會重複。因此對於需要精確選擇特定元素時,都會透過 ID 選擇器來指定元素。
基本語法:
.類型 {
樣式名稱: 樣式值;
}
在 HTML 的章節中,我們提到,每個元素必定通用的另一個屬性,就是類型 (class
)。舉例來說,我們先看到代表內文範本的 content.php 檔案中,第 30 行:
<!-- template-parts/content.php Line 30 -->
<div class="entry-content">
<?php
if ( is_search() || ! is_singular() && 'summary' === get_theme_mod( 'blog_content', 'full' ) ) {
the_excerpt();
} else {
the_content( __( 'Continue reading', 'twentytwenty' ) );
}
?>
</div><!-- .entry-content -->
我們一樣先跳過 PHP(是用來判斷要顯示全文內容,或是文章摘要)。在這裡,我們用 <div clas="entry-content"></div>
畫出了一個存放實際內容的區域。接著,我們再看到 style.css 中的第 3428 行:
/* style.css Line 3428 */
.entry-content {
line-height: 1.5;
}
我們看到,在這個語法中,我們透過 .entry-content
這個標記方式,來選擇包含 entry-content
這個類別的所有元素,使其包覆的所有元素行距都是 1.5 倍行高。因為我們選擇的是類型,所以不只是 <div clas="entry-content"></div>
,下列的各種元素都適用:
<section class="entry-content">
<h2>情況一:不同標籤套用同樣的類型也適用。</h2>
</section>
<div class="entry-content content-wrap">
<p>情況二:多個類型中,只要其中包含了 entry-content 就適用。</p>
</div>
<div class="entry-content">
<p class="entry-content">
情況三:如果在不同階層各用了同樣的類型,有些樣式會疊加,有些樣式則會由最接近的元素覆蓋。
</p>
</div>
基本語法,更多的屬性選擇器可以參考 w3schools:
[attr="屬性值"]
[attr^="屬性值開頭為.."]
[attr*="屬性值包含.."]
這種做法較常出現在替表單欄位設定樣式的時候。我們直接來看 style.css 的第 795 行:
/* style.css Line 795 */
input[type="submit"] {
-webkit-appearance: none;
-moz-appearance: none;
background: #cd2653;
border: none;
border-radius: 0;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 1.5rem;
font-weight: 600;
letter-spacing: 0.0333em;
line-height: 1.25;
margin: 0;
opacity: 1;
padding: 1.1em 1.44em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: opacity 0.15s linear;
}
上面的例子,就是選擇表單提交按鈕 <input type="submit">
,並賦予其相對應的樣式。
基本語法:
選擇器 1,
選擇器 2,
選擇器 3,
...,
選擇器 n {
樣式名稱: 樣式值;
}
如果你是直接檢視 style.css 的檔案,你會發現我在前一小節擷取的語法片段並不完全。實際上,完整的選擇器長這樣:
/* style.css Line 788 */
button,
.button,
.faux-button,
.wp-block-button__link,
.wp-block-file .wp-block-file__button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: none;
-moz-appearance: none;
background: #cd2653;
border: none;
border-radius: 0;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 1.5rem;
font-weight: 600;
letter-spacing: 0.0333em;
line-height: 1.25;
margin: 0;
opacity: 1;
padding: 1.1em 1.44em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: opacity 0.15s linear;
}
沒錯,如果你想要同時針對不同選擇器,賦予類似的樣式,你可以透過半形逗號 ,
來區隔多個選擇器。除了上述的例子外,style.css 在一開始定義預設樣式時,也大量的使用多選的方式。例如替 <h1> ~ <h6>
設定預設的字重與行高:
/* style.css Line 292 */
h1,
h2,
h3,
h4,
h5,
h6,
.faux-heading {
font-feature-settings: "lnum";
font-variant-numeric: lining-nums;
font-weight: 700;
letter-spacing: -0.0415625em;
line-height: 1.25;
margin: 3.5rem 0 2rem;
}
基本語法:
#元素 ID.類型 1.類型 2,
元素#元素 ID,
元素#元素 ID.類型 1,
元素.類型 1.類型 2 {
樣式名稱: 樣式值;
}
除了多重選擇外,另一種選擇方式就是多重選擇器 (聽起來有點拗口,歡迎提供更好的稱呼)。我們可以參考 style.css 的第 433 行:
hr.styled-separator {
background: linear-gradient(to left, currentColor calc(50% - 16px), transparent calc(50% - 16px), transparent calc(50% + 16px), currentColor calc(50% + 16px));
background-color: transparent !important;
border: none;
height: 0.1rem;
overflow: visible;
position: relative;
}
在這個範例中,Twenty Twenty 替具有 style-separator
類型的水平分隔線 <hr>
定義漸層樣式。也就是說:
<hr class="styled-separator" /><!-- 這一條有漸層樣式 -->
<hr /><!-- 這一條就不會有漸層樣式 -->
隨著網站的規模變龐大,有時候我們可能會在不同的階層,使用了相同的類型,或是在不同的階層中,使用相同的元素。
試想一下我們在 HTML 解說語意化標籤的案例:
<article class="film_review">
<header>
<h2>Jurassic Park</h2>
</header>
<section class="main_review">
<p>Dinos were great!</p>
</section>
<section class="user_reviews">
<article class="user_review">
<p>Way too scary for me.</p>
<footer>
<p>
Posted on
<time datetime="2015-05-16 19:00">May 16</time>
by Lisa.
</p>
</footer>
</article>
<article class="user_review">
<p>I agree, dinos are my favorite.</p>
<footer>
<p>
Posted on
<time datetime="2015-05-17 19:00">May 17</time>
by Tom.
</p>
</footer>
</article>
</section>
<footer>
<p>
Posted on
<time datetime="2015-05-15 19:00">May 15</time>
by Staff.
</p>
</footer>
</article>
如果我們今天只使用 <article>
作為選擇器的話,我們可能會同時套用到作為本文的第一層,與作為獨立留言的第三層 <article>
。因此,如果我們要選擇第三層的 <article>
,我們可以透過下列幾種選擇器。
基本語法:
上層項目選擇器 子項目選擇器 {
樣式名稱: 樣式值;
}
舉例來說,我們可以參考 style.css 的第 1238 行:
/* style.css Line 1238 */
.search-form .search-field {
width: 100%;
}
在這個選擇器下,以下兩種狀況的 search-field
這個類型,都會套用到寬度 100% 的樣式。
<form class="search-form">
<label for="search-field">情況一:搜尋欄位在 search-form 正下層</label>
<input class="search-field" type="text" id="search-field">
</form>
<form class="search-form">
<div class="search-wrapper">
<label for="search-field">情況二:搜尋欄位在 search-form 下下層</label>
<input class="search-field" type="text" id="search-field">
</div>
</form>
基本語法:
上層項目選擇器 > 子項目選擇器 {
樣式名稱: 樣式值;
}
如果,我們將 style.css 的第 1238 行改寫成以下語法:
/* style.css Line 1238 */
.search-form > .search-field {
width: 100%;
}
在這個選擇器下,同樣的例子中,只有情況一會套用到寬度 100% 的樣式。
<form class="search-form">
<label for="search-field">情況一:這個會套用</label>
<input class="search-field" type="text" id="search-field">
</form>
<form class="search-form">
<div class="search-wrapper">
<label for="search-field">情況二:這個不會套用</label>
<input class="search-field" type="text" id="search-field">
</div>
</form>
關於多重選擇器與子項目選擇器的案例,可以參考 PJChender 的文章,文章中的 Codepen 範例可以更直接地看到不同選擇器的差異。
今天的文章,說明了基本形式的 CSS 選擇器,包含了單選、多選、多重選擇、子項目選擇。這些選擇器足以應付 70% 的版面配置,但是有時單用這些選擇器,沒有辦法解決下面的一些需求:
<h1>
元素想要設定不同的邊界 (margin)下一章,我們會來介紹 CSS 選擇器的進階型態,包含虛擬元素 (pseudo element)、虛擬類別 (pseudo class) 以及同層級結合器 (sibling combinator)。