Takový pěkný CSS hack na páteční odpoledne, aneb Jak vyřešit plurály, když máte v ruce jen CSS a HTML?
Představte si redakční systém, kde máte přístup jen k HTML šablonám a k CSS. Obsah do nich vkládáte pomocí nějakých speciálních značek. A teď chcete vypsat počet komentářů.
S počtem komentářů je ten problém, že v češtině máme dvě množná čísla. Podívejte se sami:
- 1 komentář
- 2 komentáře
- 3 komentáře
- 4 komentáře
- 5 komentářů
- 6 komentářů
…atakdál. Podle starých pravidel se řídil tvar podle poslední číslice i v případech jako je 21, 22, 23… (21 komentář, 22 komentáře), ale nová pravidla kodifikují jako přijatelný i tvar „21 komentářů“. (Důvod je prostý – představte si větu „4721 divák nadšeně aplaudoval“ – viz Šílený korektor).
Takže tedy řešíme stavy 0, 1, 2-4 a 5+ a patřičný tvar.
A teď si představte, že redakční systém umí odlišit situaci, kdy nejsou žádné komentáře (a tu ošetří), no a pro všechno ostatní tu je jedna HTML šablona a v ní je:
<p>Diskuse obsahuje $CommentNum$ příspěvků</p>
Ne, žádné podmínky šablona nenabízí. Takže výsledkem jsou hlášky „Diskuse obsahuje 3 příspěvků“, nemluvě o „Diskuse obsahuje 1 příspěvků“.
Jak to pořešit? Jedna z možností je využít JavaScript, no a druhá možnost, kterou mi dneska ukázal kolega Honza Drda, využívá CSS. Já takové řešení nenašel, tak ho zveřejňuju s nadějí, že se může někomu hodit (a s Honzovým souhlasem, samozřejmě).
HTML kód je:
<p>Diskuse obsahuje $CommentNum$ <span class="none ek$CommentNum$">příspěvek</span><span class="none ky$CommentNum$">příspěvky</span><span class="ku$CommentNum$">příspěvků</span></p>
a k tomu patří jednoduchá CSS pravidla:
.none,.ku1,.ku2,.ku3,.ku4 { display: none; } .ek1,.ky2,.ky3,.ky4 { display: inline;}
A to je celé… Vyzkoušel jsem v Chrome, funguje, ale je možné, že někde to nepoběží.
Samozřejmě ideální řešení je využít nástroj na straně serveru, který tohle umí ošetřit (gettext např.) Ale někdy holt není…
Update: Krásné řešení navrhl v komentářích David Matějka (s použitím datových atributů a CSS3)
HTML:
<div>Diskuze obsahuje <span data-count="$CommentNum$" data-plural-1="komentář" data-plural-2="komentáře" data-plural-3="komentářů"></span></div>
CSS:
span[data-count]:before{ content: attr(data-count) ' '; } span:after { content: attr(data-plural-3); } span[data-count='1']:after { content: attr(data-plural-1); } span[data-count='2']:after, span[data-count='3']:after, span[data-count='4']:after { content: attr(data-plural-2); }
Update 2: vylepšení předchozího tak, že i v případě vypnutých CSS zůstane sémanticky správné sdělení, napsal Martin Keder
HTML:
<div>Diskuze obsahuje $CommentNum$ <span data-count="$CommentNum$" data-plural-1="komentář" data-plural-2="komentáře"><span>komentářů</span></span></div>
CSS:
span[data-count='1']:after { content: attr(data-plural-1); } span[data-count='2']:after, span[data-count='3']:after, span[data-count='4']:after { content: attr(data-plural-2); }
span[data-count='1'] span, span[data-count='2'] span, span[data-count='3'] span, span[data-count='4'] span { display: none; }