Popolno kazalo s HTML + CSS PlatoBlockchain Data Intelligence. Navpično iskanje. Ai.

Popolno kazalo s HTML + CSS

V začetku tega leta sem v samozaložbi izdal e-knjigo z naslovom Razumevanje obljub JavaScript (brezplačno za prenos). Čeprav je nisem imel namena spremeniti v tiskano knjigo, se je oglasilo dovolj ljudi, ki so povpraševali po tiskani različici, da sem se odločil, da bom tudi to izdal sam. Mislil sem, da bo to preprosta vaja z uporabo HTML in CSS ustvarite PDF in ga nato pošljite v tiskalnik. Nisem se zavedal, da nimam odgovora na pomemben del tiskane knjige: kazalo.

Sestava kazala vsebine

V svojem bistvu je kazalo dokaj preprosto. Vsaka vrstica predstavlja del knjige ali spletne strani in označuje, kje lahko najdete to vsebino. Običajno vrstice vsebujejo tri dele:

  1. Naslov poglavja ali razdelka
  2. Vodila (tj. pike, pomišljaji ali črte), ki vizualno povezujejo naslov s številko strani
  3. Številka strani

Kazalo vsebine je enostavno ustvariti v orodjih za obdelavo besedil, kot sta Microsoft Word ali Google Docs, toda ker je bila moja vsebina v Markdownu in nato preoblikovana v HTML, to zame ni bila dobra možnost. Želel sem nekaj avtomatiziranega, kar bi delovalo s HTML za ustvarjanje kazala v obliki, ki je primerna za tiskanje. Želel sem tudi, da je vsaka vrstica povezava, da bi jo lahko uporabili na spletnih straneh in PDF-jih za krmarjenje po dokumentu. Želel sem tudi vodila pik med naslovom in številko strani.

In tako sem začel raziskovati.

Naletel sem na dve odlični objavi v spletnem dnevniku o ustvarjanju kazala s HTML in CSS. Prvi je bil "Izdelajte kazalo vsebine iz svojega HTML-ja" avtorja Julie Blanc. Julie je delala naprej PagedJS, polifil za manjkajoče stranske medijske funkcije v spletnih brskalnikih, ki pravilno oblikuje dokumente za tiskanje. Začel sem z Julieinim primerom, vendar sem ugotovil, da zame ne deluje povsem. Nato sem našel Christopha Graba »Odzivne vodilne linije TOC s CSS« post, ki je uvedel koncept uporabe mreže CSS (v nasprotju z Julieinim pristopom, ki temelji na lebdeči obliki), da olajša poravnavo. Še enkrat pa njegov pristop ni bil povsem pravi za moje namene.

Ko sem prebral ti dve objavi, sem čutil, da dovolj dobro razumem težave s postavitvijo, da sem se lotil sam. Uporabil sem dele iz obeh objav v spletnem dnevniku ter v pristop dodal nekaj novih konceptov HTML in CSS, da sem prišel do rezultata, s katerim sem zadovoljen.

Izbira pravilne oznake

Ko sem se odločal za pravilno oznako za kazalo, sem razmišljal predvsem o pravilni semantiki. V osnovi gre pri kazalu za naslov (poglavje ali pododdelek), ki je vezan na številko strani, skoraj kot par ključ-vrednost. To me je pripeljalo do dveh možnosti:

  • Ena možnost je uporaba tabele (<table>) z enim stolpcem za naslov in enim stolpcem za stran.
  • Potem je tu še pogosto neuporabljen in pozabljen seznam definicij (<dl>) element. Deluje tudi kot zemljevid ključ-vrednost. Torej bi bilo še enkrat očitno razmerje med naslovom in številko strani.

Katera koli od teh se je zdela dobra možnost, dokler nisem ugotovil, da v resnici delujejo samo za enonivojska kazala, in sicer le, če bi želel imeti kazalo samo z imeni poglavij. Če pa bi želel prikazati pododdelke v kazalu, nisem imel nobene dobre možnosti. Elementi tabele niso dobri za hierarhične podatke, in čeprav je sezname definicij tehnično mogoče ugnezditi, se semantika ni zdela pravilna. Tako sem se vrnil k risalni deski.

Odločil sem se, da bom izhajal iz Juliejinega pristopa in uporabil seznam; vendar sem se odločil za urejen seznam (<ol>) namesto neurejenega seznama (<ul>). Mislim, da je v tem primeru bolj primeren urejen seznam. Kazalo vsebine predstavlja seznam poglavij in podnaslovov v vrstnem redu, v katerem se pojavljajo v vsebini. Vrstni red je pomemben in se ne sme izgubiti med oznakami.

Na žalost uporaba urejenega seznama pomeni izgubo semantičnega razmerja med naslovom in številko strani, zato je bil moj naslednji korak ponovno vzpostaviti to razmerje znotraj vsake postavke seznama. To najlažje rešite tako, da preprosto vstavite besedo »stran« pred številko strani. Tako je odnos številke glede na besedilo jasen, tudi brez kakršnega koli drugega vizualnega razlikovanja.

Tukaj je preprost skelet HTML, ki je bil osnova moje oznake:

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

Uporaba slogov na kazalu vsebine

Ko sem vzpostavil oznako, ki sem jo nameraval uporabiti, je bil naslednji korak uporaba nekaterih slogov.

Najprej sem odstranil samodejno ustvarjene številke. Če želite, se lahko odločite, da obdržite samodejno ustvarjene številke v svojem projektu, vendar je običajno, da imajo knjige neoštevilčene predgovore in pogovore, vključene na seznam poglavij, zaradi česar so samodejno ustvarjene številke nepravilne.

Za svoj namen bi ročno izpolnil številke poglavij in nato prilagodil postavitev, tako da seznam na najvišji ravni nima oblazinjenja (s čimer bi bil poravnan z odstavki), vsak vdelan seznam pa bi bil zamaknjen z dvema presledkoma. Odločil sem se za uporabo a 2ch padding value, ker še vedno nisem bil povsem prepričan, katero pisavo bi uporabil. The ch enota dolžine omogoča, da je oblazinjenje relativno glede na širino znaka – ne glede na to, katera pisava je uporabljena – namesto absolutne velikosti slikovnih pik, ki bi lahko na koncu izgledala nedosledno.

Tukaj je CSS, ki sem ga dobil:

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

Sara Soueidan me je opozoril, da brskalniki WebKit odstranijo semantiko seznama, ko list-style-type is none, zato sem moral dodati role="list" v HTML, da ga ohranite:

<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>
CodePen Embed Fallback

Oblikovanje naslova in številke strani

Ko je bil seznam oblikovan po mojih željah, je bil čas, da preidem na oblikovanje posameznega elementa seznama. Za vsako postavko v kazalu morata biti naslov in številka strani v isti vrstici, z naslovom na levi in ​​številko strani poravnano na desno.

Morda si mislite: "Ni problema, temu je namenjen flexbox!" Saj se ne motiš! Flexbox lahko dejansko doseže pravilno poravnavo naslovne strani. Toda pri dodajanju vodil je nekaj zapletenih težav s poravnavo, zato sem se raje odločil za Christophov pristop z uporabo mreže, kar je dodatek, saj pomaga tudi pri večvrstičnih naslovih. Tukaj je CSS za posamezno postavko:

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

Mreža ima dva stolpca, od katerih je prvi auto- velikosti, da zapolni celotno širino posode, brez drugega stolpca, ki je velikosti max-content. Številka strani je poravnana na desno, kot je običajno v kazalu vsebine.

Edina druga sprememba, ki sem jo naredil na tej točki, je bila skrivanje besedila »Stran«. To je koristno za bralnike zaslona, ​​vendar vizualno nepotrebno, zato sem uporabil a tradicionalna visually-hidden razred da ga skrijete pred očmi:

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

In seveda je treba HTML posodobiti za uporabo tega razreda:

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

S to osnovo sem se premaknil k nagovarjanju voditeljev med naslovom in stranjo.

CodePen Embed Fallback

Ustvarjanje vodil pik

Voditelji so v tiskanih medijih tako pogosti, da se morda sprašujete, zakaj CSS tega že ne podpira? Odgovor je: to počne. No, nekako.

Dejansko obstaja a leader() funkcija, definirana v CSS Generated Content for Paged Media specifikacija. Vendar, tako kot pri večini specifikacij stranskih medijev, ta funkcija ni implementirana v nobenem brskalniku, zato je izključena kot možnost (vsaj v času, ko to pišem). Sploh ni na seznamu caniuse.com, menda zato, ker tega ni nihče uresničil in ni načrtov ali signalov, da ga bodo.

Na srečo sta Julie in Christoph že obravnavala ta problem v svojih objavah. Za vstavljanje vodil pik sta oba uporabila a ::after psevdoelement s svojim content lastnost nastavljena na zelo dolg niz pik, kot je ta:

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

O ::after psevdoelement je nastavljen na absolutni položaj, da ga odstrani iz toka strani in prepreči prelivanje v druge vrstice. Besedilo je poravnano na desno, ker želimo, da se zadnje pike vsake vrstice poravnajo s številko na koncu vrstice. (Več o kompleksnosti tega kasneje.) The .title element je nastavljen tako, da ima relativni položaj, tako da ::after psevdoelement ne pobegne iz svoje škatle. Medtem je overflow je skrit, tako da so vse te dodatne pike nevidne. Rezultat je lepo kazalo z vodilnimi točkami.

Vendar je treba upoštevati še nekaj.

Sara me je tudi opozorila, da vse te pike štejejo kot besedilo za bralnike zaslona. Torej, kaj slišite? "Uvod pika pika pika pika ..." dokler niso objavljene vse pike. To je grozna izkušnja za uporabnike bralnikov zaslona.

Rešitev je vstavljanje dodatnega elementa z aria-hidden nastavljena true in nato s tem elementom vstavite pike. Tako HTML postane:

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

In CSS postane:

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

Zdaj bodo bralniki zaslona ignorirali pike in uporabnikom prihranili frustracije ob poslušanju oglaševanja več pik.

CodePen Embed Fallback

Zaključni dotiki

Na tej točki je komponenta kazala videti precej dobra, vendar bi lahko potrebovala nekaj manjših podrobnosti. Za začetek večina knjig vizualno zamakne naslove poglavij od naslovov pododdelkov, zato sem elemente na najvišji ravni naredil krepko in uvedel rob za ločevanje pododdelkov od poglavij, ki sledijo:

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

Nato sem želel počistiti poravnavo številk strani. Vse je bilo videti v redu, ko sem uporabljal pisavo s fiksno širino, toda pri pisavah s spremenljivo širino bi vodilne pike lahko na koncu tvorile cik-cak vzorec, ko se prilagajajo širini številke strani. Na primer, katera koli številka strani z 1 bi bila ožja od drugih, kar bi povzročilo vodilne pike, ki niso poravnane s pikami v prejšnjih ali naslednjih vrsticah.

Neporavnane številke in pike v kazalu vsebine.
Popolno kazalo s HTML + CSS

Za odpravo te težave sem nastavil font-variant-numeric do tabular-nums tako so vse številke obravnavane z enako širino. Z nastavitvijo najmanjše širine na 2ch, sem zagotovil, da so vse številke z eno ali dvema števkama popolnoma poravnane. (Morda boste to želeli nastaviti na 3ch če ima vaš projekt več kot 100 strani.) Tukaj je končni CSS za številko strani:

.toc-list li > a > .page { min-width: 2ch; font-variant-numeric: tabular-nums; text-align: right;
}
Poravnane glavne pike v kazalu vsebine.
Popolno kazalo s HTML + CSS

In s tem je kazalo končano!

CodePen Embed Fallback

zaključek

Ustvarjanje kazala s samo HTML in CSS je bil večji izziv, kot sem pričakoval, vendar sem z rezultatom zelo zadovoljen. Ne samo, da je ta pristop dovolj prilagodljiv za prilagoditev poglavjem in pododdelkom, ampak tudi lepo obravnava pododdelke brez posodabljanja CSS. Celoten pristop deluje na spletnih straneh, kjer želite povezave do različnih lokacij vsebine, kot tudi pri PDF-jih, kjer želite, da se kazalo poveže z različnimi stranmi. In seveda je videti odlično tudi v tisku, če bi ga kdaj želeli uporabiti v brošuri ali knjigi.

Rad bi se zahvalil Julie Blanc in Christophu Grabu za njune odlične objave v spletnem dnevniku o ustvarjanju kazala vsebine, saj sta bila oba neprecenljiva, ko sem začenjal. Prav tako bi se rad zahvalil Sari Soueidan za njene povratne informacije o dostopnosti, ko sem delal na tem projektu.


Popolno kazalo s HTML + CSS prvotno objavljeno na CSS-triki. Moral bi prejemanje glasila.

Časovni žig:

Več od Triki CSS