HTML解体新書を読んだ
はじめに
フロントエンドの開発に関わるようになり、薄々気づいていたけどもフレームワークの使い方やコンポーネント指向開発以上にhtmlそのものにまつわる悩みが増えました。
知らないことばっかりだった、まだまだがんばります。
特に勉強になったこと
"内容モデル"
この概念を知っただけでもこの本を読んだ意味がありました。普段htmlでマークアップするときには、どの要素がどの要素に入るかを明確に理解してなくて、なんとなくこれはこの中だな、くらいでやってしまってました。HTML Living Standardが読めそう
現行HTMLの基礎になっている概念をインプットできたのでHTMLの言語仕様であるHTML Living Standard も適宜参照できそうです。
レイアウトを作っているときに「ここに横に並べたいときどうすれば」となるので、そのときに扱っている要素の性質を仕様をもとに考えられるようになったかなと思います。
htmlをとっかかりにcssの仕様(Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification)も読めるようになったのでちまちま読んでいます。
考察: ウェブアプリケーションとhtml
書籍を通じて、htmlの要素(タグの種類)とそれの性質がよく使うものを中心に紹介されていました。そもそも、htmlはハイパーテキストをマークアップするための規格であるので、文書には見出しがあって小見出しがあって段落があってその中にリンクが埋め込めて...といった、文書を書くためのツールキットの側面が強いです(もちろん広範なウェブ技術に対応するべく拡張はされていますが)。
昨今DXだ、デジタライゼーションだなどITに推進の機運が高まり続けていて、並行して個人が使えるコンピューティングリソースが潤沢になっています。すると、そのような有り余るリソースを土台にリッチな動きができるウェブアプリケーションの需要も高まり、UIを構成するhtmlには文書を作る以上の役割を担わせています。実際、UIを作っているとタグの並びと見た目があまり噛み合ってない状況の遭遇します。
本来ハイパーテキストをマークアップする規格であったhtmlを入り口にjsを使ったapiコール、非同期での仮想DOM操作などなど飛び技を駆使していることを考えると、一周回ってそのレイアウトにこのタグを使うべきなのか?本来の用途に適しているか?を熟慮する必要性が高まっているなと感じました。ボタンクリックで出てくるドロップダウンをdivでやりきることはできるけど、アクテシビリティや本来の用途考えるとselectで良いケースがその一例です。
書籍で勉強になったこと
ここからは各章でなるほどと思ったことのメモです。
内容モデル(Content model)
ある要素がどのような要素に属することができるかは、ルールで決まっている。このルールのことを内容モデル(Content Model)と呼ぶ。
内容モデルには以下のようなものがある:- Metdadata
- Flow
- Phrasing
- Sectioning
- Heading
- Interactive
- Embeded
<span> <p> このネストはできない </p> </span>ウェブアプリケーションのマークアップによく用いられるdivやp、ulはFlowコンテンツ。spanやstrong, codeといった段落内テキストを修飾するような要素はPhrasingコンテンツ。 以下のようなマークアップはFlowコンテンツにPhrasingコンテンツが含まれる例ということになる。
<p> <span>text</span> </p>
補足: ブロックレベル要素とインラインレベル要素
ブロックレベル要素、インラインレベル要素はCSSの視覚要素レベルで、cssの 視覚整形モデル とHTMLの内容モデルは本質的に異なる概念。 HTML5でレベル分類が一新され、HTML4でインライン要素とされていたものはPhrasingコンテンツとなった。ブロックレベル要素とされていたものはFlowコンテンツに相当するものの、 FlowやPhrasingも含むため1:1に対応しない。
htmlの主要な要素
セクショニング
sectionやnavを用いることで見出しに続くセクションを明示できる。見出し要素(h1 - h6)が入っているFlowコンテンツはsection
を使わずともセクショニングされる。
body, header, footer
html要素2番目の子で、文書の表示する内容を示す。セクショニングルートになる。それぞれ、一つのhtmlに一つだけ含められる。section
一般的なセクションを表現する。通常見出し要素を置くが、それができない場合はdivで囲って代用できる。style
メタデータコンテンツ。metaやtitleと同じ内容モデルなので、`head`に置くことができるグルーピング
blockquoteはFlowコンテンツで、文字をそのまま置くこともできる。pで囲った文字列をそのまま置くこともできる。
別のソースから引用されたセクションがここに表示されます。
整形済みテキスト
preは改行やスペースをそのまま維持した、整形済みテキストとして表示する。
ul li { list-style: none; }
列挙
- ol、ulは自身とliのみ子要素になれる
- ol, ulは空でもよい
- liはFlowコンテンツ。他のFlowコンテンツないしはPhrasingコンテンツを含むことができる。
main要素
mainはその性質上、bodyに一つだけ存在することを想定した要素。hiddenで隠せば複数置くことができ、jsなどでmainの出し分けを行うユースケースを考えられる。mainはbodyの直下に置くこと。
div
divに特別な意味を持たないFlowコンテンツ。主にスタイルやレイアウトのために付与する使い方がある。
テキストレベルセマンティクス
テキストレベルセマンティクスはテキストをマークアップする用途で用いられ、すべてPhrasing contents。
テキストマークアップの要素
テキストレベルで修飾する、Phrasingコンテンツのマークアップ例。すべて対応するHTMLタグでマークアップされている。リンク関連
a
内容モデルはtransparent。親要素の内容モデルを引き継ぐので、divの子要素になっていればFlowコンテンツのように振る舞う。
<div> <a> <h1> 見出しでもクリックできる </h1> </a> </div>
ウェブにおけるリンクは重要度が高い。そのためリンク要素のアクセシビリティには十分留意すること。
- リンク先が推測できること e.g. "こちら" を避ける(here症候群)
- リンクボタンはあくまでリンクなので、支援技術は "リンク" として認識する。
link要素
Metadataコンテンツで、終了タグがない、単独で存在できる要素。- linkはaと異なり、html文書が参照するリソースとの関係を表現する要素。リンク先リソースの種類はrel属性で指定される。
- 使用できる文字列表現はHTMLリンクタイプに定義される。
- 多くの場合、relはhrefと一緒に用いてリンク先の実体とそれの種類を設定する。
stylesheet
にした典型的なマークアップ。
<link rel="stylesheet" href="./style.css">
テーブル
tableの内容モデルは複雑。thead, tbodyなどを子要素にできる。trを直接配置できるが、tbodyが補われる。
tr
テーブルの行を表現する。内容モデルはtd, thのみ。td, thはどちらもFlowモデル。ただしthの子孫にheader, 見出しを含められない。
変更日 | 商品名 | 在庫数 |
---|---|---|
商品1 | 50 | |
商品2 | 70 |
caption
テーブルにキャプションをつける。省略可能。
フォーム
ユーザが入力した情報をサーバに送信する機能があり、そのための要素が存在する。ユーザがテキストを入力するパーツをフォームコントロールと呼ぶ。
スクリプティング要素
以前のブラウザはVBScriptが動くこともあったが、現在はJavaScriptの動作のみ想定されている。
script
script
はほとんどの要素の子要素になることができ、Meta、Flow、Phrasingのどれでもある。内容モデルは複雑で、src属性が指定されているときは非置換要素になる。
script要素は複雑な経緯を持っているため、srcで外部リソースを読み込んで使うようにする。
src属性で外部リソースを読み込む際、asyncやdeferを用いることで読み込みの遅延を実現できる。defer属性を指定すると、htmlの解析を優先してスクリプトのロードを遅延させる。
noscript
属性、ARIA
ARIA(Accesible Rich Internet Applications)属性は、アクテシビリティを向上させるための属性で、任意のマークアップ言語と組み合わせることができる。
ARIA属性は、その特徴から3つに分類できる:- ロール
- ステート
- プロパティ
代表的なaria-*属性
aria-hidden[state]
支援技術に存在しないことを伝える属性。意図しない、ないしは冗長な読み上げをスキップさせられる。
aria-label[property]
要素にアクセシブルな名前を与える。例えば、アイコンボタンなどテキストから文脈を伝えづらいケースでは与えた名前によってアクションが明瞭に伝わる。
aria-labelledby[property]
aria-haspopup
属性が指定された要素にポップアップがあることを伝える。視覚的にしかわからないドロップダウンの存在を提示できる。