我們在「HTML 簡介」一文中簡單介紹了屬性,現在就讓我們深入探討屬性。
屬性是 HTML 如此強大的關鍵。屬性是開頭標記中以空格分隔的名稱和名稱/值組合,可提供元素的資訊和功能。
屬性可定義元素的行為、連結和功能。部分屬性是全域屬性,也就是說,這些屬性可出現在任何元素的開啟標記中。其他屬性則適用於部分元素,但並非所有元素都適用,而其他屬性則是元素專屬,僅與單一元素相關。在 HTML 中,除了布林屬性和部分列舉屬性外,所有屬性都需要值。
如果屬性值包含空格或特殊字元,則必須以引號將值括住。因此,為了提高可讀性,我們一律建議使用引號。
雖然 HTML 不會區分大小寫,但部分屬性值會區分大小寫。HTML 規格中的值不區分大小寫。定義的字串值 (例如類別和 ID 名稱) 會區分大小寫。如果屬性值在 HTML 中區分大小寫,則在 CSS 和 JavaScript 中用於屬性選取器時,會區分大小寫;否則則不會區分大小寫。
<!-- the type attribute is case insensitive: these are equivalent -->
<input type="text">
<input type="TeXt">
<!-- the id attribute is case sensitive: they are not equivalent -->
<div id="myId">
<div id="MyID">
布林值屬性
如果有布林值屬性,則一律為 true。布林值屬性包括 autofocus
、inert
、checked
、disabled
、required
、reversed
、allowfullscreen
、default,
、loop
、autoplay
、controls
、muted
、readonly
、multiple,
和 selected
。如果有一個或多個屬性,元素就會停用、設為必填或唯讀等。如果沒有,則不會。
布林值可以省略、設為空字串,或設為屬性名稱;但值不一定要設為字串 true
。所有值 (包括 true
、false
和 😀
) 在無效的情況下都會解析為 true。
以下三個標記具有相同效果:
<input required>
<input required="">
<input required="required">
如果屬性值為 false,請省略該屬性。如果屬性為 true,請加入該屬性,但不要提供值。舉例來說,required="required"
不是 HTML 中的有效值,但由於 required
是布林值,因此無效值會解析為 true。不過,無效的列舉屬性不一定會解析為遺漏值的相同值,因此,與其記住哪些屬性是布林值或列舉值,並可能提供無效值,不如養成省略值的習慣。
在切換為 true 和 false 之間時,請使用 JavaScript 新增及移除屬性,而非切換值。
const myMedia = document.getElementById("mediaFile");
myMedia.removeAttribute("muted");
myMedia.setAttribute("muted");
請注意,在 SVG 等 XML 語言中,所有屬性都必須包含值,包括布林屬性。
列舉屬性
有時會將列舉屬性與布林屬性搞混。這些是 HTML 屬性,具有一組預先定義的有效值。與布林屬性一樣,如果屬性存在但缺少值,則會使用預設值。舉例來說,如果您加入 <style contenteditable>
,系統會將其設為 <style contenteditable="true">
。
不過,與布林屬性不同,省略屬性並不代表屬性為 false;如果屬性存在但缺少值,不一定是 true;而且無效值的預設值不一定與空字串相同。接著,如果 contenteditable
遺漏或無效,則預設為 inherit
,並可明確設定為 false
。
預設值取決於屬性。與布林值不同,屬性不會自動設為「true」,如果您加入 <style contenteditable="false">
,就無法編輯該元素。如果值無效,例如 <style contenteditable="😀">
,或令人意外的 <style contenteditable="contenteditable">
,則該值無效,並預設為 inherit
。
在大多數列舉屬性案例中,缺少和無效的值是一樣的。舉例來說,如果 <input>
上的 type
屬性遺漏、存在但沒有值,或是有無效值,則預設為 text
。雖然這種行為很常見,但並非規則。因此,請務必瞭解哪些屬性是布林值,哪些屬性是列舉值;盡可能省略值,以免出錯,並視需要查詢值。
全域屬性
全域屬性可在任何 HTML 元素上設定,包括 <head>
中的元素。超過 30 個全域屬性。雖然這些屬性理論上可新增至任何 HTML 元素,但某些全域屬性在某些元素上設定後不會生效;舉例來說,如果在 <meta>
上設定 hidden
,中繼內容就不會顯示。
id
全域屬性 id
可用於定義元素的專屬 ID。這項資訊可用於多種用途,包括:
- 連結片段 ID 的目標。- 找出用於撰寫指令碼的元素。- 將表單元素與標籤建立關聯。- 為輔助技術提供標籤或說明。- 在 CSS 中以高特異性或屬性選取器指定樣式。
id
值為不含空格的字串。如果包含空格,文件不會中斷,但您必須在 HTML、CSS 和 JS 中使用轉義字元指定 id
。所有其他字元皆有效。id
值可以是 😀
或 .class
,但這不是明智的做法。為方便您現在和未來的程式設計作業,請將 id
的第一個字元設為英文字母,並只使用 ASCII 字母、數字、_
和 -
。id
值會區分大小寫,因此建議您採用 id
命名慣例,並且一律遵循,
id
應為文件的唯一值。如果使用 id
的次數超過一次,網頁的版面配置可能不會中斷,但 JavaScript、連結和元素互動可能會發生異常。
連結片段 ID
導覽列包含四個連結。我們稍後會介紹連結元素,但目前請先瞭解連結不限於以 HTTP 為基礎的網址;連結可以是目前文件 (或其他文件) 中網頁部分的片段 ID。
在機器學習工作坊網站上,頁面標題中的導覽列包含四個連結:
href 屬性會提供超連結,當使用者啟用連結時,系統就會將使用者導向該超連結。如果網址包含井字號 (#
),後面接著字串,該字串就是片段 ID。如果該字串與網頁中元素的 id
相符,則該片段就是該元素的錨點或書籤。瀏覽器會捲動至錨點定義的位置。
這四個連結會指向網頁的四個部分,並透過 id
屬性加以標示。當使用者點選導覽列中的任何一個連結時,片段 ID 連結的元素 (包含與 #
不相符的 ID 的元素) 就會捲動至畫面中。
機器學習工作坊的 <main>
內容包含四個具有 ID 的部分。當網站訪客點選 <nav>
中的其中一個連結時,系統會捲動含有該片段 ID 的部分,讓該部分顯示在畫面上。標記類似於:
<section id="reg">
<h2>Machine Learning Workshop Tickets</h2>
</section>
<section id="about">
<h2>What you'll learn</h2>
</section>
<section id="teachers">
<h2>Your Instructors</h2>
<h3>Hal 9000 <span>&</span> EVE</h3>
</section>
<section id="feedback">
<h2>What it's like to learn good and do other stuff good too</h2>
</section>
比較 <nav>
連結中的片段 ID,您會發現每個 ID 都與 <main>
中的 <section>
相符。id
瀏覽器會提供免費的「頁面頂端」連結。設定 href="#top"
(大小寫不敏感) 或 href="#"
時,系統會將使用者捲動至網頁頂端。
href
中的井字號分隔符並非片段 ID 的一部分。片段 ID 一律是網址的最後部分,不會傳送至伺服器。
CSS 選取器
在 CSS 中,您可以使用 ID 選取器 (例如 #feedback
) 或以較不具特徵的大小寫敏感屬性選取器 ([id="feedback"]
) 指定各個區段。
影片腳本
在 MLW.com 上,有一個僅供滑鼠使用者的復活節彩蛋。按一下燈具開關,即可開啟或關閉頁面。
燈具開關圖片的標記如下:
html
<img src="svg/switch2.svg" id="switch"
alt="light switch" class="light" />
id
屬性可用於 getElementById()
方法的參數,並搭配 #
前置字,做為 querySelector()
和 querySelectorAll()
方法參數的一部分。
const switchViaID = document.getElementById("switch");
const switchViaSelector = document.querySelector("#switch");
我們使用這項功能的 JavaScript 函式,可根據元素的 id
屬性指定元素:
<script>
/* switch is a reserved word in js, so we us onoff instead */
const onoff = document.getElementById('switch');
onoff.addEventListener('click', function(){
document.body.classList.toggle('black');
});
</script>
<label>
HTML <label>
元素具有 for
屬性,其值為所關聯表單控制項的 id
。在每個表單控制項上加入 id
,並將每個控制項與標籤的 for
屬性配對,即可建立明確的標籤,確保每個表單控制項都有相關聯的標籤。
雖然每個標籤只能與一個表單控制項建立關聯,但一個表單控制項可能會有多個相關聯的標籤。
如果表單控制項位於 <label>
開頭和結尾標記之間,則不需要 for
和 id
屬性:這稱為「隱含」標籤。標籤可讓所有使用者瞭解每個表單控制項的用途。
<label>
Send me a reminder <input type="number" name="min"> before the workshop resumes
</label>.
for
和 id
之間的關聯可讓輔助技術使用者取得資訊。此外,按一下標籤上的任一位置,系統會將焦點移至相關元素,並擴大控制項的點選區域。這項功能不僅有助於解決手指靈活度較低,導致滑鼠操作不準確的問題,也能協助所有行動裝置使用者,因為他們的手指比單選按鈕還寬。
在這個程式碼範例中,假測驗的第五個假問題是單選選擇題。每個表單控制項都有明確的標籤,且每個控制項都有專屬的 id
。為避免 ID 不小心重複,ID 值會結合問題編號和值。
當您加入圓形按鈕時,由於標籤會說明圓形按鈕的值,因此我們會將所有同名按鈕納入 <fieldset>
,其中 <legend>
是整個集合的標籤或問題。
其他無障礙用途
id
在無障礙和可用性方面的用途不限於標籤。在文字簡介中,我們將 <section>
轉換為區域地標,方法是將 <h2>
的 id
參照為 <section>
的 aria-labelledby
值,以提供可存取的名稱:
<section id="about" aria-labelledby="about_heading">
<h2 id="about_heading">What you'll learn</h2>
有超過 50 個 aria-*
狀態和屬性可用於確保無障礙存取。aria-labelledby
、aria-describedby
、aria-details
和 aria-owns
的值為以空格分隔的 id
參照清單。aria-activedescendant
可識別目前已取得焦點的子項元素,其值為單一 id
參照:具有焦點的單一元素 (一次只能將焦點放在一個元素)。
class
class
屬性提供另一種使用 CSS (和 JavaScript) 指定元素的方式,但在 HTML 中沒有其他用途 (不過架構和元件程式庫可能會使用這些屬性)。class 屬性的值為以空格分隔的清單,其中包含元素的區分大小寫類別。
建立完善的語意結構,即可根據元素的放置位置和功能進行指定。良好的結構可讓您使用子元素選取器、關聯選取器和屬性選取器。在本節中瞭解屬性時,請考量如何為具有相同屬性或屬性值的元素設定樣式。並非不應使用 class 屬性,而是大多數開發人員都不知道自己通常不需要使用這個屬性。
到目前為止,MLW 並未使用任何類別。是否可以在沒有單一類別名稱的情況下啟動網站?我們會看看情況。
style
style
屬性可用於套用內嵌樣式,也就是套用至已設定該屬性的單一元素的樣式。style
屬性的值為 CSS 屬性值組合,其值的語法與 CSS 樣式區塊的內容相同:屬性後面會加上半形冒號,就像在 CSS 中一樣,每個宣告結尾都會加上半形冒號,並在值後方顯示。
樣式只會套用至屬性設定的元素,如果在巢狀元素或 <style>
區塊或樣式表單中,沒有其他樣式宣告覆寫,則子項會繼承已繼承的屬性值。由於該值只包含單一樣式區塊的內容,且只會套用至該元素,因此無法用於產生的內容、建立關鍵影格動畫或套用任何其他 at-rule。
雖然 style
確實是全域屬性,但我們不建議使用。請改為在個別檔案中定義樣式。不過,style
屬性在開發期間相當實用,可用於快速設定樣式,例如用於測試。接著,將「解決方案」樣式貼到已連結的 CSS 檔案中。
tabindex
您可以將 tabindex
屬性新增至任何元素,讓該元素接收焦點。tabindex
值會定義是否要將其加入分頁順序,以及是否要將其加入非預設分頁順序。
tabindex
屬性的值為整數。負值 (慣用做法是使用 -1
) 可讓元素接收焦點 (例如透過 JavaScript),但不會將元素加入 Tab 鍵序列。tabindex
值為 0
時,元素可供焦點鎖定,並可透過按順序分頁存取,並依來源程式碼順序新增至網頁的預設分頁順序。如果值為 1
或更高,元素就會進入優先焦點序列,因此不建議使用。
這個頁面上的分享功能使用 <share-action>
自訂元素,做為 <button>
。零的 tabindex
是為了將自訂元素加入鍵盤預設的 tab 順序:
<share-action authors="@estellevw" data-action="click" data-category="web.dev" data-icon="share" data-label="share, twitter" role="button" tabindex="0">
<svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
<use href="#shareIcon" />
</svg>
<span>Share</span>
</share-action>
button
的 role
會向螢幕閱讀器使用者說明,這個元素應以按鈕的形式運作。使用 JavaScript 可確保按鈕功能的承諾得以保留,包括處理 click 和 keydown 事件,以及處理 Enter 和空白鍵的按鍵動作。
表單控制項、連結、按鈕和可編輯內容元素可接收焦點;當鍵盤使用者按下 Tab 鍵時,焦點會移至下一個可聚焦的元素,就像已設定 tabindex="0"
一樣。根據預設,其他元素無法聚焦。將 tabindex
屬性新增至這些元素,即可讓這些元素在原本不會接收焦點時接收焦點。
如果文件包含 tabindex
為 1
或以上的元素,這些元素會納入個別的分頁序列。您會在 CodePen 中發現,在開始分頁之前,系統會以從最低值到最高值的順序,依照分頁順序逐一檢查來源順序中的值。
變更 Tab 順序可能會導致使用者體驗不佳。使用者很難透過輔助技術 (鍵盤和螢幕閱讀器) 瀏覽內容。開發人員也難以管理及維護。焦點很重要,我們有一個單元專門討論焦點和焦點順序。
role
role
屬性屬於 ARIA 規格,而非 WHATWG HTML 規格。role
屬性可用於為內容提供語義意義,讓螢幕閱讀器可向網站使用者說明物件的預期使用者互動方式。
有些常見的 UI 小工具 (例如 組合方塊、選單列、分頁清單和樹狀結構資料表) 沒有對應的本機 HTML 元素。舉例來說,建立分頁式設計模式時,可以使用 tab
、tablist
和 tabpanel
角色。實際上可看到使用者介面的使用者,已透過經驗學會如何瀏覽小工具,並透過點選相關聯的分頁,讓不同面板顯示。當一組按鈕用於顯示不同面板時,如果將 tab
角色與 <button role="tab">
一併納入,螢幕閱讀器使用者就能瞭解目前擁有焦點的 <button>
可以切換相關面板,而非實作一般按鈕類似的功能。
role
屬性不會變更瀏覽器行為或變更鍵盤或指標裝置互動方式。將 role="button"
新增至 <span>
不會將其轉換為 <button>
。因此,建議您依預期用途使用語意式 HTML 元素。不過,如果無法使用正確的元素,role
屬性可在非語意元素改裝為語意元素的角色時,通知螢幕閱讀器使用者。
contenteditable
將 contenteditable
屬性設為 true
的元素可編輯、可聚焦,並會像是已設為 tabindex="0"
一樣加入分頁順序。Contenteditable
是列舉屬性,支援 true
和 false
的值,如果屬性不存在或有無效值,則預設值為 inherit
。
以下三個開啟標記是等效的:
<style contenteditable>
<style contenteditable="">
<style contenteditable="true">
如果您加入 <style contenteditable="false">
,元素就無法編輯 (除非預設可編輯,例如 <textarea>
)。如果值無效 (例如 <style contenteditable="😀">
或 <style contenteditable="contenteditable">
),則預設為 inherit
。
如要切換狀態,請查詢 HTMLElement.isContentEditable 只讀屬性的值。
const editor = document.getElementById("myElement");
if(editor.contentEditable) {
editor.setAttribute("contenteditable", "false");
} else {
editor.setAttribute("contenteditable", "");
}
或者,您也可以將 editor.contentEditable
設為 true
、false
或 inherit
,藉此指定這項屬性。
全域屬性可套用至所有元素,包括 <style>
元素。您可以使用屬性和少量 CSS 建立即時 CSS 編輯器。
<style contenteditable>
style {
color: inherit;
display:block;
border: 1px solid;
font: inherit;
font-family: monospace;
padding:1em;
border-radius: 1em;
white-space: pre;
}
</style>
請嘗試將 style
的 color
變更為 inherit
以外的屬性。然後嘗試將 style
變更為 p
選取器。請勿移除 display 屬性,否則樣式區塊會消失。
自訂屬性
我們只略微介紹了 HTML 全域屬性。還有更多屬性只適用於一或少數元素。即使定義了數百個屬性,您可能還是需要規格中未列出的屬性。HTML 就能滿足你的需求。
只要加上 data-
前置字串,即可建立任何自訂屬性。屬性名稱可以是任何以 data-
開頭,後面接任何小寫字元的字串,但開頭不得為 xml
,且不得包含冒號 (:
)。
雖然 HTML 會容許您建立不支援的屬性 (不以 data
開頭),且不會因此中斷,但如果您建立的屬性不以 data
開頭,甚至自訂屬性以 xml
開頭或包含 :
,您還是可以建立以 data-
開頭的有效自訂屬性。使用自訂資料屬性,您就不會不小心使用現有的屬性名稱。自訂資料屬性可確保未來的穩定性。
雖然瀏覽器不會針對任何特定 data-
前置字首屬性實作預設行為,但內建資料集 API 可逐一處理自訂屬性。自訂屬性是透過 JavaScript 傳達應用程式專屬資訊的絕佳方式。以 data-name
的形式將自訂屬性新增至元素,然後在該元素上使用 dataset[name]
透過 DOM 存取這些屬性。
<blockquote data-machine-learning="workshop"
data-first-name="Blendan" data-last-name="Smooth"
data-formerly="Margarita Maker" data-aspiring="Load Balancer"
data-year-graduated="2022">
HAL and EVE could teach a fan to blow hot air.
</blockquote>
您可以使用完整的屬性名稱使用 getAttribute()
,也可以利用更簡單的 dataset
屬性。
el.dataset["machineLearning"]; // workshop
e.dataset.machineLearning; // workshop
dataset
屬性會傳回每個元素 data-
屬性的 DOMStringMap
物件。<blockquote>
上有幾個自訂屬性。資料集屬性表示您無須知道這些自訂屬性為何,即可存取其名稱和值:
for (let key in el.dataset) {
customObject[key] = el.dataset[key];
}
本文中的屬性為全域屬性,也就是說,這些屬性可套用至任何 HTML 元素 (但並非所有屬性都會對這些元素產生影響)。接下來,我們將進一步探討前述圖片中未提及的兩個屬性 (target
和 href
),以及其他幾個元素專屬屬性,進一步瞭解連結。
進行隨堂測驗
測驗您對屬性的瞭解程度。
文件中的 id
不得重複。
選取正確格式化自訂屬性。
data-birthday
birthday
data:birthday