我們在「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");
請注意,在 XML 語言 (例如 SVG) 中,所有屬性都必須包含值,包括布林屬性。
列舉屬性
列舉屬性有時會與布林屬性混淆。這些是 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 元素,但部分全域屬性在某些元素上設定時不會生效;舉例來說,設定為中繼內容的 hidden
不會顯示。<meta>
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
的用途不限於標籤。在文字簡介中,系統會參照 <h2>
的 id
做為 <section>
的 aria-labelledby
值,將 <section>
轉換為區域地標,以提供可存取的名稱:
<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 中沒有其他用途 (不過架構和元件程式庫可能會使用)。類別屬性的值是元素的大小寫區分類別清單,並以空格分隔。
建立健全的語意結構,即可根據元素的位置和功能指定目標。健全的結構 可使用後代元素選取器、關係選取器和屬性選取器。在本節中瞭解屬性時,請思考如何為具有相同屬性或屬性值的元素設定樣式。並非不該使用類別屬性,而是大多數開發人員並未意識到自己通常不需要使用。
到目前為止,MLW 尚未使用任何類別。如果沒有單一類別名稱,可以發布網站嗎?我們拭目以待。
style
style
屬性可套用內嵌樣式,也就是套用至設定屬性的單一元素。style
屬性的值為 CSS 屬性值配對,值的語法與 CSS 樣式區塊的內容相同:屬性後方會加上半形冒號 (與 CSS 相同),而每個宣告的值後方會加上半形分號。
樣式只會套用至設定屬性的元素,後代會繼承繼承的屬性值,除非巢狀元素或 <style>
區塊或樣式表中的其他樣式宣告覆寫這些值。由於這個值相當於套用至該元素的單一樣式區塊內容,因此無法用於產生的內容、建立影格動畫,或套用任何其他 at 規則。
雖然 style
確實是全域屬性,但我們不建議使用。請改為在個別檔案中定義樣式。
不過,在開發期間,style
屬性可派上用場,例如用於測試時,可快速啟用樣式。然後將「解決方案」樣式貼到連結的 CSS 檔案中。
tabindex
只要將 tabindex
屬性新增至任何元素,即可讓該元素接收焦點。tabindex
值會定義是否要將元素加入索引標籤順序,以及是否要加入非預設的索引標籤順序 (選用)。
tabindex
屬性的值為整數。負值 (慣例是使用 -1
) 可讓元素接收焦點 (例如透過 JavaScript),但不會將元素新增至 Tab 鍵順序。tabindex
值為 0
時,元素會變成可聚焦,且可透過 Tab 鍵存取,並依來源程式碼順序新增至網頁的預設 Tab 鍵順序。如果值為 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>
role
的 button
會告知螢幕閱讀器使用者,這個元素應像按鈕一樣運作。JavaScript 用於確保按鈕功能承諾得以實現,包括處理 click 和 keydown 事件,以及處理 Enter 和 Space 鍵的按鍵事件。
表單控制項、連結、按鈕和可編輯內容元素都能接收焦點;鍵盤使用者按下 Tab 鍵時,焦點會移至下一個可聚焦的元素,就像已設定 tabindex="0"
一樣。其他元素預設無法聚焦。在這些元素中新增 tabindex
屬性,即可讓這些元素在其他情況下無法接收焦點時,仍能接收焦點。
如果文件包含 tabindex
為 1
以上的元素,這些元素會納入個別的 Tab 鍵順序。如您在 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
,則可編輯、可聚焦,並會加入 Tab 鍵順序,如同設定 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
選取器。
請勿移除顯示屬性,否則樣式區塊會消失。
自訂屬性
我們只介紹了 HTML 全域屬性的基本概念。還有更多屬性僅適用於一或一組有限的元素。 即使定義了數百個屬性,您可能還是需要規格中沒有的屬性。HTML 就能滿足你的需求。
只要加上 data-
前置字元,即可建立任何自訂屬性。屬性名稱開頭可為 data-
,後接任何小寫字元序列,但不得以 xml
開頭,也不得包含半形冒號 (:
)。
HTML 具有容錯能力,因此即使您建立的自訂屬性不支援,或開頭不是 data
,甚至開頭是 xml
或包含 :
,也不會發生錯誤。不過,建立開頭為 data-
的有效自訂屬性仍有許多好處。使用自訂資料屬性時,您會知道自己不會誤用現有的屬性名稱。自訂資料屬性可因應未來變化。
雖然瀏覽器不會為任何特定 data-
前置字元屬性實作預設行為,但內建的資料集 API 可用於疊代自訂屬性。自訂屬性是透過 JavaScript 傳達應用程式專屬資訊的絕佳方式。以 data-name
形式將自訂屬性新增至元素,並透過 DOM 使用相關元素上的 dataset[name]
存取這些屬性。
<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
data-birthday
birthday