Daftar Isi Sempurna Dengan Intelijen Data HTML + CSS PlatoBlockchain. Pencarian Vertikal. ai.

Daftar Isi Sempurna Dengan HTML + CSS

Awal tahun ini, saya menerbitkan sendiri sebuah ebook berjudul Memahami Janji JavaScript (gratis untuk diunduh). Meskipun saya tidak berniat mengubahnya menjadi buku cetak, cukup banyak orang yang bertanya tentang versi cetak sehingga saya memutuskan untuk menerbitkannya sendiri. Saya pikir ini akan menjadi latihan yang mudah menggunakan HTML dan CSS untuk menghasilkan PDF dan kemudian mengirimkannya ke printer. Apa yang tidak saya sadari adalah bahwa saya tidak memiliki jawaban untuk bagian penting dari sebuah buku cetak: daftar isi.

Susunan daftar isi

Pada intinya, daftar isi cukup sederhana. Setiap baris mewakili bagian dari buku atau halaman web dan menunjukkan di mana Anda dapat menemukan konten tersebut. Biasanya, garis berisi tiga bagian:

  1. Judul bab atau bagian
  2. Pemimpin (yaitu titik, garis, atau garis) yang secara visual menghubungkan judul dengan nomor halaman
  3. Nomor halaman

Daftar isi mudah dibuat di dalam alat pengolah kata seperti Microsoft Word atau Google Docs, tetapi karena konten saya dalam Markdown dan kemudian diubah menjadi HTML, itu bukan pilihan yang baik bagi saya. Saya menginginkan sesuatu yang otomatis yang akan bekerja dengan HTML untuk menghasilkan daftar isi dalam format yang cocok untuk dicetak. Saya juga ingin setiap baris menjadi tautan sehingga dapat digunakan di halaman web dan PDF untuk bernavigasi di sekitar dokumen. Saya juga ingin tanda titik di antara judul dan nomor halaman.

Dan jadi saya mulai meneliti.

Saya menemukan dua posting blog yang sangat bagus tentang membuat daftar isi dengan HTML dan CSS. Yang pertama adalah “Buat Daftar Isi dari HTML Anda” oleh Julie Blanc. Julie bekerja HalamanJS, polyfill untuk fitur media halaman yang hilang di browser web yang memformat dokumen dengan benar untuk dicetak. Saya mulai dengan contoh Julie, tetapi ternyata itu tidak berhasil untuk saya. Selanjutnya, saya menemukan Christoph Grabo's “Garis pemimpin TOC yang responsif dengan CSS” post, yang memperkenalkan konsep penggunaan CSS Grid (sebagai lawan dari pendekatan berbasis float Julie) untuk mempermudah penyelarasan. Namun, sekali lagi, pendekatannya tidak tepat untuk tujuan saya.

Namun, setelah membaca dua posting ini, saya merasa memiliki pemahaman yang cukup baik tentang masalah tata letak untuk memulai sendiri. Saya menggunakan potongan dari kedua posting blog serta menambahkan beberapa konsep HTML dan CSS baru ke dalam pendekatan untuk menghasilkan hasil yang saya senangi.

Memilih markup yang benar

Saat memutuskan markup yang benar untuk daftar isi, saya terutama memikirkan tentang semantik yang benar. Pada dasarnya, daftar isi adalah tentang judul (bab atau subbagian) yang diikat ke nomor halaman, hampir seperti pasangan nilai kunci. Itu membawa saya ke dua opsi:

  • Salah satu opsi adalah menggunakan tabel (<table>) dengan satu kolom untuk judul dan satu kolom untuk halaman.
  • Lalu ada daftar definisi yang sering tidak digunakan dan dilupakan (<dl>) elemen. Ini juga bertindak sebagai peta nilai kunci. Jadi, sekali lagi, hubungan antara judul dan nomor halaman akan terlihat jelas.

Salah satu dari ini tampak seperti pilihan yang baik sampai saya menyadari bahwa mereka benar-benar hanya bekerja untuk satu tingkat daftar isi, yaitu, hanya jika saya ingin memiliki daftar isi hanya dengan nama bab. Namun, jika saya ingin menampilkan subbagian dalam daftar isi, saya tidak memiliki opsi yang bagus. Elemen tabel tidak bagus untuk data hierarkis, dan sementara daftar definisi secara teknis dapat disarangkan, semantik tampaknya tidak benar. Jadi, saya kembali ke papan gambar.

Saya memutuskan untuk membangun pendekatan Julie dan menggunakan daftar; namun, saya memilih daftar pesanan (<ol>) alih-alih daftar yang tidak berurutan (<ul>). Saya pikir daftar yang dipesan lebih tepat dalam kasus ini. Daftar isi mewakili daftar bab dan subjudul sesuai urutan kemunculannya dalam konten. Urutan itu penting dan tidak boleh hilang dalam markup.

Sayangnya, menggunakan daftar berurutan berarti kehilangan hubungan semantik antara judul dan nomor halaman, jadi langkah saya selanjutnya adalah membangun kembali hubungan itu di dalam setiap item daftar. Cara termudah untuk mengatasi ini adalah dengan hanya memasukkan kata "halaman" sebelum nomor halaman. Dengan begitu, hubungan angka relatif terhadap teks menjadi jelas, bahkan tanpa perbedaan visual lainnya.

Berikut adalah kerangka HTML sederhana yang menjadi dasar markup saya:

<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>

Menerapkan gaya ke daftar isi

Setelah saya menetapkan markup yang saya rencanakan untuk digunakan, langkah selanjutnya adalah menerapkan beberapa gaya.

Pertama, saya menghapus nomor yang dibuat secara otomatis. Anda dapat memilih untuk menyimpan nomor yang dibuat secara otomatis dalam proyek Anda sendiri jika Anda mau, tetapi biasanya buku memiliki kata pengantar dan kata penutup yang tidak diberi nomor yang disertakan dalam daftar bab, yang membuat nomor yang dibuat secara otomatis menjadi salah.

Untuk tujuan saya, saya akan mengisi nomor bab secara manual kemudian menyesuaikan tata letak sehingga daftar tingkat atas tidak memiliki bantalan (sehingga menyelaraskannya dengan paragraf) dan setiap daftar yang disematkan diindentasi oleh dua spasi. Saya memilih untuk menggunakan 2ch nilai padding karena saya masih tidak yakin font mana yang akan saya gunakan. Itu ch unit panjang memungkinkan padding menjadi relatif terhadap lebar karakter — tidak peduli font apa yang digunakan — daripada ukuran piksel absolut yang bisa berakhir terlihat tidak konsisten.

Inilah CSS yang saya dapatkan:

.toc-list, .toc-list ol { list-style-type: none;
} .toc-list { padding: 0;
} .toc-list ol { padding-inline-start: 2ch;
}

Sara Soueidan menunjukkan kepada saya bahwa browser WebKit menghapus semantik daftar ketika list-style-type is none, jadi saya perlu menambahkan role="list" ke dalam HTML untuk melestarikannya:

<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>
Penggantian Penyematan CodePen

Menata judul dan nomor halaman

Dengan daftar yang ditata sesuai dengan keinginan saya, sudah waktunya untuk beralih ke menata item daftar individual. Untuk setiap item dalam daftar isi, judul dan nomor halaman harus berada pada baris yang sama, dengan judul di sebelah kiri dan nomor halaman di sebelah kanan.

Anda mungkin berpikir, “Tidak masalah, untuk itulah flexbox!” Anda tidak salah! Flexbox memang dapat mencapai perataan halaman judul yang benar. Tetapi ada beberapa masalah penyelarasan yang rumit ketika pemimpin ditambahkan, jadi saya memilih untuk menggunakan pendekatan Christoph menggunakan kisi, yang sebagai bonus karena juga membantu dengan judul multiline. Berikut adalah CSS untuk masing-masing item:

.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;
}

Grid memiliki dua kolom, yang pertama adalah auto-size untuk mengisi seluruh lebar wadah, dikurangi kolom kedua, yang berukuran max-content. Nomor halaman disejajarkan ke kanan, seperti biasa dalam daftar isi.

Satu-satunya perubahan lain yang saya buat saat ini adalah menyembunyikan teks "Halaman". Ini berguna untuk pembaca layar tetapi tidak perlu secara visual, jadi saya menggunakan a tradisional visually-hidden kelas untuk menyembunyikannya dari pandangan:

.visually-hidden { clip: rect(0 0 0 0); clip-path: inset(100%); height: 1px; overflow: hidden; position: absolute; width: 1px; white-space: nowrap;
}

Dan, tentu saja, HTML perlu diperbarui untuk menggunakan kelas itu:

<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>

Dengan dasar ini di tempat, saya pindah ke alamat pemimpin antara judul dan halaman.

Penggantian Penyematan CodePen

Membuat pemimpin titik

Pemimpin sangat umum di media cetak sehingga Anda mungkin bertanya-tanya, mengapa CSS belum mendukungnya? Jawabannya adalah: itu benar. Yah, semacam itu.

Sebenarnya ada leader() fungsi yang ditentukan dalam Konten yang Dihasilkan CSS untuk spesifikasi Media Berhalaman. Namun, seperti banyak spesifikasi media halaman, fungsi ini tidak diterapkan di browser mana pun, oleh karena itu mengecualikannya sebagai opsi (setidaknya pada saat saya menulis ini). Itu bahkan tidak terdaftar di caniuse.com, mungkin karena tidak ada yang mengimplementasikannya dan tidak ada rencana atau sinyal bahwa mereka akan melakukannya.

Untungnya, baik Julie maupun Christoph sudah membahas masalah ini di postingan masing-masing. Untuk menyisipkan pemimpin titik, mereka berdua menggunakan ::after elemen semu dengannya content properti diatur ke string titik yang sangat panjang, seperti ini:

.toc-list li > a > .title { position: relative; overflow: hidden;
} .toc-list li > a .title::after { position: absolute; padding-left: .25ch; content: " . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . "; text-align: right;
}

Grafik ::after pseudo-element diatur ke posisi absolut untuk mengeluarkannya dari aliran halaman dan menghindari pembungkusan ke baris lain. Teks diratakan ke kanan karena kita ingin titik terakhir dari setiap baris rata dengan nomor di akhir baris. (Lebih lanjut tentang kompleksitas ini nanti.) .title elemen diatur untuk memiliki posisi relatif sehingga ::after pseudo-element tidak keluar dari kotaknya. Sementara itu, overflow disembunyikan sehingga semua titik ekstra itu tidak terlihat. Hasilnya adalah daftar isi yang cantik dengan pemimpin titik.

Namun, ada hal lain yang perlu dipertimbangkan.

Sara juga menunjukkan kepada saya bahwa semua titik itu dihitung sebagai teks ke pembaca layar. Jadi apa yang Anda dengar? “Pengenalan dot dot dot dot…” sampai semua titik diumumkan. Itu adalah pengalaman yang mengerikan bagi pengguna pembaca layar.

Solusinya adalah dengan memasukkan elemen tambahan dengan aria-hidden mulai true dan kemudian gunakan elemen itu untuk menyisipkan titik-titik. Sehingga HTMLnya menjadi:

<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>

Dan CSSnya menjadi:

.toc-list li > a > .title { position: relative; overflow: hidden;
} .toc-list li > a .leaders::after { position: absolute; padding-left: .25ch; content: " . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . "; text-align: right;
}

Sekarang pembaca layar akan mengabaikan titik-titik dan membuat pengguna tidak frustrasi mendengarkan banyak titik yang diumumkan.

Penggantian Penyematan CodePen

Sentuhan akhir

Pada titik ini, komponen daftar isi terlihat cukup bagus, tetapi bisa menggunakan beberapa pekerjaan detail kecil. Untuk memulai, sebagian besar buku secara visual mengimbangi judul bab dari judul subbagian, jadi saya membuat item tingkat atas tebal dan memperkenalkan margin untuk memisahkan subbagian dari bab-bab berikutnya:

.toc-list > li > a { font-weight: bold; margin-block-start: 1em;
}

Selanjutnya, saya ingin membersihkan perataan nomor halaman. Semuanya tampak baik-baik saja ketika saya menggunakan font dengan lebar tetap, tetapi untuk font dengan lebar variabel, titik-titik pemimpin akhirnya dapat membentuk pola zigzag saat mereka menyesuaikan dengan lebar nomor halaman. Misalnya, nomor halaman apa pun dengan 1 akan lebih sempit daripada yang lain, menghasilkan titik-titik pemimpin yang tidak sejajar dengan titik-titik pada baris sebelumnya atau berikutnya.

Angka dan titik tidak sejajar dalam daftar isi.
Daftar Isi Sempurna Dengan HTML + CSS

Untuk memperbaiki masalah ini, saya mengatur font-variant-numeric untuk tabular-nums jadi semua angka diperlakukan dengan lebar yang sama. Dengan juga mengatur lebar minimum ke 2ch, saya memastikan bahwa semua angka dengan satu atau dua digit sejajar dengan sempurna. (Anda mungkin ingin mengatur ini ke 3ch jika proyek Anda memiliki lebih dari 100 halaman.) Berikut adalah CSS terakhir untuk nomor halaman:

.toc-list li > a > .page { min-width: 2ch; font-variant-numeric: tabular-nums; text-align: right;
}
Titik-titik pemimpin sejajar dalam daftar isi.
Daftar Isi Sempurna Dengan HTML + CSS

Dan dengan itu, daftar isi selesai!

Penggantian Penyematan CodePen

Kesimpulan

Membuat daftar isi dengan HTML dan CSS lebih merupakan tantangan daripada yang saya harapkan, tetapi saya sangat senang dengan hasilnya. Pendekatan ini tidak hanya cukup fleksibel untuk mengakomodasi bab dan subbagian, tetapi juga menangani sub-subbagian dengan baik tanpa memperbarui CSS. Pendekatan keseluruhan bekerja pada halaman web di mana Anda ingin menautkan ke berbagai lokasi konten, serta PDF di mana Anda ingin daftar isi ditautkan ke halaman yang berbeda. Dan tentu saja, itu juga terlihat bagus di media cetak jika Anda ingin menggunakannya dalam brosur atau buku.

Saya ingin mengucapkan terima kasih kepada Julie Blanc dan Christoph Grabo atas posting blog mereka yang luar biasa dalam membuat daftar isi, karena keduanya sangat berharga ketika saya memulai. Saya juga ingin berterima kasih kepada Sara Soueidan atas umpan balik aksesibilitasnya saat saya mengerjakan proyek ini.


Daftar Isi Sempurna Dengan HTML + CSS awalnya diterbitkan pada Trik CSS. Kamu harus dapatkan buletin.

Stempel Waktu:

Lebih dari Trik CSS