Používejte HTML5 tagy správně

Samozřejmě můžete použít DIV nebo SPAN a připlácnout k němu nějakou třídu, přes kterou ho naformátujete. Nebo můžete změnit tag STRONG, aby byl podtržený místo tučný. Nebo můžete použít ARIA role, a dodávat význam tam, kde není potřeba. Ale nešlo by to trochu chytřeji s využitím všech těch úžasných novinek, které přináší HTML5? (Nebo dokonce HTML4?)

Formátovací tagy

Původní HTML tagy se zaměřovali na formát, takže existovali tagy jako FONT (v HTML5 již není podporován), B a I (nejsou doporučovány), EM a STRONG (ty jsou doporučovány, i když rozdíl oproti B a I často není jasně vysvětlen), a další.

Samozřejmě je můžete používat (vyjma níže uvedených) pro označení a formátování blíže neurčeného textu, ale ve většině případů je možno použít lepší tagy, které místo konkrétního formátu zachytí význam daného textu a vy nebudete muset přemýšlet o tom, jestli citát má být napsán kurzívou nebo jiným písmem, nebo zda cena zboží má být tučná nebo podtržená.

Pro shrnutí (a vysvětlení anglických výrazů pro lepší pochopení):

  • B označuje zvýrazněný text, bez dalšího upřesnění, proč je zvýrazněný.
    • Např. když chcete zdůraznit něčí jméno nebo důležité slovo.
    • Anglický výraz bold se často překládá jako tučný (tlustý) ale také znamená výrazný, statečný, sebevědomý nebo snadno viditelný – což je případ právě tučného písma.
  • I označuje kurzívu, protože chcete kurzívu.
    • Např. chcete označit jméno jiné firmy.
    • Vychází z výrazu italic (anglicky doslova italské, protože ho prvně použili v Itálii v roce 1501).
    • Český výraz kurzíva (z latinského cursivus, tedy běžný, od currere = běhat) označuje písmo, které má spojená písmena, aby se snadněji psalo rukou – označovat tak tiskařské nakloněné písmo je tedy nesprávné a měl by se spíše používat počeštěný výraz italika.
  • EM označuje zvýrazněný text, který má nějaký speciální význam.
    • Např. neznámý výraz, který později objasníte.
    • Vychází z anglického emphasize (doslova zdůraznit)
  • STRONG označuje důležitý text, na který je potřeba dát si pozor.
    • Např. upozornění nebo varování.
    • Výraz strong se může (chybně) překládat jako „silný“ (připomínaje český výraz tlustý, který označuje tučné písmo), ale tag by se měl překládat jako vážný nebo důležitý (např. strong warning = důležité varování)
  • MARK označuje text, který se nějak týká toho, co uživatel zrovna dělá nebo co je důležité v kontextu stránky.
    • Např. na stránce se slevami takto označíte zvýhodněné ceny.
    • Slouží také k označení hledaného výrazu v textu.
    • Slovo mark v angličtině doslova znamená nakreslit čáru nebo jiný symbol pro označení pozice hledané věci.
  • SMALL označuje méně důležitý text nebo poznámku.
    • Např. že cena je bez DPH.
    • Anglické small může označovat malé číslo nebo malou velikost (např. oblečení) tak i něco méně důležitého (např. small changes = nedůležité změny).
  • U označuje podtržení, tedy text, který je potřeba označit, ale nemá vyšší (EM, STRONG, …) ani nižší (SMALL) prioritu.
    • V HTML5 lze použít např. pro označení gramatické nebo matematické chyby (podržení vlnovkou)
    • Z anglického underline, doslova čára pod. Výraz lze ale ve větě použít podobně jako emphesize a nemusí tedy označovat skutečnou čáru, ale jen něco očividného.
  • SUB (dolní) a SUP (horní) označuje dolní a horní index.
    • Např. pro matematické zápisy nebo poznámky pod čarou.
  • Tagy FONT, STRIKE, BIG a CENTER jsou v HTML5 zakázány (nejsou podporovány).

Části stránky

Pro označení různých částí stránky slouží následující tagy:

  • MAIN označuje hlavní část stránky, kde uživatel najde obsah. Musí být na stránce jen jeden a nesmí být uvnitř ARTICLE, ASIDE, HEADER, FOOTER nebo NAV (ale může být uvnitř SECTION).
  • HEADER uvnitř BODY nebo MAIN označuje hlavičku stránky, tedy tu část, kde je logo, jméno stránky, příp. rychlé menu
  • FOOTER uvnitř BODY nebo MAIN označuje konec stránky, obvykle obsahující odkazy jinam, kontakt autora, apod.
  • SECTION označuje části stránky, které obsahují odlišné informace.
    • Např. část pro firmy, soukromé osoby, novináře, apod.
  • ARTICLE označuje blok obsahující hlavní text stránky nebo sekce (navíc plní stejnou funkci jako SECTION).
  • ASIDE pak označuje text, který hlavní článek doplňuje nebo rozšiřuje (navíc plní stejnou funkci jako SECTION) .
  • Specifikace HTML 5.1 umožňuje použít HEADER a FOOTER uvnitř sekcí (SECTION, ARTICLE, ASIDE, apod.). Dokonce lze vnořit do sebe např. SECTIONHEADERASIDEHEADER.
  • MENU označuje menu se seznamem odkazů. Ty by měli být značeny tagem MENUITEM. Tagy MENU a MENUITEM jsou z HTML5 vyloučeny. Pro menu je potřeba použít tag NAV.
  • Specifikace HTML 5.1 přidává zpět tagy MENU a MENUITEM, ale pouze pro definici akcí pro kontextové menu prohlížeče (viz dále). Tag MENU musí mít atribut type=context a MENUITEM musí mít atribut type s hodnotami command, checkbox nebo radio (hodnota command je výchozí a může být vynechána).
  • NAV označuje navigační menu nebo část stránky obsahující navigační odkazy (např. sitemap či odkazy v patičce).
    • Navigace musí obsahovat obyčejné odkazy A. Případně lze menu doplnit o UL-LI strukturu.
    • Navigace neslouží jako obal libovolného odkazu v textu ale jako samostatný blok odkazů nesouvisejících s obsahem stránky nebo článku (pokud je uvedena v BODY, MAIN, HEADER nebo FOOTER).
    • Pokud je NAV uveden uvnitř sekce (ARTICLE, ASIDE, apod.), týká se navigace dané sekce (např. obsah se seznam nadpisů v článku); pro přístupnost by taková navigace měla být označena pomocí aria-labeledby, aby bylo jasné, které části stránky se týká.
  • FIGURE označuje část, která obsahuje různé spolu související prvky. Titulek by měl být označen tagem FIGCAPTION.
    • Např. blok s obrázkem a jeho popisem, datem a místem pořízení, apod.
    • Ve formulářích může označovat blok s inputem, jeho labelem, chybovou hláškou, atd.
    • Figure může obsahovat více obrázků, videa, reklamy, atd. Může obsahovat i další vnořené figure.
    • FIGCAPTION může obsahovat další tagy jako je Hx, P, atd.
  • ADDRESS obsahuje kontaktní informace související s článkem nebo stránkou.
    • Nejedná se o poštovní adresu, kterou chcete uvést, ale nesouvisí s textem nebo jeho autorem.
    • Může obsahovat údaje jako jméno, telefon, email, ale i poštovní adresu (pokud dává v kontextu smysl) buď na autora článku, majitele autorských práv, nebo někoho, kdo je za text zodpovědný (např. HR nebo PR oddělení).
    • Adresa se vždy váže k textu v tagu ARTICLE, nebo k celé stránce (pokud není uvnitř ARTICLE).
  • TIME obsahuje časové informace (jak čas tak i datum) související s článkem nebo stránkou.
    • Opět nejde o označení času uvedeného v textu.

Citace

Pokud uvádíte text z jiné stránky, knihy či jiného dokumentu, můžete použít tagy Q (quote), BLOCKQUOTE a CITE.

Tag Q je určen pro inline text, kdy například do vaší věty zahrnete citát z jiného zdroje. Naopak BLOCKQUOTE, jak název napovídá, slouží jako blokový prvek, kdy uvádíte celou větu nebo odstavec z jiného dokumentu. Oba mohou mít atribut cite, který by měl obsahovat URL adresu (či jakýkoliv jiný zdroj, např. jméno knihy), odkud jste čerpali. Pokud do textu uvedete i jméno autora nebo díla, můžete k tomu použít tag CITE.

Jaký je rozdíl mezi I a EM? 

Slovy <cite>Shakespeara</cite>: 
<q>
    Voněla by snad růže jinak,
    kdyby nebyla růží zvána?
    <cite>(Romeo a Julie)</cite>
</q>.

Takže je používejte jak jen chcete.

<cite>Cimrman</cite> by na to řekl:
<blockquote 
  cite="http://citaty.net/autori/jara-cimrman/">
    Do hospody s umytýma nohama.
</blockquote>

Úpravy textu

Pro různé blogy a novinové servery, které se o své články starají a upravují je podle současné situace, se hodí tagy DEL, INS a S. Lze je ale také použít např. pro seznamy, kde chcete označit již neplatné nebo nově přidané položky (seznam úkolů, kroky návodu, apod.).

Tag S (jméno pochází ze strike-through, protože v HTML4 jednoduše označoval přeškrtnutí, ale v HTML5 má jiný význam – jméno zůstalo pro zapamatovatelnost) slouží pro označení textu, který již za současné situace neplatí, ale stále je dobré vědět, jak to dříve fungovalo. Naopak tag DEL („deleted“ = smazáno) označuje text, který byl vymazán kvůli tomu, že je chybný.

Tag INS („inserted“ = vloženo) by pak měl následovat za S nebo DEL a označovat text, který byl nově vložen a nahrazuje původní text. Samozřejmě tagy S, DEL a INS je možno použít i samostatně, pokud mažete text, který není potřeba nahradit, nebo naopak vkládáte text, který něco doplňuje, ale neruší platnost stávajícího textu.

<!-- Starý text je opraven novým, 
     ale ten nemění fakt, že dříve to tak
     fungovalo a bylo to správně, proto tag S -->
<s>Tag B označuje tučný text.</s> 
<ins>V HTML5 používejte EM pro zvýraznění, 
STRONG pro zdůraznění a MARK pro označení.</ins>

<!-- Zde naopak nový text opravuje starý, 
     který nebyl platný ani v době zápisu, 
     ale byl v textu ponechán, aby si čtenář uvědomil,
     že původní text obsahoval chybu, 
     takže tag DEL -->
Flexbox je plně podporován ve Firefoxu od verze <del>20</del><ins>28 (předchozí verze mají jen částečnou
nebo experimentální podporu)</ins>.

<!-- Zde se jedná o starou informaci, 
     protože IE8 již není podporováno, 
     ale je dobré stále vědět, že byla 
     nějaká omezení, proto tag S.
     Není ale již potřeba uvádět, 
     že od IE9 je podporován (vyplývá to z textu),
     takže není potřeba uvádět INS. -->
Tag MARK podporují všechny prohlížeče
<s>kromě IE8</s>.

Všechy 3 tagy mohou obsahovat atribut cite s URL odkazující na důvod změny (zde by to mohl být třeba http://caniuse.com pro příslušné vlastnosti).

Také mohou obsahovat atribut timestamp s časem, kdy ke změně došlo, pokud je to relevantní. Čas by měl být ve formátu yyyy-mm-ddThh:mm:ss+zz:zz (tedy datum a čas vč. časové zóny; místo T lze uvést mezeru a odděluje datum a čas). Pokud nechcete uvádět přesný čas, můžete použít atribut datetime a uvést datum a/nebo čas s libovolnou přesností.

Rozšiřující informace

Pro rozbalovací prvek, který po kliknutí zobrazí další informace slouží kombinace prvků DETAILS a SUMMARY. Tag DETAILS označuje kontejner, který obsahuje všechny informace. Tag SUMMARY pak označuje text, který bude (jako jediný) vidět a ostatní obsah v DETAILS se skryje. Po kliknutí na SUMMARY se pak zobrazí i zbytek DETAILS . Nyní jsou již oba podporované ve všech prohlížečích (v Chromium od 2014, v Safari od 2018 a Edge od 2020 po přechodu na Chromium).

Alternativně můžete použít tag DIALOG, jehož obsah bude také skryt. V okamžiku, kdy prvku nastavíte atribut open, zobrazí se jeho obsah uprostřed stránky. V Chromium je od roku 2014, a od března 2022 ho podporují všechny ostatní prohlížeče.

<details> 
    <summary>Klikni pro více informací</summary>

    Více informací (zobrazí se po kliku)... 
</details>

<dialog>
    Tohle nebude vidět.
</dialog>
<dialog open>
    Tohle bude vidět uprostřed stránky.
</dialog>

Poznámka: tagy DETAILS a SUMMARY byly přesunuty do specifikace HTML 5.1, protože pouze Chrome ji podporoval jako součást HTML5.

Kód

Původní tag TT („TeleType“ = telegrafický zápis) je v HTML5 zakázán. Místo něj lze použít tagy podle toho, co chcete zobrazit.

  • Tag CODE je určen pro zdrojový kód (např. tak, jako se to používá zde).
  • Pokud v textu odkazujete na konkrétní proměnnou nebo funkci, k označení slouží tag VAR (variable).
  • Pokud chcete uvést, co má uživatel zadat do systémové konzole nebo jakou klávesu má stisknout, můžete použít tag KBD (keyboard input = vstup z klávesnice).
  • Pro zápis toho, co se v konzoly, v programu nebo v souboru vypíše, pak slouží tag SAMP (sample = ukázka).

Samozřejmě v HTML5 je možno použít tag PRE, který se od všech ostatních liší tím, že zobrazuje mezery, tabulátory a odřádkování přesně tak, jak jsou zapsány v HTML souboru.

Kromě PRE jsou všechny tyto tagy primárně inlinové, ale lze je pomocí CSS změnit na blokové či jinak formátovat.

Formuláře

Formátováním formulářů se zabývá článek Méně známé typy inputů.

V HTML5 jsou pro seskupování prvků formuláře nejvhodnější tagy FIELDSET (rámeček s titulkem LEGEND) nebo FIGURE (skupina souvisejících prvků).

Verze HTML 5.1 přidává JS metodu form.checkValidity(), pomocí které možné vyvolat validaci formuláře programově. Metoda označí nevalidní prvky a následně vrátí TRUE nebo FALSE, podle toho, zda validace uspěla či nikoliv.

Tabulka

Tabulka má celou řadu tagů, které slouží pro její formátování:

  • TABLE označuje celou tabulku.
  • TBODY obsahuje řádky (TR) a sloupce (TD) s daty.
  • THEAD obsahuje řádky (TR) a sloupce (TH) s popisy sloupců v TBODY.
  • TFOOT obsahuje řádky (TR) a sloupce (TD) se součty nebo jinými souhrnnými informacemi.
  • TH lze také použít pro popis řádky (první buňka řádky).
  • CAPTION může obsahovat popis tabulky
    • Uvádí se uvnitř tabulky a bude zobrazen nad nebo pod tabulkou přes celou její šířku.
  • COLGROUP může definovat hromadný formát pro celý sloupec (stejně jako TR definuje formát pro řádek).
    • Měl by obsahovat tag COL pro každý TD v řádkách TR. COL nemá žádný obsah, jen definuje ID, CLASS nebo STYLE pro celý sloupec. COL může obsahovat atribut span, pokud zastupuje více sloupců.

Skryté obrázky

Specifikace HTML 5.1 umožňuje legálně používat skryté obrázky, jako jsou trackovací pixely. Takový obrázek musí mít atributy WIDTH a HEIGHT nastaveny na nulu a atribut ALT musí být prázdný:

<img src="//ad.com/track/pixel" width=0 height=0 alt="">

Kontextové menu

Tato možnost byla plánována v HTML4, ale jelikož ji v té době podporoval pouze Firefox, byla z HTML5 odebrána. Nová specifikace HTML 5.1 ji znovu přidává s tím, že výrazně omezuje možnosti použití.

Pomocí tagu MENU můžete nadefinovat položky, které se zobrazí v kontextovém menu prohlížeče, když na něj kliknete pravým tlačítkem (resp. jiným způsobem, který na daném OS vyvolá kontextovou nabídku).

Podle specifikace HTML 5.1 musí mít tag MENU atribut type=context. Jakékoliv jiné použití známé z HTML4 (např. type=toolbar) není možné. S konkrétním prvkem pak menu svážete atributem contextmenu, do kterého uvede id daného menu (tudíž MENU musí mít také atribut id, jinak nejde použít a nedává smysl).

Příklad použití – stažení obrázku v plném rozlišení po kliknutí na náhled (thumbnail):

<img src="img_th.jpg" contextmenu=pictureMenu>

<menu type=context id=pictureMenu>
    <menuitem label="Download" onclick="download(this)"></menuitem>
</menu>

Po kliknutí na obrázek z příkladu se zobrazí standardní kontextové menu prohlížeče, ale prohlížeč, který to podporuje (zatím jen Firefox), přidá do menu položku „Download„, která po kliknutí vyvolá JS funkci download().

Kontextové menu může obsahovat i podmenu, které vytvoříte vložením vnořeného tagu MENU:

<img src="img_th.jpg" contextmenu=pictureMenu>

<menu type=context id=pictureMenu>
    <menuitem label="Download" onclick="download(this)"></menuitem>
    <menu type=context label="Zoom">
        <menuitem onclick="zoomin(this)">Zoom in</menuitem>
        <menuitem onclick="zoomout(this)">Zoom out</menuitem>
    <menu>
</menu>

Tento příklad přidá kromě položky Download také submenu Zoom, které obsahuje příkazy pro přiblížení a oddálení.

Všimněte si, že popisek položek menu můžete nadefinovat v atributu label, nebo v případě MENUITEM jako obsah tagu.

Položka MENUITEM bez atributu type má výchozí typ command, který říká, že po kliknutí pouze vyvolá onlick. Položky ale mohou mít i typy checkbox nebo radio a v tom případě se pak chovají stejně jako formulářový checkbox nebo radio (radia se seskupují podle atributu name). Stav můžete nastavit nebo přečíst z atributu checked.

Šablony (Templates)

HTML5 nabízí možnost uložit do HTML kódu části, které nebudou při renderování použity a vloženy do DOMu. Místo toho se uloží odděleně a lze je použít později z Javascriptu pro změnu obsahu nebo po načtění nového obsahu.

Tag template musí mít atribut id pomocí něhož ho můžete najít (resp. nemusí, ale hledat ho jiným způsobem je pomalejší). Tag template je v moderních prohlížečích skrytý a ani se nerenderuje (tzn. pokud obsahuje HTML tagy, v DOM inspektoru ho uvidíte jako text podobně jako komentář).

<body>
    <h1>Titulek stránky</h1>
    <template id=myArticle>
        <article>
            <h2>Nadpis článku</h2>
            <p>Text článku</p>
        </article>
    </template>
    <p>Toto je první odstravec stránky</p>
...

Pokud nemáte jistotu, že stránka nebude zobrazena ve starších prohlížečích, doporučuji do CSS přidat podmínku, která tagy template skryje:

template { display: none; }

Template můžete načíst z JS a vložit do stránky podle potřeby:

var template = document
        .getElementById('myArticle');
var article = template.content || template;
var clone = article.cloneNode(true);
clone.getElementsByTagName('h2')[0]
             .innerHTML = response.json.title;
clone.getElementsByTagName('p')[0]
             .innerHTML = response.json.body;
body.appendChild(clone);

V kódu si všimněte, že nejprve najdeme template podle jeho ID a následně ho necháme převést na HTML pomocí template.content. Pro starší prohlížeče, které template neznají a obsah již vyrenderovali pak stačí použít přímo daný kontejner.

Vlastnost content vyrenderuje prvky v šabloně, ale mimo aktivní DOM. Pro použití prvků a následné vložení do DOM musíme na vytvořený prvek použít article.cloneNode(true) nebo document.importNode(article, true) – oba postupy vytvoří kopii kontejneru a všech jeho vnořených prvků v aktivním DOM.

Následně již můžeme obsah prvků upravit podle potřeby a vložit do DOM (v kódu na konec body).

Stínový DOM a sloty

Data do template nemusíte vkládat jen přes JS (typicky načtené v JSON přes AJAX), ale můžete je nadefnovat v HTML (v jakémsi XML zápisu). Tato možnost je ale podporována jen ve Firefox 63+, Chrome 53+, Edge 79+, Safari 10.3+ a Opera 40+ (dříve byste pro IE a starší Edge museli použít polyfill, ale dnes (2022) už asi není potřeba s nimi počítat).

Pointa stínového DOMu je obdobná jako XML transformace. Tedy máte nějaká surová data, která převedete na jinou strukturu (pomocí šablony). Stínový DOM je sice nadefinován v HTML, ale vyžaduje JS pro jeho aktivaci.

Příklad šablony a stínového DOMu:

    <template id=myArticle>
        <h2>
            <slot name=title>Nadpis článku</slot>
            <a href="#menu">Nahoru</a>
        </h2>
        <p>
            <slot name=text>Text článku</slot>
        </p>
    </template>
    <article>
        <span slot=title>HTML5 prvky</span>
        <span slot=text>HTML5 přináší ...</span>
    </article>
    <article>
        <span slot=title>ECMA 2015</span>
        <span slot=text>Nová verze JS ...</span>
    </article>
    ...

Když máte takovouhle HTML strukturu (vygenerovanou jednoduše na serveru, kde template načtete z *.html souboru a seznam článků vygenerujete jednoduchým FOR-EACH), můžete pomocí javaskriptu aplikovat na jednotlivé články uvedenou šablonu:

if (!'attachShadow' in document
               .createElement('article')
) {
    alert('Tento prohlížeč neumí'
         +' stránku správně zobrazit!!!');
    return;
}
//díky podpoře ShadowDOM lze využít ES6
let template = document
      .getElementById('myArticle');
let articles = document
      .getElementsByTagName('article');

for (const article of articles) {
    article
        .attachShadow({mode:'open'})
            .appendChild(template
               .content.cloneNode(true)
            )
    ;
}

Kód získá template a seznam článků. Následně každý článek označí jako stínový DOM, který obsahuje pouze data a následně k němu připojí šablonu definující strukturu.

Metoda .attachShadow() vytvoří stínový DOM nad prvkem. Je důležité poslat parametr {mode: 'open'}, aby byl stínový DOM dostupný z javaskriptu. Metoda nevrací přímo prvek, ale jeho stínovou kopii (shadowRoot), takže následná práce s ním je trochu jiná, než na co jste zvyklí (např. to, že šablona se aplikuje přes .appendChild()).

Prohlížeč pak automaticky nahradí všechny prvky slot v šabloně za prvky z článku s vlastností slot s odpovídajím jménem name.

Prohlížeč, který stínový DOM nepodporuje, zobrazí chybu a surová data. Pro vylepšení můžete dopsat do CSS podmínku, která article zobrazí až po té, co se aplikuje šablona (tím, že mu přiřadíte nějakou třídu).

Poznámka: sloty můžete použít i bez stínového DOMu tak, že v JS načtete všechny prvky, které mají atribut slot (document.querySelector('[slot]')) a následně přečtením hodnoty atributu slot a innerHTML získáte seznam klíčů a hodnot, které pak můžete podle potřeby použít (vložit do šablony, apod.), ale proč to dělat složitě, když máte jednodušší způsob?

Hodnota slotu nemusí obsahovat jen text a může obsahovat další DOM prvky, které se do slotu vloží. Často je tak hodnější formátování typu H2, P, FIGURE, A (odkaz) mít v datech a do slotů je jen vkládat:

<template>
    <article>
    <figure>
        <slot name=image></slot>
        <figcaption>
            <slot name=title></slot>
        </figcaption>
    </figure>
    <slot name=text></slot>
    <slot name=more></slot>
</template>

<div id=article1>
    <h2 slot=title>Nadpis článku</h2>
    <img slot=image src="image-12345.webp>
    <a slot=more href="#more">Číst dále</a>
    <div slot=text>
        <p>Text článku</p>
        <p>Text článku</p>
        <p>Text článku</p>
    <div>
</div>

Stylování slotů

Pozor na to, že stínový DOM je samostatný dokument, který nemá přístup ke stylům načteným v hlavním dokumentu. Pomocí stylů z hlavního dokumentu tak můžete formátovat pouze SLOT prvky, jejichž styl se pak přenese i do stínového DOMu.

Pokud potřebujete formátovat prvky ve stínovém DOMu, musíte potřebné styly vložit přímo do TEMPLATE (buď pomocí STYLE nebo přes LINK rel=STYLESHEET).

<template id=myArticle>
    <!-- styl pro nadpis, který nelze
      naformátovat přes již načtené CSS -->
    <style>
        h2 { color: blue }
    <style>
    <!-- styl pro odkaz, který musí být znovu
      načten do stínového DOMu -->
    <link rel=stylesheet href="/css/navigation.css">
    <h2>
        <slot name=title>Nadpis článku</slot>
        <a href="#menu">Nahoru</a>
    </h2>
    <p>
        <slot name=text>Text článku</slot>
    </p>
</template>

Pokud potřebujete uvnitř stínového DOMu zjistit, jestli nějaký prvek má nebo nemá hodnotu, můžete použít pseudo-třídu (funkci) ::slotted(). Ta funguje podobně jako ::empty s tím rozdílem, že empty nepozná, jestli je ve slotu něco vloženo o jen ověřuje, jestli má nebo nemá výchozí hodnotu (nezávisle na tom, jestli je tato hodnota vidět nebo ne).

Pokud tedy chcete formátovat výchozí hodnotu slotu, musíte ji obalit nějakým prvek (SPAN) a ten pak formátovat. V okamžiku, kdy se do slotu vloží jiný prvek se ten výchozí automaticky skryje:

<template>
    <style>
        article slot * {
            display: none; //skryj výchozí obsah
        }
        article ::slotted(*) {
            display: block; //zobraz jen skutečný obsah
        }
    </style>
    <article>
        <slot name=title><h2>Výchozí titulek<h2></slot>
        <slot name=text><p>Výchozí text<p></slot>
    </article>
</template>

<div id=article1>
    <p slot=text>Text článku bez titulku</p>
</div>
<div id=article2>
    <h2 slot=title>Titulek bez článku</h2>
</div>

Všimněte si, že styly se slotted musíme definovat přímo v šabloně, protože styly z hlavního dokumentu (nalinkované CSS and styly z debuggeru) stínový DOM ignoruje (nemá k nim přístup).

Funkci slotted můžete také použít k tomu, že určutý slot naformátujete podle toho, jaký prvek je do něj vložen. Plný zápis selektoru pro slot s vloženým prvek by byl:

slot[name=<jméno>]::slotted(<vložený prvek>) {
    //styl prvku uvnitř slotu
}

Pokud nepotřebujete styl určovat pro konkrétní slot podle jeho jména, můžete ho vynechat a použít jen funkci ::slotted() – browser sám pozná, že tuto funkci lze aplikovat pouze na slot a sám ji tedy bude použít jen na slot prvky.

Pro příklad, pokud chcete formátovat všechny obrázky vložené do slotu template, provedete to takhle:

::slotted(img) {
    display: block;
    //další styly
}

Dležité je uvědomit si, že funkce slotted v selektoru zastupuje dva prvky: samotný slot, který určuje selektor před funkcí (např. slot[name=username]::slotted()) a pak prvek vložený do slotu, který je určen selektorem v závorce (např. ::slotted(span.large[slot=username])). Styl určený selektorem se pak aplikuje na prvek vložený do slotu!

article slot[name=title]::slotted(h2.news) {
    //styl pro titulek článku, 
    //pokud je jím nadpis se třídou "news"
}
article slot[name=title]::slotted(figure.photo) {
    //styl pro titulek článku, 
    //pokud je v něm fotka s popiskem
}

Levou část selektoru se slotted můžete vynechat, pokud poznáte slot podle vloženého prvku (např. ::slotted(h2) bude pravděpodobně nadpis článku, tedy slot title). Pravou část (vložený prvek) můžete nahradit za hvězdičku a formátovat tak jakýkoliv prvek (např. slot[name=username]::slotted(*) pro shodné formátování jména nezávisle na vloženénm prvku).

Styl slotu před kompilací

Pokud používáte LESS nebo SASS a využíváte kaskádovaných tříd, je potřeba si dát pozor na to, jak zapíšete prvek uvnitř slotu.

.article {
    &-header {
        &-title {
            &, ::slotted(&) { ... }
        }
    }
}

Tento styl popisuje třídu article-header-title a aplikuje na ní styl, ať už je uvedená samostatně nebo ve slotu.

.article {
    &-header {
        > h2 { //NEPOUŽÍVAT!!!
            &, ::slotted(&) { ... }
        }
    }
}

Tento styl popisuje prvek H2 uvnitř kontejneru article-header. Styl pro slot by ale fungoval jen v případě, že uvnitř slotu by byla celá hlavička s nadpisem; pokud ale máte slot uvnitř hlavičky a vkládáte jen nadpis, musel by styl být:

.article {
    &-header {
        > h2, > ::slotted(h2) { ... }
    }
}

Vlastní tagy pomocí CustomElements

Když už používáte Šablony a Stínový DOM, tak můžete rovnou začít používat i vlastní prvky, protože jejich podpora je v podstatě stejná jako pro Stínový DOM.

Pointa CustomElements je taková, že pokud chcete do Šablony zobrazit nějaké data vygenerovaná na serveru, není potřeba generovat je do známých (výše uvedených) prvků z HTML5, ale můžete použít libovolnou XML strukturu (např. ze SOAP API) a prohlížeči pak jen říct, jak má XML strukturu zobrazit – tedy na které prvky aplikovat šablony.

Začít musíte tím, že zjistíte, jestli prohlížeč podporuje CustomElements a následně zaregistrovat ty typy, které chcete použít:

//Kontrola, že lze registrovat vlastní prvky:
if ('customElements' in window) {
    //Registrace vlastního prvku
    customElements.define(
        //jméno dat v XML
        'data-item',
        //Registrace jako HTML prvku
        class extends HTMLElement {
            //definice, co se má udělat,
            //když prohlížeč najde tento prvek
            //v HTML a potřebuje ho vyrenderovat
            constructor() {
                //aplikace stylu standardního HTML
                super();

               //Přidání vlastní šablony
               this.attachShadow({mode: 'open'})
                   .appendChild(document.
                   .getElementById('item-tmplt')
                   .content.cloneNode(true)
               );
            } //konec konstruktoru
        } //konec třídy
    ); //konec define()
} //konec IF

Tento přístup vám umožní automaticky aplikovat Šablonu na libovolný prvek, ale má jeden problém – že byste museli mít v daném XML již připravého atributy SLOT pro vložení konkrétních dat do slotů šablony. Pokud data načítáte z vlastního API nebo je generujete na serveru, tak to nejspíš není problém.

Pokud ale skutečně načítáte data z externího API, kde nemůžete řídit strukturu dat, budete muset ještě doplnit informaci o tom, jak data do šablony vložit.

//Kontrola, že lze registrovat vlastní prvky:
if ('customElements' in window) {
    //Registrace vlastního prvku
    customElements.define(
        //jméno dat v XML (jméno položky)
        'data-item-name',
        //Registrace jako HTML prvku
        class extends HTMLElement {
            constructor() {
                //aplikace stylu standardního HTML
                super();

               //Určení slotu, do kterého
               //se má hodnota vložit
               this.setAttribute(
                   'slot',
                   'name'
               );
            } //konec konstruktoru
        } //konec třídy
    ); //konec define()
} //konec IF

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Tato stránka používá Akismet k omezení spamu. Podívejte se, jak vaše data z komentářů zpracováváme..