Täydellinen sisällysluettelo HTML + CSS PlatoBlockchain Data Intelligencellä. Pystysuuntainen haku. Ai.

Täydellinen sisällysluettelo HTML + CSS:llä

Aiemmin tänä vuonna julkaisin itse e-kirjan nimeltä JavaScript-lupausten ymmärtäminen (ilmaiseksi ladattavaksi). Vaikka minulla ei ollut aikomustakaan tehdä siitä painettua kirjaa, niin monet ihmiset kysyivät painetusta versiosta, joten päätin julkaista sen myös itse. Ajattelin, että se olisi helppo harjoitus käyttää HTML- ja CSS-syötteitä. Luo PDF ja lähetä se sitten tulostimelle. En tajunnut, että minulla ei ollut vastausta painetun kirjan tärkeään osaan: sisällysluetteloon.

Sisällysluettelon rakenne

Sisällysluettelo on pohjimmiltaan melko yksinkertainen. Jokainen rivi edustaa osaa kirjasta tai verkkosivusta ja osoittaa, mistä voit löytää kyseisen sisällön. Tyypillisesti rivit sisältävät kolme osaa:

  1. Luvun tai osan otsikko
  2. Johtimet (eli ne pisteet, katkoviivat tai viivat), jotka yhdistävät visuaalisesti otsikon sivunumeroon
  3. Sivunumero

Sisällysluettelo on helppo luoda tekstinkäsittelytyökaluilla, kuten Microsoft Wordilla tai Google Docsilla, mutta koska sisältöni oli Markdownissa ja muutettu sitten HTML:ksi, se ei ollut hyvä vaihtoehto minulle. Halusin jotain automatisoitua, joka toimisi HTML:n kanssa luomaan sisällysluettelon tulostukseen sopivassa muodossa. Halusin myös jokaisen rivin olevan linkki, jotta sitä voitaisiin käyttää verkkosivuilla ja PDF-tiedostoissa dokumentissa liikkumiseen. Halusin myös pisteviivat otsikon ja sivunumeron väliin.

Ja niin aloin tutkia.

Löysin kaksi erinomaista blogitekstiä sisällysluettelon luomisesta HTML:n ja CSS:n avulla. Ensimmäinen oli "Rakenna sisällysluettelo HTML-koodistasi" Kirjailija: Julie Blanc Julie työskenteli PagedJS, verkkoselaimien puuttuvien sivuttujen mediaominaisuuksien monitäyttö, joka muotoilee asiakirjat oikein tulostusta varten. Aloitin Julien esimerkistä, mutta huomasin, että se ei oikein toiminut minulle. Seuraavaksi löysin Christoph Grabon "Responsiiviset TOC-johtolinjat CSS:llä" post, jossa esiteltiin CSS Grid -konsepti (toisin kuin Julien float-pohjainen lähestymistapa) kohdistamisen helpottamiseksi. Mutta jälleen kerran, hänen lähestymistapansa ei ollut aivan oikea tarkoituksiini.

Luettuani nämä kaksi viestiä, minusta tuntui, että minulla oli tarpeeksi hyvä ymmärrys asettelukysymyksistä aloittaakseni itse. Käytin palasia molemmista blogikirjoituksista sekä lisäsin lähestymistapaan uusia HTML- ja CSS-konsepteja saadakseni tuloksen, johon olen tyytyväinen.

Oikean merkinnän valinta

Kun päätin sisällysluettelon oikeasta merkinnästä, ajattelin ensisijaisesti oikeaa semantiikkaa. Pohjimmiltaan sisällysluettelo on otsikko (luku tai alakohta), joka on sidottu sivunumeroon, melkein kuin avain-arvo-pari. Tämä johti minut kahteen vaihtoehtoon:

  • Yksi vaihtoehto on käyttää taulukkoa (<table>), jossa on yksi sarake otsikolle ja yksi sarake sivulle.
  • Sitten on usein käyttämätön ja unohdettu määritelmäluettelo (<dl>) elementti. Se toimii myös avainarvokartana. Joten jälleen kerran, otsikon ja sivunumeron välinen suhde olisi ilmeinen.

Kumpikin näistä vaikutti hyviltä vaihtoehdoilta, kunnes tajusin, että ne todella toimivat vain yksitasoisille sisällysluetteloille, nimittäin vain, jos halusin sisällysluettelon, jossa on vain lukujen nimiä. Jos halusin näyttää alaosat sisällysluettelossa, minulla ei kuitenkaan ollut hyviä vaihtoehtoja. Taulukkoelementit eivät sovellu hierarkkisille tiedoille, ja vaikka määritelmäluettelot voidaan teknisesti sisäkkäin, semantiikka ei vaikuttanut oikealta. Joten palasin piirustuspöydän ääreen.

Päätin rakentaa Julien lähestymistavan ja käyttää luetteloa; valitsin kuitenkin tilatun listan (<ol>) järjestämättömän luettelon sijaan (<ul>). Mielestäni järjestetty luettelo on sopivampi tässä tapauksessa. Sisällysluettelo edustaa luetteloa luvuista ja alaotsikoista siinä järjestyksessä, jossa ne esiintyvät sisällössä. Järjestyksellä on väliä, eikä se saa kadota merkinnöissä.

Valitettavasti järjestetyn luettelon käyttäminen merkitsee otsikon ja sivunumeron välisen semanttisen suhteen menettämistä, joten seuraava askeleni oli luoda tämä suhde uudelleen jokaisen luettelokohteen sisällä. Helpoin tapa ratkaista tämä on yksinkertaisesti lisätä sana "sivu" ennen sivunumeroa. Näin luvun suhde tekstiin on selkeä, jopa ilman muuta visuaalista eroa.

Tässä on yksinkertainen HTML-runko, joka muodosti merkintäni perustan:

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

Tyylien soveltaminen sisällysluetteloon

Kun olin määrittänyt käyttämäni merkinnät, seuraava askel oli soveltaa joitain tyylejä.

Ensin poistin automaattisesti luodut numerot. Voit halutessasi säilyttää automaattisesti luodut numerot omassa projektissasi, mutta on yleistä, että kirjoissa on numeroimattomia esi- ja jälkisanoja, jotka sisältyvät lukuluetteloon, mikä tekee automaattisesti luoduista numeroista virheellisiä.

Omaa tarkoitusta varten täytän lukujen numerot manuaalisesti ja säätäisin sitten asettelua niin, että ylimmän tason luettelossa ei ole täyttöä (täten tasaisin sen kappaleiden kanssa) ja jokainen upotettu luettelo on sisennetty kahdella välilyönnillä. Päätin käyttää a 2ch täytearvoa, koska en vieläkään ollut aivan varma, mitä fonttia käyttäisin. The ch pituusyksikkö sallii täytön olevan suhteessa merkin leveyteen – käytetystä kirjasimesta riippumatta – absoluuttisen pikselikoon sijaan, joka saattaa näyttää epäjohdonmukaiselta.

Tässä on CSS, johon päädyin:

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

Sara Soueidan huomautti minulle, että WebKit-selaimet poistavat luettelon semantiikan, kun list-style-type is none, joten minun piti lisätä role="list" HTML-koodiin sen säilyttämiseksi:

<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

Otsikon ja sivunumeron muotoilu

Kun lista oli tyylitelty minun makuuni, oli aika siirtyä yksittäisen listakohteen muotoiluun. Jokaisen sisällysluettelon otsikon ja sivunumeron on oltava samalla rivillä otsikon vasemmalla ja sivunumeron oikealla puolella.

Saatat ajatella: "Ei hätää, flexbox on sitä varten!" Et ole väärässä! Flexbox voi todellakin saavuttaa oikean otsikkosivun kohdistuksen. Mutta on joitain hankalia kohdistusongelmia, kun johtajat lisätään, joten valitsin sen sijaan Christophin lähestymistavan käyttämällä ruudukkoa, mikä bonuksena auttaa myös monirivisissä nimikkeissä. Tässä on yksittäisen kohteen 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;
}

Ruudukossa on kaksi saraketta, joista ensimmäinen on auto-kokoinen täyttämään säiliön koko leveyden, vähennettynä toisella sarakkeella, joka on mitoitettu max-content. Sivunumero on tasattu oikealle, kuten sisällysluettelossa perinteisesti.

Ainoa muu muutos, jonka tein tässä vaiheessa, oli piilottaa "Sivu"-teksti. Tämä on hyödyllinen näytönlukuohjelmille, mutta tarpeeton visuaalisesti, joten käytin a perinteinen visually-hidden luokka piilottaaksesi sen näkyvistä:

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

Ja tietysti HTML-koodi on päivitettävä käyttääksesi tätä luokkaa:

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

Kun tämä perusta oli paikallaan, siirryin puhumaan johtajille otsikon ja sivun välillä.

CodePen Embed Fallback

Pistejohtajien luominen

Johtajat ovat niin yleisiä painetussa mediassa, että saatat ihmetellä, miksi CSS ei jo tue sitä? Vastaus on: se tekee. No, sellainen.

Siellä on itse asiassa a leader() määritetty toiminto CSS:n luoma sisältö Paged Media -määrityksiä varten. Kuitenkin, kuten useimmat sivutut mediatiedot, tätä toimintoa ei ole toteutettu missään selaimessa, joten se ei ole mahdollista (ainakin tätä kirjoittaessani). Sitä ei ole edes listattu caniuse.com, oletettavasti siksi, että kukaan ei ole toteuttanut sitä, eikä ole olemassa suunnitelmia tai signaaleja, että ne toteuttaisivat.

Onneksi sekä Julie että Christoph käsittelivät tätä ongelmaa jo omissa viesteissään. Pistemerkkien lisäämiseksi he molemmat käyttivät a ::after pseudoelementti sen kanssa content ominaisuus asetettu erittäin pitkäksi pistejonoksi, kuten tämä:

.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 pseudoelementti asetetaan absoluuttiseen asentoon, jotta se poistuu sivun virrasta ja vältetään rivittäminen muille riveille. Teksti on tasattu oikealle, koska haluamme jokaisen rivin viimeisen pisteen olevan rivin lopussa olevan numeron tasolla. (Lisää tämän monimutkaisuudesta myöhemmin.) .title elementillä on suhteellinen sijainti, joten ::after pseudoelementti ei irtoa laatikostaan. Samaan aikaan, overflow on piilotettu, joten kaikki ylimääräiset pisteet ovat näkymättömiä. Tuloksena on kaunis sisällysluettelo, jossa on pisteviivat.

On kuitenkin jotain muuta, joka vaatii huomion.

Sara huomautti minulle myös, että kaikki nuo pisteet lasketaan tekstiksi näytönlukuohjelmille. Joten mitä kuulet? "Johdatus piste piste piste piste…", kunnes kaikki pisteet on ilmoitettu. Se on kauhea kokemus näytönlukuohjelman käyttäjille.

Ratkaisu on lisätä lisäelementti aria-hidden asetettu true ja käytä sitten tätä elementtiä pisteiden lisäämiseen. Joten HTML:stä tulee:

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

Ja CSS:stä tulee:

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

Nyt näytönlukijat jättävät huomioimatta pisteet ja säästävät käyttäjät turhautumiselta, kun he kuuntelevat useita ilmoituksia.

CodePen Embed Fallback

Viimeistelyt

Tässä vaiheessa sisällysluettelokomponentti näyttää melko hyvältä, mutta se voisi vaatia pieniä yksityiskohtia. Aluksi useimmat kirjat erottivat visuaalisesti lukujen otsikot alaosastojen otsikoista, joten lihavoitin ylimmän tason kohdat ja lisäsin marginaalin erottamaan alaosat seuraavista luvuista:

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

Seuraavaksi halusin puhdistaa sivunumeroiden kohdistuksen. Kaikki näytti olevan kunnossa, kun käytin kiinteäleveistä fonttia, mutta muuttuvan leveyden fonttien kohdalla alkupisteet saattoivat muodostaa siksak-kuvion, kun ne mukautuvat sivunumeron leveyteen. Esimerkiksi mikä tahansa sivunumero, jossa on 1, olisi kapeampi kuin toiset, mikä johtaisi alkupisteisiin, jotka on kohdistettu väärin edellisten tai seuraavien rivien pisteisiin.

Väärin kohdistetut numerot ja pisteet sisällysluettelossa.
Täydellinen sisällysluettelo HTML + CSS:llä

Korjatakseni tämän ongelman asetin font-variant-numeric että tabular-nums joten kaikkia numeroita käsitellään samalla leveydellä. Asettamalla myös vähimmäisleveydeksi 2ch, varmistin, että kaikki luvut, joissa on yksi tai kaksi numeroa, ovat täysin kohdakkain. (Haluat ehkä asettaa tämän 3ch jos projektissasi on yli 100 sivua.) Tässä on lopullinen CSS sivunumerolle:

.toc-list li > a > .page { min-width: 2ch; font-variant-numeric: tabular-nums; text-align: right;
}
Tasaiset alkupisteet sisällysluettelossa.
Täydellinen sisällysluettelo HTML + CSS:llä

Ja sen myötä sisällysluettelo on valmis!

CodePen Embed Fallback

Yhteenveto

Sisällysluettelon luominen vain HTML:llä ja CSS:llä oli haasteellisempi kuin odotin, mutta olen erittäin tyytyväinen tulokseen. Tämä lähestymistapa ei ole vain riittävän joustava lukujen ja alaosien mukauttamiseksi, vaan se käsittelee alaosat hienosti ilman CSS:n päivittämistä. Yleinen lähestymistapa toimii verkkosivuilla, joilla haluat linkittää sisällön eri paikkoihin, sekä PDF-tiedostoissa, joiden sisällysluettelon haluat linkittää eri sivuille. Ja tietysti se näyttää hyvältä myös painettuna, jos olet joskus taipuvainen käyttämään sitä esitteessä tai kirjassa.

Haluan kiittää Julie Blancia ja Christoph Graboa heidän erinomaisista blogikirjoituksistaan ​​sisällysluettelon luomiseen, sillä molemmat olivat korvaamattomia, kun aloitin. Haluaisin myös kiittää Sara Soueidania hänen saavutettavuuspalautteestaan ​​työskennellessäni tämän projektin parissa.


Täydellinen sisällysluettelo HTML + CSS:llä alun perin julkaistu CSS-temppuja. Sinun pitäisi hanki uutiskirje.

Aikaleima:

Lisää aiheesta CSS-temppuja