属性については HTML の概要で簡単に説明しましたので、詳しく見ていきましょう。
HTML は、属性によって強力になっています。属性は、開始タグに表示されるスペース区切りの名前と名前/値のペアで、要素に関する情報と機能を提供します。
属性は、要素の動作、リンク、機能を定義します。一部の属性はグローバルで、どの要素の開始タグ内にも指定できます。すべての属性ではなく、複数の要素に適用される属性や、1 つの要素だけに関連する、要素固有の属性もあります。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
があります。これらの属性が 1 つ(または複数)存在する場合は、その要素は「無効」、「必須」、「読み取り専用」などとなり、存在しない場合は存在しません。
ブール値は、省略するか、空の文字列に設定するか、属性の名前にすることができますが、値を実際に文字列 true
に設定する必要はありません。true
、false
、😀
を含むすべての値は無効ですが、true に解決されます。
次の 3 つのタグは同じです。
<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 であるとは限りません。無効な値のデフォルトは、null 文字列と必ずしも同じになるとは限りません。例を続行すると、contenteditable
が存在しないか無効な場合、デフォルトで inherit
になり、明示的に false
に設定できます。
デフォルト値は属性によって異なります。ブール値とは異なり、属性が存在しても自動的に「true」になるわけではありません。<style contenteditable="false">
が含まれていると、要素は編集できなくなります。値が無効な場合(<style contenteditable="😀">
、驚くことに <style contenteditable="contenteditable">
など)、値は無効になり、デフォルトは inherit
になります。
列挙型属性のほとんどの場合、欠損値と無効な値は同じです。たとえば、<input>
の type
属性が存在しない、存在するが値がない場合、または無効な値がある場合、デフォルトの text
が使用されます。これはよくあることですが、決して正しいものではありません。このため、ブール値と列挙型属性のどちらがブール値であるかを把握することが重要です。可能であれば、値を間違えないように値を省略し、必要に応じて値を調べてください。
グローバル属性
グローバル属性は、<head>
内の要素を含め、任意の HTML 要素で設定できる属性です。30 個を超えるグローバル属性があります。これらはすべて、理論的には任意の HTML 要素に追加できますが、一部のグローバル属性は一部の要素に設定しても効果がありません。たとえば、<meta>
で hidden
をメタ コンテンツとして設定した場合は表示されません。
id
グローバル属性 id
は、要素の一意の識別子を定義するために使用されます。次のようなさまざまな目的で使用します。
- リンクのフラグメント識別子のターゲット。
- スクリプトの要素を特定する。
- フォーム要素をラベルに関連付ける。
- 支援技術のラベルや説明を提供する。
- CSS で(限定度または属性セレクタとして)ターゲティング スタイルを使用する
id
値はスペースを含まない文字列です。スペースが含まれている場合、ドキュメントは破損しませんが、HTML、CSS、JS でエスケープ文字を使用して id
をターゲットにする必要があります。その他の文字はすべて有効です。id
の値には 😀
または .class
を指定できますが、これはおすすめしません。現在と将来の自分にとってプログラミングを簡単にするために、id
の最初の文字を文字にし、ASCII 文字、数字、_
、-
のみを使用します。id
では大文字と小文字が区別されます。そのため、id
の命名規則を決めて使用することをおすすめします。
id
はドキュメントに対して一意である必要があります。id
を複数回使用してもページのレイアウトはおそらく破損しませんが、JavaScript、リンク、要素のインタラクションは想定どおりに動作しない可能性があります。
リンク フラグメント識別子
ナビゲーション バーには 4 つのリンクがあります。リンク要素については後で説明しますが、今のところ、リンクは HTTP ベースの URL に制限されず、現在のドキュメント(または他のドキュメント)のページのセクションのフラグメント識別子にすることができます。
ML ワークショップ サイトでは、ページヘッダーのナビゲーション バーに 4 つのリンクがあります。
href 属性は、リンクを有効にするとユーザーがリダイレクトされるハイパーリンクを提供します。URL にハッシュマーク(#
)の後に文字列が続く場合、その文字列はフラグメント識別子です。この文字列がウェブページ内の要素の id
と一致する場合、フラグメントはその要素のアンカー(ブックマーク)です。ブラウザは、アンカーが定義されたポイントまでスクロールします。
これら 4 つのリンクは、id
属性で識別されるページの 4 つのセクションを指しています。ユーザーがナビゲーション バーの 4 つのリンクのいずれかをクリックすると、フラグメント識別子でリンクされている要素(一致する ID から #
を引いた要素)がスクロールされて表示されます。
機械学習ワークショップの <main>
コンテンツには、ID 付きの 4 つのセクションがあります。サイト訪問者が <nav>
内のリンクのいずれかをクリックすると、そのフラグメント識別子を含むセクションがスクロールされて表示されます。マークアップは次のようになります。
<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>
リンクのフラグメント識別子を比較すると、それぞれが <main>
内の <section>
の id
と一致していることがわかります。ブラウザには無料の「ページ上部」リンクがあります。href="#top"
を設定すると(大文字と小文字を区別しない、または単に href="#"
)、ユーザーをページの最上部までスクロールできます。
href
のハッシュマーク区切り文字は、フラグメント識別子の一部ではありません。フラグメント識別子は常に URL の最後の部分であり、サーバーには送信されません。
CSS セレクタ
CSS では、#feedback
などの ID セレクタや、詳細性を低くするために属性セレクタ [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
属性とペア設定して明示的なラベルを作成すると、すべてのフォーム コントロールにラベルが関連付けられます。
各ラベルは 1 つのフォーム コントロールにのみ関連付けることができますが、フォーム コントロールには複数のラベルを関連付けることができます。
フォーム コントロールが <label>
の開始タグと終了タグの間にネストされている場合、for
属性と id
属性は必要ありません。これを「暗黙的」ラベルと呼びます。ラベルを使用すると、各フォーム コントロールの用途をすべてのユーザーが知ることができます。
<label>
Send me a reminder <input type="number" name="min"> before the workshop resumes
</label>.
for
と id
の関連付けにより、支援技術のユーザーがその情報を利用できるようになります。また、ラベルの任意の場所をクリックすると、関連する要素にフォーカスが移動し、コントロールのクリック領域が広がります。これは、細かい作業に支障があり、マウス操作の精度が低下しているユーザーだけでなく、すべてのモバイル デバイス ユーザーで、ラジオボタンよりも指の幅が広い場合に便利です。
このコード例では、偽のクイズの 5 番目の質問は、単一選択の多肢選択式問題です。各フォーム コントロールには明示的なラベルがあり、それぞれに一意の id
があります。ID が誤って重複しないように、ID の値は質問番号と値を組み合わせたものになります。
ラジオボタンを含める場合、ラベルはラジオボタンの値を説明するため、<legend>
はセット全体のラベル(質問)であり、<fieldset>
に同じ名前のボタンがすべて含まれます。
その他のユーザー補助機能の用途
ユーザー補助とユーザビリティにおける id
の使用は、ラベルに限定されません。テキストの概要では、<section>
の aria-labelledby
の値として <h2>
の id
を参照し、アクセス可能な名前を指定することで、<section>
をリージョン ランドマークに変換しました。
<section id="about" aria-labelledby="about_heading">
<h2 id="about_heading">What you'll learn</h2>
アクセシビリティを確保するために使用できる aria-*
の状態とプロパティは 50 以上あります。aria-labelledby
、aria-describedby
、aria-details
、aria-owns
は、値としてスペース区切りの id
参照リストを取ります。現在フォーカスされている子孫要素を識別する aria-activedescendant
は、値として単一の id
参照を受け取ります。これは、フォーカスされている単一の要素の参照です(一度にフォーカスできるのは 1 つの要素のみです)。
class
class
属性は、CSS(および JavaScript)で要素をターゲティングする場合に役立ちますが、HTML でこれ以外の目的に使用することはできません(フレームワークとコンポーネント ライブラリでは使用できます)。クラス属性は、その要素の値として、大文字と小文字を区別するクラスのスペース区切りリストを受け取ります。
健全なセマンティック構造を構築することで、配置と機能に基づいて要素をターゲットに設定できます。健全な構造により、子孫要素のセレクタ、リレーショナル セレクタ、属性セレクタを使用できるようになります。このセクションで属性について学習する際に、同じ属性または属性値を持つ要素のスタイル設定について検討してください。クラス属性は、使用すべきではないということではなく、多くの場合、その必要がないことをほとんどのデベロッパーが認識していないからです。
これまでのところ、MLW はどのクラスも使用していません。クラス名を 1 つも付けずにサイトを公開することはできますか?わかりました。
style
style
属性を使用すると、インライン スタイルを適用できます。インライン スタイルは、属性が設定されている単一の要素に適用されるスタイルです。style
属性は、CSS プロパティ値のペアを値として受け取ります。値の構文は CSS スタイル ブロックの内容と同じです。CSS と同様にプロパティの後でコロンが続き、宣言の最後にセミコロンが値の後ろで終わります。
スタイルは属性が設定されている要素にのみ適用されます。子孫は、ネストされた要素や <style>
ブロックやスタイルシート内で他のスタイル宣言によってオーバーライドされていなければ、継承されたプロパティ値を継承します。この値は、その要素にのみ適用される単一のスタイル ブロックのコンテンツと同等であるため、生成されたコンテンツ、キーフレーム アニメーションの作成、その他のアットルールの適用には使用できません。
style
は実際にグローバル属性ですが、使用はおすすめしません。別のファイルでスタイルを定義します。とはいえ、style
属性は開発時にテスト目的などでスタイルをすばやく設定できるため便利です。次に、「ソリューション」スタイルを選択して、リンクした CSS ファイルに貼り付けます。
tabindex
任意の要素に tabindex
属性を追加すると、フォーカスを受け取ることができるようになります。tabindex
値は、タブオーダーや、必要に応じてデフォルト以外のタブ順序に追加するかどうかを定義します。
tabindex
属性は、値として整数を取ります。負の値(慣例では -1
)を指定すると、その要素は JavaScript 経由などでフォーカスを受け取ることができるようになりますが、タブ操作にはその要素は追加されません。tabindex
の値を 0
にした場合、タブ操作で要素がフォーカス可能かつ到達可能になり、ソースコード順でページのデフォルトのタブオーダーに追加されます。値を 1
以上に設定すると、要素が優先フォーカス シーケンスに配置されるため、推奨されません。
このページでは、<button>
として機能する <share-action>
カスタム要素を使用した共有機能について説明します。ゼロの tabindex
が含まれていると、カスタム要素をキーボードのデフォルトのタブ順に追加できます。
<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 キーおよび Space キー押下の処理など)が保持されます。
フォーム コントロール、リンク、ボタン、編集可能なコンテンツ要素は、フォーカスを受け取れます。キーボード ユーザーが Tab キーを押すと、tabindex="0"
が設定されているかのように、次のフォーカス可能な要素にフォーカスが移動します。他の要素は、デフォルトではフォーカス不可能です。これらの要素に tabindex
属性を追加すると、フォーカスを取得できないときにフォーカスを受け取れるようになります。
ドキュメント内に tabindex
が 1
以上の要素が含まれている場合、それらの要素は別のタブシーケンスに配置されます。Codepen を見ると、タブは別のシーケンスで始まります(値が低いものから高いものの順に、通常のシーケンスのソース順に処理します)。
タブ操作の表示順序を変更すると、ユーザー エクスペリエンスが大幅に損なわれる可能性があります。これにより、支援技術(キーボードやスクリーン リーダーなど)を使ってコンテンツを操作するのが難しくなります。また、デベロッパーとして管理やメンテナンスを行うのも困難です。フォーカスは重要です。フォーカスとフォーカスの順序についてはモジュール全体で説明します。
role
role
属性は、WHATWG HMTL 仕様ではなく、ARIA 仕様の一部です。role
属性を使用すると、オブジェクトにセマンティックな意味を持たせることができ、スクリーン リーダーはオブジェクトの想定されるユーザー操作についてサイトユーザーに通知できます。
コンボボックス、メニューバー、タブリスト、ツリーグリッドなど、ネイティブ HTML と同等のものがない一般的な UI ウィジェットがいくつかあります。たとえば、タブ形式のデザイン パターンを作成する場合、tab
、tablist
、tabpanel
のロールを使用できます。ユーザー インターフェースを物理的に見ることができる人は、ウィジェットを操作し、関連するタブをクリックしてさまざまなパネルを表示する方法を経験しています。ボタンのグループを使用してさまざまなパネルを表示する際に tab
ロールと <button role="tab">
を含めると、スクリーン リーダーのユーザーは、一般的なボタンのような機能を実装するのではなく、現在フォーカスされている <button>
が関連するパネルを表示に切り替えることができることを把握できます。
role
属性によってブラウザの動作が変更されたり、キーボードやポインタ デバイスの操作が変更されたりすることはありません。<span>
に role="button"
を追加しても <button>
に変換されることはありません。そのため、本来の目的に応じてセマンティック HTML 要素を使用することをおすすめします。ただし、適切な要素を使用できない場合は、role
属性を使用することで、非セマンティックな要素がセマンティック要素の役割にレトロフィットされたことをスクリーン リーダーのユーザーに通知できます。
contenteditable
contenteditable
属性が true
に設定された要素は編集可能で、フォーカス可能で、tabindex="0"
が設定されているかのようにタブオーダーに追加されます。Contenteditable
は true
と false
の値をサポートする列挙型属性です。属性が存在しないか無効な値がある場合、デフォルト値は inherit
です。
次の 3 つの開始タグは同じものです。
<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 グローバル属性について触れただけです。1 つの要素だけに適用される属性や、一部の要素に適用される属性もあります。何百もの属性が定義されている場合でも、仕様にない属性が必要になることがあります。HTML を使えば問題ありません。
data-
接頭辞を追加することで、必要なカスタム属性を作成できます。属性には data-
で始まり、その後に xml
で始まらず、コロン(:
)を含まない小文字の文字列が続く任意の名前を使用できます。
HTML は許容され、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 要素にも適用できます(ただし、すべての属性がこれらの要素に影響するわけではありません)。次に、イントロ画像の 2 つの属性(target
と href
)と、その他の要素固有の属性について、リンクを詳しく調べながら見てみましょう。
理解度チェック
属性に関する知識をテストします。
id
はドキュメント内で一意にする必要があります。
正しい形式のカスタム属性を選択してください。
data-birthday
birthday
data:birthday