HTMLを学び始めたとき、「この要素はどう使うのが正解……?」と悩んだ経験はありませんか。HTMLは気軽に始められる言語ですが、実はルールや使い方のポイントが数多く存在しています。
私はフロントエンドエンジニアとして日々コードを書く一方で、HTMLをはじめとするウェブ技術を大学や企業で教える講師も務めてきました。その中で、なんとかHTMLを書けるようになったものの、要素の使い方や使い分けに自信が持てないという方に数多く出会ってきました。
この記事では、そんなHTML初心者に向けてつまずきやすいポイントを10項目ピックアップしてご紹介します。HTMLを学び始めたときに陥りがちなマークアップ時の迷いを、この記事で少しでも解消していただければ幸いです。
1. div/spanタグと他のタグの違いを理解する
HTMLに不慣れなころ、意味を深く考えずにdivタグやspanタグを多用してしまった経験はありませんか。
これらの要素は汎用性が高く便利ですが、意味や役割を理解せずに使うと、本来文書構造を定義するためのHTMLの意義を無視したコードになってしまいます。
<div class="nav">
<div class="nav-item">ホーム</div>
<div class="nav-item">ブログ</div>
<div class="nav-item">お問い合わせ</div>
</div>
<div class="title">HTMLでよくある間違い</div>
<div class="text">
HTMLは<div class="strong">マークアップ言語</div>です。
</div>
この例では、ナビゲーションもタイトルも強調したい箇所も、すべてdivタグで表現されています。HTMLはマークアップ言語であり、基本的にすべてのタグに特定の意味(セマンティクス)があります。「囲いたいからdiv」ではなく、構造や意味を意識しましょう。
div/spanタグは、非セマンティクスタグと呼ばれて特定の意味を持たず、何かしらを区別するためのグルーピングの役割のみを担います。divタグはブロックや複数要素のまとまりを、spanタグはテキストの一部分のみを囲うために使います。
一方でaやh1、strongのように、それぞれ固有の意味を持つタグはセマンティクスタグと呼ばれます。div/spanタグに頼るのは、他に適切な意味を持つタグが見当たらないときだけにしましょう。先ほどの例は、以下のように書き直せます。
<nav>
<ul>
<li><a href="/">ホーム</a></li>
<li><a href="/blog">ブログ</a></li>
<li><a href="/contact">お問い合わせ</a></li>
</ul>
</nav>
<h1>HTMLでよくある間違い</h1>
<p>
HTMLは<strong>マークアップ言語</strong>です。
</p>
navタグでナビゲーションであることを示し、ul/li/aタグでリンクのリストを表現しています。見出しにはh1、本文にはp、強調したい部分にはstrongを使うことで、それぞれの意味が正しく伝わります。
もちろん、CSSを適用するためだけにグルーピングしたい場合は、div/spanタグを使っても問題ありません。
2. aタグとbuttonタグを使い分ける
aタグとbuttonタグは、どちらを使うべきか混同しがちです。
例えば、以下のような見た目のパーツがあったとします。「ボタンらしい見た目」なのでbutton要素を使いたくなるかもしれません。しかしテキストは「詳細ページを開く」となっており、別ページへの遷移が想定される内容です。
<button type="button">
詳細ページを開く
</button>
「ボタンっぽい見た目だからbutton」という理由だけでタグを選んでしまうのはNGです。なぜなら、aタグとbuttonタグでは明確に役割が異なるからです。
別のウェブページやPDF、圧縮ファイルといったファイルにリンクする場合は、a要素を用います。一般的には、別URLへの画面遷移を伴うものはa要素になるでしょう。
<a href="/about">詳細ページを開く</a>
逆に、画面遷移を伴わない、タブやアコーディオン、ハンバーガーメニューといった操作に対して何らかのアクションを実施するときは、button要素を用います。
<button type="button">ページの詳細を表示</button>
a要素として扱うべきリンクをbutton要素でマークアップしてしまうと、リンク先のURLが分からない、Ctrl(macの場合は⌘)+クリックで別タブを開けない、といった問題が発生します。それぞれの役割を理解して使い分けましょう。
3. 見出しレベルの順序を守る
h1~h6タグを使うと、見出しを設定できます。数字は見出しのレベルを表し、h1が最も高く、h6が最も低いランクになります。見出しレベルはスキップできないため、必ずh1から始めて、その次はh2...h6とする必要があります。
<!-- 🙅見出しレベルの順番が違う -->
<body>
<h1>大見出し</h1>
<h3>小見出し</h3>
<h2>中見出し</h2>
</body>
<!-- 🙅いきなりh2から始まっている -->
<body>
<h2>サイトのタイトル</h2>
<p>本文</p>
</body>
このような構造では、検索エンジンやスクリーンリーダーのユーザーがページ構造を正確に認識できなくなる恐れがあります。見出しレベルの順番が乱れたり、不適切なレベルを設定したりしないよう注意しましょう。
<body>
<h1>大見出し</h1>
<h2>中見出し</h2>
<h3>小見出し</h3>
</body>
見出しレベルのイメージとしては、本に例えると理解しやすいでしょう。本のタイトルがh1、章タイトルがh2、章に属する節タイトルがh3、といった具合です。順番さえ正しく設定されていれば、同じレベルの見出しが複数あっても構いません。
<body>
<h1>ウェブ制作の教科書</h1>
<h2>第1章 HTMLの基礎</h2>
<h3>1-1. HTMLとは何か</h3>
<h3>1-2. タグの書き方</h3>
<h2>第2章 CSSの基礎</h2>
<h3>2-1. セレクタの種類</h3>
<h3>2-2. ボックスモデル</h3>
</body>
4. imgタグの必須属性を理解する
imgタグは、他の要素に比べて指定できる属性が多く、利用頻度も高いためつまづきやすいポイントの1つです。
alt属性は、画像の代替テキストを提供するため属性です。アクセシビリティの観点から非常に重要であり、設定が必須です。
通常は、画像を見なくてもその内容や役割が伝わるよう、簡潔かつ具体的な文章を設定するのが基本です。「画像」「写真」のような曖昧な言葉ではなく、何が写っているのか、どんな意味を持つ画像なのかが伝わる表現を心がけましょう。
<img src="dog.jpg" alt="白いポメラニアンが芝生の上で座っている写真" />
単なる装飾のための画像では、空文字(alt="")を指定することで「意味のない画像である」ことを示せます。
なお、画像が何らかの理由で読み込めなかった場合、一般的なブラウザはその位置にalt属性のテキストを代わりに表示します。ユーザーが画像を目にできない状況でも、内容を正しく伝えられるのはこのためです。
次に、width/height属性です。これらには画像の実際のピクセルサイズ(実寸)を指定します。ここで指定した数値は、「画面上で必ず746x427pxで表示する」という意味ではありません。
<img
src="dog.jpg"
alt="白いポメラニアンの写真"
width="746"
height="427"
/>
width/height属性の目的は、画像の縦横比(アスペクト比)を指定し、あらかじめ表示に必要な領域を確保することです。CSS側でwidth: 100%のように可変幅で表示する場合でも、width/height属性から縦横比を計算できるため、画像の読み込み前後で発生しがちなレイアウト崩れ(レイアウトシフトと呼びます)を防げます。
5. リストの入れ子構造に注意する
入れ子構造(ネスト)とは、あるタグを別のタグの中に含めることを指します。例えば以下のコードでは、h1タグとpタグがsectionタグの入れ子になっています。
<section>
<h1>HTML初心者必見! 間違いやすい要素の使い方10選</h1>
<p>この記事では、HTML初心者が間違いやすい要素や注意すべきポイントを10項目ピックアップしてご紹介します。</p>
</section>
ただし、タグはなんでも自由に入れ子にできるわけではありません。タグ同士には、入れ子にできるかどうかのルールが決められています。
間違いやすい例として、リスト(ul、olタグ)が挙げられます。次のコードでは、材料と調味料を入れ子の箇条書きにしたいのですが、調味料のliタグと中身のulタグが同列に並んでしまっています。
<ul>
<li>鶏肉</li>
<li>大根</li>
<li>調味料</li>
<!-- 調味料を材料の入れ子にしたい -->
<ul>
<li>しょうゆ</li>
<li>酒</li>
<li>みりん</li>
</ul>
</ul>
ul、olタグの直下に書けるのはliタグだけです。材料と調味料を入れ子にしたい場合は、子のリスト(2つ目のulタグ)を親のliタグで囲う必要があります。
<ul>
<li>鶏肉</li>
<li>大根</li>
<li>
調味料
<ul>
<li>しょうゆ</li>
<li>酒</li>
<li>みりん</li>
</ul>
</li>
</ul>
olの中にolを書く場合や、ulの中にolを書く場合も、考え方は同じです。
6. header/footerタグを活用する
headerタグやfooterタグは、「ウェブページ全体のヘッダーやフッターをマークアップするためのタグ」という印象を持たれがちです。そのため、1ページに1つずつしか使えないと誤解されることもあります。
しかし実際は、ページ全体に限らずセクション単位やコンポーネント単位にも使用できます。記事やカード、モーダルなどの構造の中で、導入や締めくくりの部分を明示できるのです。
以下は、モーダルを簡略化した例です。まず、header/footerタグを使わない場合を見てみましょう。
<dialog>
<h2>感想・報告を送る</h2>
<form method="post">
<p>ご感想やご指摘、気になったことについてお気軽にお送りください。</p>
<textarea name="お問い合わせ内容" required placeholder="内容を入力してください"></textarea>
<button type="submit">送信する</button>
</form>
</dialog>
これをheader/footerタグを使って書き換えると、以下のようになります。
<dialog>
<header>
<h2>感想・報告を送る</h2>
</header>
<form method="post">
<p>ご感想やご指摘、気になったことについてお気軽にお送りください。</p>
<textarea name="お問い合わせ内容" required placeholder="内容を入力してください"></textarea>
<footer>
<button type="submit">送信する</button>
</footer>
</form>
</dialog>
モーダルを表現するdialogタグの内部に、headerタグとfooterタグを配置することで、どの部分が導入で、どこがアクションエリアなのかを構造的に示せます。これは要素が複雑化した場合の可読性向上や、アクセシビリティの改善にもつながります。
7. button/inputタグのtype属性を設定する
buttonタグやinputタグにはtype属性があります。これを指定することで、バリデーションを強化し、意図しない動作を防げます。
button要素を例に見てみましょう。type属性を省略すると、デフォルト値であるsubmitが適用されてしまい、以下のように不適切なコードとなります。
<button>検索</button>
<!-- 以下と同じ意味になる -->
<button type="submit">検索</button>
submitはフォームのデータをサーバーに送信するための値です。検索ボタンにはその機能が不要なため、次のようにtype="button"を指定するのが適切です。
<button type="button">検索</button>
フォームやボタンの動作を誤って指定しないために、type属性は必ず指定しましょう。特にbutton要素の場合は、type="button"を明示することで意図しないフォーム送信を防げます。
8. labelタグはfor属性で関連付ける
フォームを作る際、labelタグをうまく取り扱うことでアクセシビリティ向上につながります。特にfor属性を設定して、inputタグのid属性の値と一致させると、ラベル部分をクリックしてもinputにフォーカスが移ります。
<!-- for属性が設定されていない -->
<label>名前:</label>
<input type="text">
<!-- 正しく関連付けられた例 -->
<label for="username">ユーザー名:</label>
<input type="text" id="username">
チェックボックスやラジオボタンでは特に効果が大きく、UIだけでなく文字部分をクリックして選べるようになります。
また、labelとフォーム関連の要素を紐づけるには、labelタグで要素を囲う方法もあります。UIのラベルとして直感的に理解しやすいことと、必要最小限の記述で済むため、筆者はこちらの方法を愛用しています。
<!-- labelタグで囲む例 -->
<label>
ユーザー名:
<input type="text">
</label>
9. 日付や時刻のマークアップにはtimeタグを使う
「2024年12月24日」のような日付は、HTMLの中でよく登場する表現の一つです。日付や時刻をブラウザーや検索エンジンに正確に伝えるために、timeタグを使って以下のようにマークアップできます。
<!-- 年月日 -->
<time>2024-12-24</time>
<!-- 時刻 -->
<time>14:54</time>
<!-- 年月日+時刻+秒 -->
<time>2024-12-24T14:54:02</time>
timeタグで囲う文字列は、決められたフォーマットでなければいけません。ただし、現実的にこのフォーマットで日時を表現することは少ないでしょう。
「2024年12月24日」のように日本でよく使われる表記にするには、datetime属性を使います。先ほどのコードをdatetime属性で書き換えると、以下のようになります。
<!-- 年月日 -->
<time datetime="2024-12-24">2024年12月24日</time>
<!-- 時刻 -->
<time datetime="14:54">午後2時54分</time>
<!-- 年月日+時刻+秒 -->
<time datetime="2024-12-24T14:54:02">2024年12月24日14時54分2秒</time>
datetime属性を使うことで、人間にもマシンにも読みやすい日時情報を表現できます。
10. metaタグのuser-scalable="no"は使わない
meta name="viewport"は、ウェブサイトをあらゆる画面サイズで適切に表示するために使われます。特にレスポンシブウェブデザインには欠かせない要素です。
この要素では、user-scalable属性を使ってページ拡大縮小の可否を設定できます。値をno(または0)に設定すると、ズームが無効化され、ユーザーは自分の意思で拡大率を変更できなくなります。
<meta name="viewport" user-scalable="no" content="width=device-width, initial-scale=1" />
拡大率を固定すると、コンテンツ提供側がレイアウトをユーザーに強制できるため、一見都合がよいようにも思えます。しかし、拡大率が固定されてしまうと、視力が低い方にとってコンテンツが読みづらくなる場合がある、デバイスサイズによっては見づらいレイアウトになる、などの問題が発生します。
user-scalable属性の初期値は1、つまりyesと同じです。特に値を指定しなければ、ユーザーは自由にズームできます。
<meta name="viewport" content="width=device-width, initial-scale=1" />
HTMLを正しく理解し、自信を持ってコーディングしよう
ここまで、HTML初心者が間違いやすい要素・属性の使い方や、注意すべきポイントを10項目ご紹介しました。
生成AIにコードを書いてもらうことが当たり前になった今でも、HTMLの仕様を正しく理解しておくことの重要性は変わりません。むしろAIやJavaScript/TypeScript全盛の時代だからこそ、ウェブページの礎となるHTMLについて深く知ることで、スキルに欠かせない土台となるでしょう。
コード初心者は、ついついコードをコピペしてしまいがちですが、あいまいな理解のまま中途半端なコードを書くよりも、分からない部分はその都度調べて仕組みを理解する方が、結果的に遠回りになりません。要素の意味や役割を正しく理解し、自信を持ってコーディングできるようになりましょう。
この記事が、これからマークアップに触れる方々の助けになれば幸いです。