屬性

我們在「HTML 簡介」一文中簡單介紹了屬性,現在就讓我們深入探討屬性。

屬性是 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。布林值屬性包括 autofocusinertcheckeddisabledrequiredreversedallowfullscreendefault,loopautoplaycontrolsmutedreadonlymultiple,selected。如果有一個或多個屬性,元素就會停用、設為必填或唯讀等。如果沒有,則不會。

布林值可以省略、設為空字串,或設為屬性名稱;但值不一定要設為字串 true。所有值 (包括 truefalse😀) 在無效的情況下都會解析為 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、連結和元素互動可能會發生異常。

導覽列包含四個連結。我們稍後會介紹連結元素,但目前請先瞭解連結不限於以 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>&amp;</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> 開頭和結尾標記之間,則不需要 forid 屬性:這稱為「隱含」標籤。標籤可讓所有使用者瞭解每個表單控制項的用途。

<label>
  Send me a reminder <input type="number" name="min"> before the workshop resumes
</label>.

forid 之間的關聯可讓輔助技術使用者取得資訊。此外,按一下標籤上的任一位置,系統會將焦點移至相關元素,並擴大控制項的點選區域。這項功能不僅有助於解決手指靈活度較低,導致滑鼠操作不準確的問題,也能協助所有行動裝置使用者,因為他們的手指比單選按鈕還寬。

在這個程式碼範例中,假測驗的第五個假問題是單選選擇題。每個表單控制項都有明確的標籤,且每個控制項都有專屬的 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-labelledbyaria-describedbyaria-detailsaria-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>

buttonrole 會向螢幕閱讀器使用者說明,這個元素應以按鈕的形式運作。使用 JavaScript 可確保按鈕功能的承諾得以保留,包括處理 clickkeydown 事件,以及處理 Enter 和空白鍵的按鍵動作。

表單控制項、連結、按鈕和可編輯內容元素可接收焦點;當鍵盤使用者按下 Tab 鍵時,焦點會移至下一個可聚焦的元素,就像已設定 tabindex="0" 一樣。根據預設,其他元素無法聚焦。將 tabindex 屬性新增至這些元素,即可讓這些元素在原本不會接收焦點時接收焦點。

如果文件包含 tabindex1 或以上的元素,這些元素會納入個別的分頁序列。您會在 CodePen 中發現,在開始分頁之前,系統會以從最低值到最高值的順序,依照分頁順序逐一檢查來源順序中的值。

變更 Tab 順序可能會導致使用者體驗不佳。使用者很難透過輔助技術 (鍵盤和螢幕閱讀器) 瀏覽內容。開發人員也難以管理及維護。焦點很重要,我們有一個單元專門討論焦點和焦點順序。

role

role 屬性屬於 ARIA 規格,而非 WHATWG HTML 規格role 屬性可用於為內容提供語義意義,讓螢幕閱讀器可向網站使用者說明物件的預期使用者互動方式。

有些常見的 UI 小工具 (例如 組合方塊選單列分頁清單樹狀結構資料表) 沒有對應的本機 HTML 元素。舉例來說,建立分頁式設計模式時,可以使用 tabtablisttabpanel 角色。實際上可看到使用者介面的使用者,已透過經驗學會如何瀏覽小工具,並透過點選相關聯的分頁,讓不同面板顯示。當一組按鈕用於顯示不同面板時,如果將 tab 角色與 <button role="tab"> 一併納入,螢幕閱讀器使用者就能瞭解目前擁有焦點的 <button> 可以切換相關面板,而非實作一般按鈕類似的功能。

role 屬性不會變更瀏覽器行為或變更鍵盤或指標裝置互動方式。將 role="button" 新增至 <span> 不會將其轉換為 <button>。因此,建議您依預期用途使用語意式 HTML 元素。不過,如果無法使用正確的元素,role 屬性可在非語意元素改裝為語意元素的角色時,通知螢幕閱讀器使用者。

contenteditable

contenteditable 屬性設為 true 的元素可編輯、可聚焦,並會像是已設為 tabindex="0" 一樣加入分頁順序。Contenteditable 是列舉屬性,支援 truefalse 的值,如果屬性不存在或有無效值,則預設值為 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 設為 truefalseinherit,藉此指定這項屬性。

全域屬性可套用至所有元素,包括 <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>

請嘗試將 stylecolor 變更為 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 元素 (但並非所有屬性都會對這些元素產生影響)。接下來,我們將進一步探討前述圖片中未提及的兩個屬性 (targethref),以及其他幾個元素專屬屬性,進一步瞭解連結。

進行隨堂測驗

測驗您對屬性的瞭解程度。

文件中的 id 不得重複。

請再試一次。
答對了!

選取正確格式化自訂屬性。

data-birthday
正確
birthday
請再試一次。
data:birthday
再試一次