Skip to content

Ierarhia titlurilor h1/h2/h3

Vitalie requested to merge 17_heading-hierarchy into main

Closes #17 (closed)

Patru probleme, toate invizibile pe ecran și toate în ce citește Google.

Ce s-a schimbat

Fișele de produs aveau două h1 identice. Cele două blocuri de titlu stau în locuri structural diferite — deasupra galeriei pe telefon, în capul coloanei de informații pe calculator — deci ambele sunt în DOM și CSS-ul ascunde unul. Blocul de telefon păstrează elementul h1 (indexarea se face mobile-first, iar acolo el e titlul vizibil), iar cel de calculator poartă nivelul doar în arborele de accesibilitate. Fiecare e display: none la lățimea celuilalt, deci se expune exact un titlu de nivel 1.

h1-ul primei pagini era sloganul bannerului, deci subiectul paginii se schimba odată cu carusela, depindea de ce scria cineva în panou și era un spațiu neîntrerupt cât timp cererea către /api/banners era în curs. Acum prima pagină are un h1 fix și invizibil, cu exact textul folosit deja ca titlu de pagină și ca h1 în varianta servită de server. Sloganul rămâne ce este: text de reclamă.

Paginile de colecție săreau de la nivel 1 la nivel 3. Banda de categorii și grila de produse primesc fiecare câte un titlu invizibil. Titlul grilei stă în afara ramurii condiționale, deci îl are și starea „niciun produs".

Subsolul era scris de două ori, o dată pentru telefon și o dată pentru calculator, deci fiecare pagină din magazin conținea de două ori toate linkurile, titlul de newsletter și sigla. Acum e un singur arbore: ordinea din DOM e cea stivuită, pentru telefon și pentru un crawler mobile-first, iar aranjamentul de calculator vine din poziționare explicită pe grilă. Coloanele sunt o singură componentă, cu titlul h3 o singură dată.

Verificare

Măsurat în browser, build de producție și baza reală, versiunea veche față de cea nouă, la 390px și la 1440px:

Înainte După
h1 pe fișa de produs 2 1
h1 pe prima pagină sloganul bannerului titlu fix al magazinului
Salt de nivel pe /collections/shop-all 1 → 3 1 → 2 → 3
Titlu de newsletter în subsol 2 1
Linkuri în subsol 36, din care 13 duplicate 23, zero duplicate
Înălțimea subsolului 714 / 997 px 714 / 997 px

Diferența de geometrie a subsolului: zero. Fiecare element și fiecare nod de text stă la aceleași coordonate, cu aceeași mărime, grosime și culoare de literă. Acordeonul de pe telefon se deschide la aceeași înălțime (1423px), iar pe calculator starea lui nu are niciun efect. Heroul primei pagini e identic la ambele lățimi, inclusiv poziția în pagină — titlul invizibil nu ocupă spațiu.

npx tsc --noEmit -p tsconfig.app.json curat; oxlint doar cu avertismentul preexistent din src/App.tsx; npm run test 408 de teste în 32 de fișiere, toate trecute (12 teste noi, unul pe fiecare defect); npm run build curat.

Două compromisuri, asumate

  • Ordinea de tabulare pe calculator se schimbă. Aceleași 23 de linkuri, dar cele cinci sociale vin acum înaintea celor patru linkuri mari, pentru că ordinea din DOM e cea de telefon. Într-un arbore unic doar o lățime își poate păstra ordinea; nepotrivirea a fost pusă pe calculator, unde cele două zone stau una lângă alta, nu pe telefon, unde tabularea ar fi sărit în josul paginii și înapoi. La 390px ordinea e neschimbată.
  • Trei opriri de tabulare în plus pe calculator. Titlurile de coloană sunt butoane la orice lățime, deci peste 1024px pot primi focus, deși nu fac nimic. Varianta cu detectarea pragului în JavaScript a fost scrisă și apoi scoasă: un ascultător de media query care ratează un eveniment lasă butoanele accesibile doar cu mouse-ul pe telefon, adică un defect mai grav decât cel pe care îl repară. Diferența rămâne în CSS, care nu poate rămâne în urmă.

Merge request reports