今年の初めに、私はという電子ブックを自費出版しました JavaScriptの約束を理解する (無料でダウンロード)。 印刷本にするつもりはなかったのですが、印刷版について問い合わせがあったので、自費出版することにしました。HTMLやCSSを使って簡単に作れると思いました。 PDFを生成し、それをプリンターに送信します。 私が気づかなかったのは、印刷物の重要な部分である目次に対する答えがなかったということでした。
目次の構成
基本的に、目次はかなり単純です。 各行は、本またはWebページの一部を表し、そのコンテンツを見つけることができる場所を示します。 通常、行には次のXNUMXつの部分が含まれます。
- 章またはセクションのタイトル
- タイトルをページ番号に視覚的に接続するリーダー(つまり、点、破線、または線)
- ページ番号
目次は、MicrosoftWordやGoogleDocsなどのワードプロセッシングツール内で簡単に生成できますが、コンテンツがMarkdownにあり、HTMLに変換されたため、これは適切なオプションではありませんでした。 HTMLと連携して、印刷に適した形式で目次を生成する自動化されたものが必要でした。 また、各行をリンクにして、WebページやPDFでドキュメント内を移動できるようにしたかったのです。 また、タイトルとページ番号の間にドットリーダーが必要でした。
それで私は研究を始めました。
HTMLとCSSを使用した目次の作成に関するXNUMXつの優れたブログ投稿に出くわしました。 最初は 「HTMLから目次を作成する」 ジュリー・ブラン著。 ジュリーは PagedJS、印刷用にドキュメントを適切にフォーマットするWebブラウザで欠落しているページメディア機能のポリフィル。 ジュリーの例から始めましたが、うまくいかなかったことがわかりました。 次に、クリストフ・グラボの 「CSSを使用したレスポンシブTOCリーダーライン」 投稿。CSSグリッドを使用して(ジュリーのフロートベースのアプローチとは対照的に)位置合わせを簡単にするという概念を紹介しました。 しかし、繰り返しになりますが、彼のアプローチは私の目的には完全に適切ではありませんでした。
しかし、これらXNUMXつの投稿を読んだ後、私は自分で着手するのに十分なレイアウトの問題を理解していると感じました。 私は両方のブログ投稿の一部を使用し、アプローチにいくつかの新しいHTMLとCSSの概念を追加して、満足のいく結果を出しました。
正しいマークアップの選択
目次の正しいマークアップを決定するとき、私は主に正しいセマンティクスについて考えました。 基本的に、目次は、ほとんどキーと値のペアのように、ページ番号に関連付けられたタイトル(章またはサブセクション)に関するものです。 それは私をXNUMXつの選択肢に導きました:
- XNUMXつのオプションは、テーブルを使用することです(
<table>
)タイトル用にXNUMX列、ページ用にXNUMX列。 - 次に、よく使用されない、忘れられる定義リストがあります(
<dl>
) エレメント。 また、Key-Valueマップとしても機能します。 したがって、ここでも、タイトルとページ番号の関係は明らかです。
これらのいずれも、実際には単一レベルの目次でのみ機能することに気付くまで、つまり、章名だけの目次が必要な場合にのみ、適切なオプションのように見えました。 ただし、目次にサブセクションを表示したい場合は、適切なオプションがありませんでした。 テーブル要素は階層データには適していません、および定義リストは技術的にネストできますが、セマンティクスは正しくないようです。 それで、私は製図板に戻りました。
私はジュリーのアプローチを基にしてリストを使用することにしました。 しかし、私は順序付きリストを選びました(<ol>
)順序付けられていないリストの代わりに(<ul>
)。 この場合、順序付きリストの方が適切だと思います。 目次は、章と小見出しのリストを、コンテンツに表示される順序で表しています。 順序は重要であり、マークアップで失われるべきではありません。
残念ながら、順序付きリストを使用すると、タイトルとページ番号の間の意味的な関係が失われるため、次のステップは、各リストアイテム内でその関係を再確立することでした。 これを解決する最も簡単な方法は、ページ番号の前に「ページ」という単語を挿入することです。 そうすれば、他の視覚的な区別がなくても、テキストに対する数字の関係が明確になります。
これが私のマークアップの基礎を形成した単純なHTMLスケルトンです:
<ol class="toc-list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title</span> <span class="page">Page 1</span> </a> <ol> <!-- subsection items --> </ol> </li>
</ol>
目次にスタイルを適用する
使用する予定のマークアップを確立したら、次のステップはいくつかのスタイルを適用することでした。
まず、自動生成された番号を削除しました。 必要に応じて、自動生成された番号を独自のプロジェクトに保持することもできますが、本の章のリストに番号のない序文と後語が含まれているのが一般的であり、自動生成された番号が正しくありません。
私の目的では、章番号を手動で入力してからレイアウトを調整し、最上位のリストにパディングがなく(したがって、段落に揃えて)、埋め込まれた各リストがXNUMXつのスペースでインデントされるようにします。 私は使用することを選択しました 2ch
どのフォントを使用するかまだよくわからなかったため、値をパディングします。 The ch
長さの単位を使用すると、使用するフォントに関係なく、一貫性のないように見える絶対ピクセルサイズではなく、文字の幅を基準にしてパディングを行うことができます。
これが私が最終的に得たCSSです:
.toc-list, .toc-list ol { list-style-type: none;
} .toc-list { padding: 0;
} .toc-list ol { padding-inline-start: 2ch;
}
サラ・スエイダン WebKitブラウザは次の場合にリストのセマンティクスを削除することを私に指摘しました list-style-type
is none
、追加する必要がありました role="list"
それを保存するためにHTMLに:
<ol class="toc-list" role="list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title</span> <span class="page">Page 1</span> </a> <ol role="list"> <!-- subsection items --> </ol> </li>
</ol>
タイトルとページ番号のスタイリング
リストのスタイルを自分の好みに合わせて、個々のリストアイテムのスタイルに移りましょう。 目次の各項目について、タイトルとページ番号は同じ行にあり、タイトルは左側に、ページ番号は右側に配置されている必要があります。
「問題ありません、それがフレックスボックスの目的です!」とお考えかもしれません。 あなたは間違っていません! Flexboxは確かに正しいタイトルページの配置を実現できます。 しかし、リーダーが追加されるときにいくつかのトリッキーな配置の問題があるので、代わりにグリッドを使用するクリストフのアプローチを選択しました。これは、複数行のタイトルにも役立つので、ボーナスとして使用します。 個々のアイテムのCSSは次のとおりです。
.toc-list li > a { text-decoration: none; display: grid; grid-template-columns: auto max-content; align-items: end;
} .toc-list li > a > .page { text-align: right;
}
グリッドにはXNUMXつの列があり、最初の列は auto
-コンテナの幅全体を埋めるサイズからXNUMX番目の列を引いたサイズ。 max-content
。 ページ番号は、目次によくあるように、右側に配置されます。
この時点で私が行った他の唯一の変更は、「ページ」テキストを非表示にすることでした。 これはスクリーンリーダーには役立ちますが、視覚的には不要なので、 伝統的な visually-hidden
class ビューから非表示にするには:
.visually-hidden { clip: rect(0 0 0 0); clip-path: inset(100%); height: 1px; overflow: hidden; position: absolute; width: 1px; white-space: nowrap;
}
そしてもちろん、そのクラスを使用するにはHTMLを更新する必要があります。
<ol class="toc-list" role="list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title</span> <span class="page"><span class="visually-hidden">Page</span> 1</span> </a> <ol role="list"> <!-- subsection items --> </ol> </li>
</ol>
この基盤が整ったので、私はタイトルとページの間のリーダーに話しかけることに移りました。
ドットリーダーの作成
リーダーは印刷媒体では非常に一般的であるため、疑問に思われるかもしれませんが、CSSがすでにそれをサポートしていないのはなぜですか? 答えは次のとおりです。 します。 まあ、一種。
実際にあります leader()
で定義された関数 ページメディア仕様のCSS生成コンテンツ。 ただし、多くのページメディア仕様と同様に、この関数はどのブラウザーにも実装されていないため、オプションとして除外されています(少なくともこれを書いている時点では)。 それもリストされていません caniuse.comおそらく、誰もそれを実装しておらず、実行する計画やシグナルがないためです。
幸いなことに、ジュリーとクリストフはそれぞれの投稿ですでにこの問題に取り組んでいます。 ドットリーダーを挿入するために、両方とも ::after
その疑似要素 content
次のように、プロパティを非常に長いドットの文字列に設定します。
.toc-list li > a > .title { position: relative; overflow: hidden;
} .toc-list li > a .title::after { position: absolute; padding-left: .25ch; content: " . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . "; text-align: right;
}
::after
疑似要素は絶対位置に設定され、ページのフローから外れ、他の行への折り返しを回避します。 各行の最後のドットを行末の数字と同じ高さにするため、テキストは右揃えになります。 (これの複雑さについては後で詳しく説明します。) .title
要素は相対位置を持つように設定されているため、 ::after
疑似要素は、その箱から出ることはありません。 一方、 overflow
は非表示になっているため、余分なドットはすべて非表示になります。 結果は、ドットリーダーを含むきれいな目次です。
ただし、他にも考慮が必要なことがあります。
サラはまた、これらのドットはすべてスクリーンリーダーへのテキストとしてカウントされることを私に指摘しました。 それで、あなたは何を聞きますか? すべてのドットが発表されるまで「はじめにドットドットドットドット…」。 これは、スクリーンリーダーのユーザーにとってはひどい体験です。
解決策は、次の要素を追加で挿入することです。 aria-hidden
に設定 true
次に、その要素を使用してドットを挿入します。 したがって、HTMLは次のようになります。
<ol class="toc-list" role="list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title<span class="leaders" aria-hidden="true"></span></span> <span class="page"><span class="visually-hidden">Page</span> 1</span> </a> <ol role="list"> <!-- subsection items --> </ol> </li>
</ol>
そしてCSSは次のようになります。
.toc-list li > a > .title { position: relative; overflow: hidden;
} .toc-list li > a .leaders::after { position: absolute; padding-left: .25ch; content: " . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . "; text-align: right;
}
これで、スクリーンリーダーはドットを無視し、アナウンスされている複数のドットを聞くことへのフラストレーションをユーザーに与えないようになります。
仕上げ
この時点で、目次コンポーネントはかなり見栄えがしますが、細かい作業が必要になる可能性があります。 まず、ほとんどの本は章のタイトルをサブセクションのタイトルから視覚的にオフセットしているので、トップレベルの項目を太字にし、サブセクションを後続の章から分離するためのマージンを導入しました。
.toc-list > li > a { font-weight: bold; margin-block-start: 1em;
}
次に、ページ番号の配置をクリーンアップしたいと思いました。 固定幅フォントを使用しているときはすべて問題ないように見えましたが、可変幅フォントの場合、ページ番号の幅に合わせてリーダードットがジグザグパターンを形成する可能性があります。 たとえば、1のページ番号は他のページ番号よりも狭くなり、リーダーのドットが前の行または次の行のドットとずれてしまいます。
この問題を解決するために、私は font-variant-numeric
〜へ tabular-nums
したがって、すべての数値は同じ幅で扱われます。 最小幅もに設定することにより 2ch
、XNUMX桁またはXNUMX桁のすべての数字が完全に整列していることを確認しました。 (これをに設定することをお勧めします 3ch
プロジェクトに100ページを超える場合。)ページ番号の最終的なCSSは次のとおりです。
.toc-list li > a > .page { min-width: 2ch; font-variant-numeric: tabular-nums; text-align: right;
}
これで目次が完成しました!
まとめ
HTMLとCSSだけで目次を作成することは、私が予想していたよりも困難でしたが、結果には非常に満足しています。 このアプローチは、チャプターとサブセクションに対応するのに十分な柔軟性があるだけでなく、CSSを更新せずにサブサブセクションを適切に処理します。 全体的なアプローチは、コンテンツのさまざまな場所にリンクするWebページ、および目次をさまざまなページにリンクするPDFで機能します。 そしてもちろん、パンフレットや本で使用したい場合は、印刷物でも見栄えがします。
JulieBlancとChristophGraboの目次の作成に関する優れたブログ投稿に感謝します。どちらも、私が始めたときは非常に貴重でした。 また、このプロジェクトに取り組んでいるときに、アクセシビリティに関するフィードバックを寄せてくれたSaraSoueidanにも感謝します。
HTML+CSSを使用した完璧な目次 最初に公開された CSSトリック。 あなたがすべき ニュースレターを入手する.
- "
- 100
- a
- 私たちについて
- 絶対の
- 接近性
- 対応する
- 達成する
- 越えて
- 追加されました
- NEW
- 住所
- すべて
- ことができます
- 既に
- 発表の
- 回答
- 申し込む
- アプローチ
- 適切な
- 周りに
- オート
- 自動化
- 基礎
- なぜなら
- 始まった
- さ
- の間に
- ブログ
- ブログの投稿
- ボード
- 大胆な
- ボーナス
- 本
- ボックス
- ビルド
- 場合
- 挑戦する
- 変化する
- 章
- 選択する
- class
- コラム
- 来ます
- コマンドと
- 複雑さ
- コンポーネント
- コンセプト
- お問合せ
- 考慮
- コンテナ
- コンテンツ
- 中身
- 基本
- 可能性
- 作成
- 決定しました
- 詳細
- 異なります
- 数字
- ディスプレイ
- ドキュメント
- 描画
- 各
- 要素は
- 乗り出す
- 埋め込まれた
- 設立
- すべてのもの
- 例
- 優れた
- 除外
- 運動
- 予想される
- 体験
- 特徴
- フィードバック
- 名
- 修正する
- フレキシブル
- フロー
- フォロー中
- 形式でアーカイブしたプロジェクトを保存します.
- 発見
- Foundation
- から
- function
- 根本的に
- 生成する
- 受け
- 良い
- でログイン
- 素晴らしい
- グリッド
- ハッピー
- 高さ
- 役立つ
- ことができます
- こちら
- 隠す
- しかしながら
- HTTPS
- 実装
- 重要
- 含まれました
- 個人
- 意図
- 問題
- IT
- JavaScriptを
- キープ
- リーダー
- リーダー
- ツェッペリン
- LINE
- ライン
- LINK
- リスト
- リストされた
- 耳を傾ける
- リスト
- 場所
- 長い
- 見
- 探して
- 製
- make
- 作る
- メイクアップ
- 手動で
- 地図
- 問題
- 事態
- 手段
- メディア
- Microsoft
- かもしれない
- 最小
- 他には?
- 最も
- の試合に
- すなわち
- 名
- ナビゲート
- ニーズ
- 数
- 番号
- 明白
- オフセット
- 良い
- オプション
- オプション
- 注文
- その他
- 全体
- 自分の
- 部
- パターン
- のワークプ
- 完璧
- ピース
- 計画されました
- プラン
- ポイント
- 位置
- 投稿
- かなり
- 前
- 問題
- 処理
- プロジェクト
- 財産
- 目的
- 目的
- RE
- リーダー
- 読者
- リーディング
- 実現する
- 実現
- 関係
- 表し
- 結果として
- 同じ
- 画面
- 自己出版
- 意味論
- セッションに
- 設定
- 簡単な拡張で
- サイズ
- So
- 溶液
- 解決する
- 一部
- 何か
- スペース
- 仕様
- start
- 開始
- まだ
- サポート
- したがって、
- 考え
- 三
- タイド
- 時間
- 役職
- 豊富なツール群
- トップレベル
- 伝統的な
- 変換
- 一般的に
- 理解する
- 更新
- つかいます
- users
- 値
- さまざまな
- バージョン
- 詳しく見る
- W3
- wanted
- ウェブ
- ウェブブラウザ
- この試験は
- while
- 風
- 以内
- 無し
- 仕事
- 働いていました
- 作品
- でしょう
- 書き込み
- 年
- あなたの