12k
All articles

モダンなHTMLボイラープレートに含めるべきもの

必須の5項目にメタデータ、ファビコン、SNSタグを加えた最新のHTMLボイラープレートを解説。古いテンプレートで残す項目や削除する項目も紹介します。

OpenReplay Team
OpenReplay Team
モダンなHTMLボイラープレートに含めるべきもの

モダンなHTMLボイラープレートに必要なものは5つです。HTML5のdoctype、<html>のlang属性、UTF-8の文字コード宣言、viewportメタタグ、そしてページごとに固有の<title>です。それ以外の要素は、ページがシェアされるか、インストールされるか、ブックマークされるかによって決まります。

ほとんどのページは、Emmetの!スニペット、フレームワークのindex.html、あるいは10年前のHTML5 Boilerplateのコピーから作り始められます。これらの行を見直す人はいないため、古くなった記述がプロジェクトからプロジェクトへとそのまま受け継がれていきます。

この記事では、ドキュメントを1行ずつ確認していきます。各行について、何をするのか、なければ何が壊れるのか、そして必須・任意・削除してよいのどれに当たるのかを解説します。head内の記述順序やメタデータ全体については、関連記事のドキュメントのheadに本当に含めるべきものを参照してください。

Emmetの!で生成されるのは次のコードです。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

</body>
</html>

出発点としては妥当です。ただし、description、canonical、ソーシャル用のタグ、アイコン、color-schemeは含まれておらず、viewportにはもう不要な値が入っています。

要点

  • モダンなHTMLボイラープレートで必須となるのは、doctype、lang、<meta charset="UTF-8">、viewportタグ、<title>です。どれか1つでも欠けると、ページが正しく描画されない、アクセシビリティが低下する、あるいは不正なHTMLになります。
  • lang属性は、スクリーンリーダーの発音、CSSのハイフネーション、ブラウザの翻訳機能を制御します。Googleはページの言語判定にlangを使用しません。
  • maximum-scale、minimum-scale、user-scalable=noはロービジョンのユーザーによるズームを妨げます。見つけたらすべて削除してください。
  • ファビコン一式は、favicon.ico、favicon.svg、180×180のapple-touch-icon.png、そして192px・512pxのアイコンとmaskableアイコンを含むWebマニフェストです。
  • X-UA-Compatible、shrink-to-fit=no、type="text/javascript"は新規プロジェクトでは何の役にも立たないため、削除して構いません。

doctypeとlang属性

必須。 <!DOCTYPE html>はブラウザを標準モードに切り替えます。これがないと、HTMLパーサーは互換モード(quirks mode)にフォールバックし、古いブラウザのレイアウトバグを再現します。その結果、どれだけCSSをデバッグしても説明のつかないボックスモデルやテーブルのサイズの違いが生じます。

必須。 <html>のlang属性には3つの役割があります。

  • スクリーンリーダーに、どの発音ルールを適用すべきかを伝える。
  • CSSのhyphens: autoが正しい辞書を使って単語を分割できるようにする。
  • ブラウザの翻訳機能がページの言語を判別する助けになる。

これがないと、スクリーンリーダーがフランス語のテキストを英語の発音で読み上げてしまうことがあります。値にはen、de、pt-BRのようなBCP 47言語タグを指定します。MDNのlangリファレンスにあるとおり、子要素で上書きすることもできます。

langが担うのはアクセシビリティと言語の扱いであり、検索順位ではありません。Google検索はlangを無視し、ページのコンテンツから言語を判定すると明言しています。

<!DOCTYPE html>
<html lang="en">

charsetを先に、続いてviewport

必須。 <meta charset="UTF-8">はドキュメントの先頭1024バイト以内に記述する必要があります。そのため、<head>の最初、つまり<title>や、ブラウザが誤ったエンコーディングでデコードしてしまう可能性のある他のテキストよりも前に置きます。これがない、あるいは記述位置が遅すぎると、タイトル内のアクセント付き文字や絵文字が文字化けします。

必須。 viewportタグは、モバイルブラウザにデバイスの幅でページをレイアウトするよう指示します。これがないと、スマートフォンはデスクトップ幅(通常は約980px)でレイアウトを描画して縮小表示するため、メディアクエリがまったく発動しません。width=device-widthだけで十分で、initial-scale=1は通常不要です。指定できる値の一覧はMDNのviewportリファレンスを参照してください。

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">

任意(事前にテストすること)。 <meta name="text-scale" content="scale">はCSS Fonts Level 5のドラフトで定義されており、実装しているのはChromium系ブラウザのみです。これを指定すると、ルートのフォントサイズが、ユーザーがOSやブラウザの設定で選んだ文字サイズに追従するようになります。その結果、大きくなるのはremやemで指定したテキストだけなので、高さを固定したコンポーネントではテキストがはみ出す可能性があります。導入前に、システムの文字サイズを大きくしてレイアウトを確認してください。

title、description、canonical

必須。 <title>は、ブラウザのタブ、ブックマーク、履歴、検索結果でページ名として表示されます。デフォルトのDocumentのままにしておくと、開いたタブがすべて同じに見えてしまいます。

任意(推奨)。 <meta name="description">は検索スニペット用の概要を提供します。ただし、クエリにより適したページ内容が見つかった場合、Googleはこれを書き換えることがあります。また、スニペットは表示幅に基づいて切り詰められるため、文字数のルールはあてになりません。

任意(推奨)。 <link rel="canonical">は、同じコンテンツが複数のURLでアクセスできる場合(クエリ文字列の有無や末尾スラッシュの違いなど)に、優先するURLを指定します。詳しくはSEO関連のHTMLタグとその最適化方法を参照してください。

<title>Page title – Site name</title>
<meta name="description" content="One or two sentences describing this page.">
<link rel="canonical" href="https://example.com/page">

Open GraphタグとTwitter Cardタグ

任意(シェアされるページでは必須)。 Open Graphタグは、SNSやチャットアプリでのリンクプレビューを制御します。これがないと、シェアされたリンクはURLだけ、あるいはスクレイパーが拾った情報から組み立てられたカードとして表示されます。

Open Graphプロトコルでは、og:title、og:type、og:image、og:urlが必須プロパティとされており、typeのないページはwebsiteとして扱うべきとされています。og:urlにはcanonical URLと同じ値を設定してください。そうすれば、トラッキングパラメータ付きのリンクが別ページとしてキャッシュされるのを防げます。og:imageについては、Metaは1200×630ピクセル以上で、1.91:1に近い比率の画像を推奨しています。

Xは独自のtwitter:*タグ(propertyではなくnameで記述)を読み取り、それがない場合は対応するog:*の値にフォールバックします。実際のところ、X固有のタグで必要なのはtwitter:cardだけで、それも大きな画像のカードを表示したい場合に限られます。

<meta property="og:title" content="Page title">
<meta property="og:description" content="Description for link previews.">
<meta property="og:image" content="https://example.com/og-image.jpg">
<meta property="og:url" content="https://example.com/page">
<meta name="twitter:card" content="summary_large_image">

ページごとにこれらのタグを生成するには、メタタグジェネレーターを利用してください。

ファビコン一式

任意(ただし、あって当然とみなされる)。 ファビコンを一通り揃えるには4つの要素が必要です。これらを省くと、タブのアイコンが空白になり、iOSのホーム画面ではスクリーンショットのようなタイルが表示され、Androidでは汎用的なインストールアイコンになります。

<link rel="icon">要素は、favicon.ico用とfavicon.svg用の両方を残してください。そうすれば、バージョン26より前のSafariなど、SVGファビコンを使えないブラウザでもICOファイルが読み込まれます。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    circle { fill: #1a1a2e; }
    @media (prefers-color-scheme: dark) {
      circle { fill: #f5f5f5; }
    }
  </style>
  <circle cx="16" cy="16" r="14"/>
</svg>
{
  "name": "Site name",
  "short_name": "Site",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
    { "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
  ]
}

各ファイルの生成方法について詳しくは、Webサイトにファビコンを追加する方法を参照してください。

color-schemeとtheme-color

任意(ダークモードを提供する場合は推奨)。 <meta name="color-scheme" content="light dark">は、CSSが読み込まれる前の段階で、ページがライトとダークの両モードに対応していることをブラウザに伝えます。これにより、デフォルトの背景、フォームコントロール、スクロールバーがユーザーの設定に従うようになります。これがないと、ダークテーマのサイトで読み込み時に白い画面が一瞬表示されることがあります。MDNのcolor-schemeの解説を参照してください。

任意。 theme-colorはブラウザUIに色を付けるもので、media属性を受け付けるため、ライトとダークで別々の値を設定できます。Android版のChromiumでは機能しますが、MDNではブラウザのサポートが限定的とされているため、すべてのブラウザで表示されるものではなく、あれば嬉しいおまけ程度に考えてください。

<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#111111" media="(prefers-color-scheme: dark)">

モーション軽減のデフォルト設定

任意(強く推奨)。 モーション軽減のデフォルト設定は、headのタグではなくベーススタイルシートのルールです。それでもボイラープレートに含めるべきなのは、後から追加する人がいないからです。prefers-reduced-motion: reduceブロックは、OSでモーションを減らす設定をしているユーザーに対して、アニメーションやトランジションを短縮し、スムーズスクロールを無効にします。

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

継続時間を0ではなく0.01msにしているのは、animationendやtransitionendが引き続き発火するようにするためです。これにより、それらのイベントを待つJavaScriptが止まってしまうことを防げます。これは大まかなデフォルト設定です。個々のコンポーネントで、不透明度のフェードのような前庭障害を引き起こさない穏やかなモーションを、改めて有効にすることもできます。

古いボイラープレートから削除すべき行は?

削除。 古いHTMLボイラープレートにある次の4つの記述は、IE時代のテンプレートや初期のレスポンシブ対応スターターに由来するもので、現在ではいずれも何の役にも立ちません。

  • X-UA-Compatible はInternet Explorerのドキュメントモードを選択するためのものでした。サポート対象のブラウザでこれを読み取るものはありません。
  • maximum-scale、minimum-scale、user-scalable=no はロービジョンのユーザーによるピンチズームを妨げ、WCAG 1.4.4 テキストのサイズ変更に反します。すべてのviewportタグから削除してください。
  • shrink-to-fit=no は古いiOS Safariのスケーリング挙動を回避するためのもので、現在は何の効果もありません。
  • type="text/javascript" はデフォルト値を繰り返しているだけです。HTML仕様は、クラシックスクリプトではtypeを省略するよう作成者に求めています。
<!-- Before -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no">
<script type="text/javascript" src="/app.js"></script>

<!-- After -->
<meta name="viewport" content="width=device-width">
<script type="module" src="/app.js"></script>

type="module"のスクリプトはデフォルトで遅延実行されるため、レンダリングをブロックせずにパース完了後に実行されます。モジュールにできないスクリプトにはdeferを付けてください。

HTMLボイラープレートの完成形

以下は、この記事で取り上げた必須および推奨の記述をすべて組み合わせた、モダンなHTMLボイラープレートの完成形です。フィードやプリロードなど、サイト固有の追加要素は必要に応じてこの上に加えてください。スキップリンクと<main>ランドマークはbodyに置きます。続いて使うセマンティック要素については、押さえておくべきHTML要素10選で解説しています。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <!-- Optional, test with large OS text first: <meta name="text-scale" content="scale"> -->
  <title>Page title – Site name</title>
  <meta name="description" content="One or two sentences describing this page.">
  <link rel="canonical" href="https://example.com/page">

  <meta name="color-scheme" content="light dark">
  <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
  <meta name="theme-color" content="#111111" media="(prefers-color-scheme: dark)">

  <link rel="stylesheet" href="/styles.css">
  <script type="module" src="/app.js"></script>

  <link rel="icon" href="/favicon.ico">
  <link rel="icon" href="/favicon.svg" type="image/svg+xml">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
  <link rel="manifest" href="/site.webmanifest">

  <meta property="og:title" content="Page title">
  <meta property="og:description" content="Description for link previews.">
  <meta property="og:image" content="https://example.com/og-image.jpg">
  <meta property="og:url" content="https://example.com/page">
  <meta name="twitter:card" content="summary_large_image">
</head>
<body>
  <a href="#main">Skip to content</a>
  <main id="main"></main>
</body>
</html>
記述役割ない場合に起こること判定
doctype標準モード互換モードでのレイアウト必須
lang発音、ハイフネーション、翻訳スクリーンリーダーの発音が誤る必須
charsetUTF-8を宣言文字化け必須
viewportデバイス幅でのレイアウトスマートフォンでデスクトップ用レイアウトが縮小表示される必須
<title>ページの名前タブやブックマークが区別できない必須
description、canonicalスニペットと優先URLスニペットの質が下がる、URLが重複する任意
Open Graph、twitter:cardリンクプレビューURLのみ、または汎用的なカード任意
ファビコン一式タブおよびホーム画面のアイコン空白またはスクリーンショットのアイコン任意
color-schemeネイティブのダークモード白い画面のちらつき、ライト表示のコントロール任意
X-UA-Compatible、ズーム制限、shrink-to-fit、type="text/javascript"レガシーな回避策何も起こらない削除

HTMLボイラープレートで必須なのは5行だけです。それ以外は、ページがシェアされるか、インストールされるか、テーマを持つかに応じた任意の記述か、削除すべきレガシーな記述のどちらかです。現在のプロジェクトのindex.htmlを開き、上の表と1行ずつ照らし合わせて、次のプロジェクトにファイルをコピーする前に「削除」の行に該当するものを取り除いてください。

よくある質問

meta charsetとmeta http-equiv Content-Typeは同じものですか?

はい。WHATWGのHTML仕様では、http-equiv Content-Type版はcharset属性と同じ役割を果たします。どちらも文字エンコーディング宣言として扱われ、どちらも先頭1024バイト以内に置く必要があります。ドキュメントに両方を含めてはならず、含めるとバリデーターがエラーとして指摘します。短いmeta charset='UTF-8'を使ってください。サーバーがHTTPのContent-Typeヘッダーでcharsetを送信している場合は、そちらもUTF-8になっていることを確認してください。

HTMLのmetaタグやlinkタグに末尾のスラッシュは必要ですか?

いいえ。meta、link、imgなどの空要素には終了タグがなく、HTMLパーサーは末尾のスラッシュを無視します。スラッシュを付けて書いたタグと付けずに書いたタグは、同じ要素になります。スラッシュは有効ですが効果はないため、スタイルの問題です。違いが生じるのは、ページをXMLのMIMEタイプでXHTMLとして配信する場合だけです。

html、head、bodyタグは省略できますか?

はい。HTML仕様では、多くの場合html、head、bodyタグは省略可能とされており、タグがなくてもパーサーがそれらの要素を生成します。それでも、ボイラープレートでは明示的に記述すべきです。lang属性を付けるには明示的なhtml開始タグが必要ですし、明示的なタグによってheadとbodyの境界が読みやすくなります。htmlタグを省略すると、langも失われます。

Emmetの!スニペットのデフォルトのlang値を変更するには?

VS Codeのemmet.variables設定でlang変数を設定します。settings.jsonのemmet.variablesオブジェクトに、deなどの値を持つlangキーを追加すると、Emmetは!スニペットを展開するたびにその言語コードを書き出すようになります。同じ設定にはcharset変数もありますが、こちらはUTF-8のままにしておいてください。viewportの行には引き続きinitial-scale=1.0が含まれるため、手作業で削除するか、カスタムスニペットを定義してください。

Open-source session replay

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.