Tökéletes tartalomjegyzék HTML + CSS PlatoBlockchain adatintelligenciával. Függőleges keresés. Ai.

Tökéletes tartalomjegyzék HTML + CSS segítségével

Az év elején saját kiadásban adtam ki egy e-könyvet A JavaScript ígéreteinek megértése (ingyenesen letölthető). Annak ellenére, hogy nem állt szándékomban nyomtatott könyvet készíteni, elég sokan keresték fel a nyomtatott változat iránt érdeklődve, és úgy döntöttem, hogy azt is kiadom. készítsen egy PDF-fájlt, majd küldje el a nyomtatóra. Nem vettem észre, hogy nincs válaszom egy nyomtatott könyv egy fontos részére: a tartalomjegyzékre.

A tartalomjegyzék felépítése

Lényegében a tartalomjegyzék meglehetősen egyszerű. Minden sor egy könyv vagy weboldal egy részét jelöli, és jelzi, hol található az adott tartalom. A sorok általában három részből állnak:

  1. A fejezet vagy szakasz címe
  2. Vezetők (azaz azok a pontok, kötőjelek vagy vonalak), amelyek vizuálisan összekapcsolják a címet az oldalszámmal
  3. Az oldalszám

A tartalomjegyzéket könnyű létrehozni olyan szövegszerkesztő eszközökön belül, mint a Microsoft Word vagy a Google Docs, de mivel a tartalom Markdown-ban volt, majd HTML-be alakították át, ez nem volt jó lehetőség számomra. Valami automatizáltat szerettem volna, ami HTML-lel működik, hogy nyomtatásra alkalmas formátumban állítsa elő a tartalomjegyzéket. Azt is szerettem volna, hogy minden sor egy hivatkozás legyen, így weboldalakon és PDF-fájlokban használható a dokumentumban való navigáláshoz. A cím és az oldalszám közé pontvezetőket is szerettem volna.

És így elkezdtem kutatni.

Két kiváló blogbejegyzésre bukkantam a tartalomjegyzék HTML és CSS segítségével történő létrehozásáról. Az első volt „Tartalomjegyzék készítése a HTML-ből” írta: Julie Blanc. Julie tovább dolgozott PagedJS, a webböngészők hiányzó oldalazott médiafunkcióinak polifillje, amely megfelelően formázza a dokumentumokat a nyomtatáshoz. Julie példájával kezdtem, de rájöttem, hogy ez nem egészen működik számomra. Ezután megtaláltam Christoph Grabo-t „Reszponzív TOC vezető vonalak CSS-sel” post, amely bevezette a CSS Grid használatának koncepcióját (szemben Julie float-alapú megközelítésével), hogy megkönnyítse az igazítást. A megközelítése azonban még egyszer nem felelt meg a céljaimnak.

Miután elolvastam ezt a két bejegyzést, úgy éreztem, elég jól ismerem az elrendezési problémákat ahhoz, hogy önállóan is nekivágjak. Mindkét blogbejegyzés darabjait felhasználtam, valamint néhány új HTML- és CSS-koncepciót is hozzáadtam a megközelítéshez, hogy olyan eredményt érjek el, amellyel elégedett vagyok.

A megfelelő jelölés kiválasztása

Amikor a tartalomjegyzék helyes jelöléséről döntöttem, elsősorban a megfelelő szemantikára gondoltam. A tartalomjegyzék alapvetően arról szól, hogy egy cím (fejezet vagy alszakasz) egy oldalszámhoz van kötve, majdnem úgy, mint egy kulcs-érték pár. Ez két lehetőséghez vezetett:

  • Az egyik lehetőség egy táblázat (<table>) egy oszloppal a címhez és egy oszlophoz az oldalhoz.
  • Aztán ott van a gyakran nem használt és elfelejtett definíciós lista (<dl>) elem. Kulcs-érték térképként is működik. Tehát ismét nyilvánvaló lenne a kapcsolat a cím és az oldalszám között.

Bármelyik jó lehetőségnek tűnt, amíg rá nem jöttem, hogy valójában csak egyszintű tartalomjegyzékeknél működnek, mégpedig csak akkor, ha csak fejezetnevekkel szeretnék tartalomjegyzéket készíteni. Ha viszont a tartalomjegyzékben meg akartam jeleníteni az alfejezeteket, akkor nem volt jó lehetőségem. A táblázatelemek nem alkalmasak hierarchikus adatokhoz, és bár a definíciós listák technikailag egymásba ágyazhatók, a szemantika nem tűnt helyesnek. Szóval visszamentem a rajzasztalhoz.

Úgy döntöttem, hogy Julie megközelítésére építek, és egy listát használok; én azonban a rendezett listát választottam (<ol>) rendezetlen lista helyett (<ul>). Szerintem ebben az esetben a rendezett lista megfelelőbb. A tartalomjegyzék a fejezetek és alcímek listája abban a sorrendben, ahogyan azok a tartalomban megjelennek. A sorrend számít, és nem szabad elvesznie a jelölésben.

Sajnos a rendezett lista használata a cím és az oldalszám közötti szemantikai kapcsolat elvesztését jelenti, ezért a következő lépésem az volt, hogy minden listaelemen belül helyreállítsam ezt a kapcsolatot. Ezt a legegyszerűbben úgy oldhatjuk meg, ha az oldalszám elé egyszerűen beszúrjuk az „oldal” szót. Így minden egyéb vizuális megkülönböztetés nélkül is egyértelmű a szám viszonya a szöveghez.

Íme egy egyszerű HTML-váz, amely a jelölésem alapját képezte:

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

Stílusok alkalmazása a tartalomjegyzékben

Miután létrehoztam a használni kívánt jelölést, a következő lépés néhány stílus alkalmazása volt.

Először eltávolítottam az automatikusan generált számokat. Dönthet úgy, hogy megtartja az automatikusan generált számokat a saját projektjében, de gyakran előfordul, hogy a könyvekben számozatlan elő- és utószavak szerepelnek a fejezetek listájában, ami hibássá teszi az automatikusan generált számokat.

Célom szerint a fejezetszámokat kézzel írnám ki, majd módosítanám az elrendezést úgy, hogy a legfelső szintű listán ne legyen kitöltés (ezáltal a bekezdésekhez igazítanám), és minden beágyazott lista két szóközzel legyen behúzva. Úgy döntöttem, hogy a 2ch padding value, mert még mindig nem voltam egészen biztos benne, hogy melyik betűtípust fogom használni. A ch A hosszegység lehetővé teszi, hogy a kitöltést a karakter szélességéhez viszonyítsák – függetlenül attól, hogy milyen betűtípust használnak –, nem pedig egy abszolút pixelmérethez, amely következetlennek tűnhet.

Íme a CSS, amivel végül sikerült:

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

Sara Soueidan rámutatott arra, hogy a WebKit böngészők eltávolítják a lista szemantikáját, amikor list-style-type is none, ezért hozzá kellett tennem role="list" a HTML-be, hogy megőrizze:

<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 beágyazási tartalék

A cím és az oldalszám stílusozása

Mivel a listát ízlésem szerint alakították ki, ideje volt áttérni egy egyedi listaelem stíluszására. A tartalomjegyzékben minden egyes tételnél a címnek és az oldalszámnak egy sorban kell lennie, a címnek balra, az oldalszámnak pedig jobbra kell igazodnia.

Lehet, hogy azt gondolja: „Semmi baj, erre való a flexbox!” Nem tévedsz! A Flexbox valóban el tudja érni a megfelelő címoldal-igazítást. De van néhány bonyolult igazítási probléma, amikor a vezetőket hozzáadjuk, ezért inkább Christoph megközelítését választottam egy rács használatával, ami bónuszként segít a többsoros címeknél is. Íme egy egyedi tétel CSS-je:

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

A rács két oszlopból áll, amelyek közül az első az auto-mérete, hogy kitöltse a tartály teljes szélességét, levonva a második oszlopot, amelyre méretezett max-content. Az oldalszám a tartalomjegyzékben megszokott módon jobbra van igazítva.

Az egyetlen másik változtatás, amit ezen a ponton végrehajtottam, az az „Oldal” szövegének elrejtése volt. Ez hasznos a képernyőolvasók számára, de vizuálisan felesleges, ezért használtam a hagyományos visually-hidden osztály hogy elrejtse a szem elől:

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

És természetesen a HTML-t frissíteni kell az osztály használatához:

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

Ezzel az alappal a cím és az oldal között folytattam a vezetők megszólítását.

CodePen beágyazási tartalék

Pontvezetők létrehozása

A vezetők olyan gyakoriak a nyomtatott médiában, hogy felmerülhet benned a kérdés, vajon a CSS miért nem támogatja ezt már? A válasz: igen. Nos, ilyen.

Valójában van a leader() -ban meghatározott függvény CSS által generált tartalom a lapozott média specifikációjához. Azonban, mint a legtöbb lapozható média specifikáció esetében, ez a funkció nincs implementálva egyetlen böngészőben sem, ezért kizárt opcióként (legalábbis akkor, amikor ezt írom). Még csak nem is szerepel caniuse.com, feltehetően azért, mert senki nem valósította meg, és nincsenek tervek vagy jelzések, hogy megteszik.

Szerencsére Julie és Christoph is foglalkozott ezzel a problémával a saját bejegyzéseiben. A pontvezetők beillesztéséhez mindketten a ::after pszeudo-elem azzal content tulajdonság egy nagyon hosszú pontsorra van beállítva, például:

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

A ::after A pszeudoelem abszolút pozícióba van állítva, hogy kivonja az oldal áramlásából, és elkerülje a tördelést más sorokba. A szöveg jobbra van igazítva, mert azt szeretnénk, hogy az egyes sorok utolsó pontjai a sor végén lévő számmal egy szintben legyenek. (Ennek bonyolultságáról később.) Az .title elem relatív pozícióra van beállítva, így a ::after pszeudo-elem nem tör ki a dobozából. Eközben a overflow el van rejtve, így az összes extra pont láthatatlan. Az eredmény egy szép tartalomjegyzék pontelőkkel.

Van azonban még valami, amit figyelembe kell venni.

Sara arra is rámutatott, hogy ezek a pontok szövegnek számítanak a képernyőolvasók számára. Szóval mit hallasz? „Introduction dot dot dot dot…”, amíg az összes pontot be nem jelenti. Ez szörnyű élmény a képernyőolvasót használók számára.

A megoldás egy további elem behelyezése aria-hidden állítva true majd ezzel az elemmel illessze be a pontokat. Tehát a HTML a következő lesz:

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

És a CSS lesz:

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

Mostantól a képernyőolvasók figyelmen kívül hagyják a pontokat, és megkímélik a felhasználókat attól a frusztrációtól, hogy több pont bejelentését hallgatják.

CodePen beágyazási tartalék

Utolsó simítások

Ezen a ponton a tartalomjegyzék komponens elég jól néz ki, de némi apró részletmunkát is igénybe vehet. Kezdetben a legtöbb könyv vizuálisan eltolja a fejezetcímeket az alfejezetek címeitől, ezért a legfelső szintű elemeket félkövérre szedtem, és margót vezettem be, hogy elkülönítsem az alfejezeteket a következő fejezetektől:

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

Ezután az oldalszámok igazítását szerettem volna megtisztítani. Minden rendben volt, amikor rögzített szélességű betűtípust használtam, de a változó szélességű betűtípusok esetén a vezetőpontok cikkcakk mintát alkothatnak, ahogy igazodnak az oldalszám szélességéhez. Például minden oldalszám 1-gyel keskenyebb lesz, mint a többi, így a vezetőpontok rosszul illeszkednek az előző vagy a következő sorok pontjaihoz.

Rosszul igazított számok és pontok a tartalomjegyzékben.
Tökéletes tartalomjegyzék HTML + CSS segítségével

A probléma megoldására beállítottam font-variant-numeric nak nek tabular-nums így minden számot azonos szélességgel kezelünk. A minimális szélesség beállításával is 2ch, Biztosítottam, hogy minden egy- vagy kétjegyű szám tökéletesen igazodik. (Ezt érdemes beállítani 3ch ha a projektje több mint 100 oldalból áll.) Itt van az oldalszám végső CSS-je:

.toc-list li > a > .page { min-width: 2ch; font-variant-numeric: tabular-nums; text-align: right;
}
Igazított vezetőpontok a tartalomjegyzékben.
Tökéletes tartalomjegyzék HTML + CSS segítségével

És ezzel kész is a tartalomjegyzék!

CodePen beágyazási tartalék

Következtetés

Egy tartalomjegyzék létrehozása HTML-en és CSS-en kívül nagyobb kihívás volt, mint amire számítottam, de nagyon elégedett vagyok az eredménnyel. Ez a megközelítés nemcsak elég rugalmas a fejezetek és alfejezetek befogadásához, hanem szépen kezeli az alfejezeteket a CSS frissítése nélkül. Az általános megközelítés azokon a weboldalakon működik, amelyeken a tartalom különböző helyeire szeretne hivatkozni, valamint azokon a PDF-fájlokon, amelyeken a tartalomjegyzéket különböző oldalakra szeretné hivatkozni. És természetesen nyomtatott formában is remekül néz ki, ha valaha is hajlandó vagy brosúrában vagy könyvben használni.

Szeretnék köszönetet mondani Julie Blancnak és Christoph Grabónak a tartalomjegyzék elkészítésével kapcsolatos kiváló blogbejegyzéseikért, mivel mindkettő felbecsülhetetlen értékű volt, amikor elkezdtem. Szeretnék köszönetet mondani Sara Soueidannak a kisegítő lehetőségekre vonatkozó visszajelzéséért, miközben ezen a projekten dolgoztam.


Tökéletes tartalomjegyzék HTML + CSS segítségével eredetileg megjelent CSS-trükkök. Neked kellene kapja meg a hírlevelet.

Időbélyeg:

Még több CSS trükkök