mcpField
S
semantic-html-and-seo

semantic-html-and-seo

github.com/dembrandt開発174916 回インストール1 週間前に更新
リポジトリ

semantic-html-and-seo について

セマンティックでアクセシブルなHTMLと検索されやすいページの実装を支援する開発スキルです。メタデータ、構造化データ、プログレッシブエンハンスメント、SPAのアクセシビリティとSEOを扱います。

主な機能

  1. 01セマンティックなHTML構造
  2. 02画像の代替テキスト指針
  3. 03SEOメタデータと構造化データ
  4. 04プログレッシブエンハンスメントの実践
  5. 05SPAのアクセシビリティとSEOの確認

活用シーン

  1. 01見出しと文書構造のレビュー
  2. 02メタデータと共有カードの準備
  3. 03SPAのアクセシビリティと検索対応の改善

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dembrandt/dembrandt-skills --skill semantic-html-and-seo

インストール後、Claude Code で/semantic-html-and-seoを入力して読み込まれたか確認します。

詳細

セマンティック HTML と SEO

優れた HTML は単なるマークアップではありません。コンテンツ、検索エンジン、支援技術、ブラウザーの間の契約です。セマンティック HTML、適切なメタデータ、プログレッシブエンハンスメントにより、UI は標準で堅牢かつ見つけやすく、アクセシブルになります。


セマンティック HTML5

見た目だけでなく、コンテンツの意味を表す要素を使用してください。

ドキュメント構造
<header>       
<nav>          
<main>         
<article>      
<section>      
<aside>        
<footer>       
見出し

1 ページにつき <h1> は 1 つにします。ページの主題を表す見出しです。見出しでアウトラインを構成します。レベルを飛ばさないでください(h1 → h3 のように、h2 を飛ばすのは避けてください)。

<h1>Product name</h1>
  <h2>Features</h2>
    <h3>Feature detail</h3>
  <h2>Pricing</h2>
インタラクティブ要素
<button>   
<a href>   
<input>    
<select>   
<details> / <summary>  

完全な ARIA 属性を付けずに <div> や <span> をインタラクティブ要素として使用しないでください。また、属性を付ける場合でも、ネイティブ要素を優先してください。


画像と代替テキスト

すべての <img> に alt 属性が必要です。設定する内容はコンテキストによって異なります。

画像の種類代替テキスト
情報を伝える画像(製品写真、グラフ)内容を説明します:alt="赤い革張りの3人掛けソファ"
機能を持つ画像(アイコンボタン、ロゴリンク)機能を説明します:alt="ホームページに移動"
装飾画像空にします:alt="" — スクリーンリーダーは読み飛ばします
複雑な画像(グラフ、図)短い代替テキストに加え、近くに長い説明を置くか、<figcaption> に記載します

<img src="sofa.jpg" alt="Red leather sofa, three-seater">


<img src="divider.svg" alt="">


<figure>
  <img src="chart.png" alt="Bar chart showing revenue growth Q1–Q4 2025">
  <figcaption>Revenue grew 42% year-on-year in Q4 2025.</figcaption>
</figure>

SEO の基本

タイトルと説明
<title>Product Name — Short descriptor | Brand</title>
<meta name="description" content="One or two sentences. What this page is, who it is for, what they will find.">
  • タイトル:50~60 文字にします。最も重要なキーワードを先頭に置きます。
  • 説明:120~160 文字にします。検索結果に表示されるため、アルゴリズムではなく人に向けて書いてください。
正規 URL
<link rel="canonical" href="https://example.com/the-definitive-url">

同じページに複数の URL からアクセスできる場合に、重複コンテンツによるペナルティを防ぎます。

Open Graph(ソーシャル共有)
<meta property="og:title" content="Page title">
<meta property="og:description" content="Page description">
<meta property="og:image" content="https://example.com/og-image.jpg">
<meta property="og:url" content="https://example.com/page">
<meta property="og:type" content="website">


<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Page title">
<meta name="twitter:image" content="https://example.com/og-image.jpg">

OG 画像:1200×630px。URL が Slack、LinkedIn、Twitter、iMessage で共有されたときに表示されます。

カードの見出しには、記事の知見ではなく、読者が使う言葉を選びます。 フィードには文脈がないため、記事を読まないと意味が通じない一文は、スクロール中の見知らぬ人には意味不明に映ります。読者がすでに探している、わかりやすい約束を、そのプラットフォームで使われている言葉でカードに載せ、気の利いた一文はページ本文に残してください。

色合いではなく、モードに合わせてプラットフォームごとにカードを調整します。 明るいフィードでは暗いカードが広告バナーのように見えます。そのプラットフォームの背景に合わせて明るいカードにするのが解決策であり、ネイビーを少し暖色寄りにしたり、青を少し淡くしたりすることではありません。プラットフォームの UI に並ぶと、色相をわずかに変えても気づかれず、無駄な往復作業が増えるだけです。トーンの微調整は、モードを適切にしてから行います。

構造化データ(JSON-LD)

機械可読コンテンツにより、リッチ検索結果を表示できます。

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Product Name",
  "description": "Product description",
  "image": "https://example.com/product.jpg",
  "offers": {
    "@type": "Offer",
    "price": "49.00",
    "priceCurrency": "EUR"
  }
}
</script>

一般的なタイプ:Product、Article、BreadcrumbList、FAQPage、Organization、SiteLinksSearchBox。


プログレッシブエンハンスメント

レイヤーを重ねて構築します。コアとなるコンテンツと機能は、JavaScript なしで動作しなければなりません。CSS で拡張し、さらに JS で拡張します。

Layer 1: HTML — content is readable, links work, forms submit
Layer 2: CSS  — layout, typography, visual design
Layer 3: JS   — interactivity, animations, dynamic content

実際には:

  • フォームは JS なしでネイティブの <form action> を使って送信できる必要があります。JS で送信を捕捉し、fetch で機能を拡張できます
  • ナビゲーションリンクには実際の <a href> を使用する必要があります。JS でトランジションを追加できます
  • コンテンツは HTML 内に含める必要があります。JS で遅延読み込みやパーソナライズを追加できます
  • 画像には src が必要です。JS で loading="lazy" を使った遅延読み込みを追加できます(現在はネイティブで対応しています)

SPA に関する考慮事項

シングルページアプリケーションは、SEO とアクセシビリティが依存するブラウザーの既定の動作を損ないます。明示的に対処してください。

サーバーサイドレンダリングまたは静的生成

クライアント側でレンダリングされた HTML は、検索エンジンに確実にインデックス登録されるとは限りません。見つけてもらう必要のあるコンテンツには、SSR(Next.js、Nuxt、SvelteKit)または静的生成を使用してください。

タイトルとメタデータの更新

ルートが変わるたびに document.title とメタタグを更新してください。フレームワークの <Head> コンポーネントまたは同等のものを使用してください。

フォーカス管理

ルートが変わったら、新しいページの <h1> または <main> にフォーカスを移動します。スクリーンリーダーは SPA のナビゲーションを自動的には検知しません。

// After route change
document.querySelector('h1')?.focus();
スクロール位置の復元

ナビゲーション時にスクロール位置を先頭に戻すか、戻るナビゲーション時に保存した位置へ戻します。SPA では、ブラウザーの既定のスクロール位置復元が無効になっています。

History API

pushState / replaceState を使用して、戻る/進むナビゲーションやブックマークが正しく機能するようにします。


デバイスの機能とユーザーコンテキスト

デザインとコードは、デバイスとユーザーが実際にできることに合わせて調整する必要があります。

クライアント側ストレージをパーソナライズに活用する

localStorage、sessionStorage、その他のブラウザー機能(Cookie、IndexedDB、メディアや権限のクエリ)は、エクスペリエンスを調整するための適切な手段です。前回の表示モード、選択したロケール、非表示にしたバナー、作成途中の下書き、再訪ユーザーのコンテキストなどを保存できます。

ガードレール:

  • 推測ではなく、実際の理解に基づいてパーソナライズします。 何を安全に保存して事前入力するかは、通常、ユーザーテストで確認する必要があります。保存された状態に基づく誤った想定は、何も設定しない場合よりも悪い結果を招きます。
  • 範囲と同意。 1 回のセッションでは sessionStorage、セッションをまたぐ場合は localStorage を使います。機密情報はクライアント側に保存せず、同意を尊重してください。
  • 2~3 年ごとに再検証します。 ニーズは変化します。提供開始時には適切だったパーソナライズも、やがて使いにくさにつながることがあります。できれば新たにテストを実施して見直してください。
入力方式の検出
@media (hover: hover) {
  /* hover states — mouse or trackpad */
  .btn:hover { background: var(--color-primary-hover); }
}

@media (hover: none) {
  /* touch device — no hover, larger targets */
  .btn { min-height: 44px; }
}
ポインターの精度
@media (pointer: coarse) {
  /* fat-finger touch — increase target sizes */
  .interactive { min-height: 44px; min-width: 44px; }
}

@media (pointer: fine) {
  /* mouse — precise, can use smaller targets */
}

ポインターの精度は、ターゲットのサイズだけでなく、デフォルトの動作も選択できます。同じクエリは JavaScript の matchMedia('(pointer: fine)') で確認できますが、操作モデルが異なる場合は、各イベントの pointerType を使ってください。たとえば、クリックでは切り替え、マウスではポインターによるパン、タッチではピンチやダブルタップといった違いです。ハイブリッドデバイスでは推測が外れるため、ビューポートの幅から入力方式を推定しないでください。画像のズームについては [[modal-and-overlay-patterns]] を参照してください。

ネットワークの状態

<img src="product.jpg" loading="lazy" alt="...">


<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="...">
</picture>
ユーザー設定
@media (prefers-reduced-motion: reduce) { /* disable animations */ }
@media (prefers-color-scheme: dark)     { /* dark mode tokens */ }
@media (prefers-contrast: more)         { /* increase contrast */ }
@media (forced-colors: active)          { /* Windows high contrast mode */ }

レビューチェックリスト

  • 1 ページにつき <h1> が 1 つあり、見出しが論理的な階層を構成している
  • <main>、<nav>、<header>、<footer>、<article>、<section> などのセマンティック要素を使用している
  • すべての <img> に意味のある alt が設定されている。装飾画像の場合は alt="" を設定している
  • ページごとに固有の <title> があり、50~60 文字で、キーワードが先頭にある
  • <meta name="description"> が設定されており、120~160 文字である
  • 共有可能なすべてのページに Open Graph タグが設定されている
  • 複数の URL からアクセスできるページに <link rel="canonical"> が設定されている
  • 製品、記事、FAQ のページに構造化データ(JSON-LD)が設定されている
  • JavaScript がなくてもフォームが動作する
  • SPA がルート変更時に document.title とメタタグを更新する
  • SPA がルート変更時にフォーカスを移動する
  • ホバー状態が @media (hover: hover) の範囲内に設定されている
  • @media (pointer: coarse) でタッチターゲットが 44px 以上である
  • ファーストビューより下の画像に loading="lazy" を設定している
  • prefers-reduced-motion を尊重している

コメント