Vše o prvku BUTTON a tlačítkách v HTML

Prvek button reprezentuje tlačítko. Tím bychom mohli skončit a jít na pivo, že jo? To byste ale byli na špatném místě. My půjdeme do hloubky.
Text vyšel původně na autorově blogu.
Jak hluboko půjdeme?
- Doporučím vám dávat prvku
<button>
přednost před tlačítky v<input>
. - Upozorním, že prvek
<a>
stylovaný jako tlačítko vždy nemusí být dobrý nápad. - Nakonec společně zjistíme, že
<button>
je vlastně univerzální interaktivní prvek.
Začneme ale u samotné HTML značky.
Prvek BUTTON
Specifikace uvádí, že <button>
reprezentuje tlačítko, jenže definice tlačítka je širší, než bychom mohli čekat.
Nespornou výhodou prvku <button>
je jeho párovost. Můžeme do něj vložit libovolný text, který zároveň slouží jako jeho popis (label). Můžeme do něj vložit libovolnou HTML strukturu.
Atributem type=""
můžete tlačítku vnutit různé vzorce chování:
<button type="submit">
nebo<button>
– odesílá formulář<button type="reset">
– resetuje hodnoty ve formuláři<button type="button">
– nedělá nic
Poslední typ neodešle formulář, takže mu můžete přidávat nejrůznější funkce. Rozdíl mezi odesílacím a neodesílacím tlačítkem je patrný také v mé další ukázce. cdnp.io/e/VrZJwX
To, že type="button"
nic nedělá, neznamená, že nic neumí. Má vlastnosti, které jiným HTML prvkům chybí. Za chvilku se k nim dostaneme. Nejprve ještě k sesterské značce <input>
.
Proč prvek BUTTON a ne INPUT?
Známe přeci <input type="button">
nebo jiné s hodnotami image
, submit
a reset
v atributu type=""
. Proč tedy <button>
?
Protože je univerzální a snadněji se styluje.
Do prvku BUTTON můžete vložit další element
Prvek pojme skoro jakoukoliv HTML strukturu:
<button>
<img src="icon.svg" alt="">
Tlačítko <em>s důrazem</em>
</button>
Přesněji řečeno: Pojme jakékoliv značky, které popisují text v odstavci (tzv. Phrasing Content). Takže <svg>
, <img>
nebo dokonce <iframe>
je povolený. <p>
, <div>
nebo <h1>
naopak zakázaný.
<input>
přijímá pouze textové hodnoty nebo obrázek, který je ovšem dneska kvůli přístupnosti už dost krajní možností.
Můžete používat pseudotřídy :before a :after
Tohle bychom s <input>
jako nepárovou značkou opět nemohli:
button:before {
background: url(icon.svg)
}
Nicméně pozor na velké aktivní plochy. Jak uvádí Bohumil Jahoda, větší plochy pseudotříd nejsou aktivní ve Firefoxu. kod.djpw.cz/mckc
Problémy se starými Explorery, spíše pro zajímavost
S <button>
se pojily nějaké problémy v Internet Explorerech verzí 6-9. Zejména pak v situacích, když jste textovou hodnotu uvedenou v <button>
chtěli poslat na server. Mě osobně to nevadí, protože to je velmi vzácný scénář a protože už i staré Explorery jsou dnes druh velmi vzácný, až vyhynulý. Problémy se starými Explorery přesně popisuje Bohumil Jahoda, ale nenechte se jimi odradit.
Nepleťte si tlačítko s odkazem
Odkaz (link) specifikace definuje jako interaktivní odkaz na interní nebo externí zdroj. Prostě kotva uvnitř dokumentu nebo odkaz na jinou adresu. Plně mu odpovídá prvek <a>
.
Odkaz má kromě toho speciální chování v prohlížečích. Jejich obsah lze pomocí drag’n’drop přemístit jinam. Některé prohlížeče po najetí myši ukazují cílovou adresu. Poslední specialita je možnost otevřít cílovou adresu v novém okně pomocí klávesové zkratky nebo z kontextové nabídky. Někteří také tvrdí, že je jim vyhrazený kurzor v podobě ruky (cursor:pointer
), ale s tím já se neztotožňuji. „Pracičkový“ kurzor se dnes na webech široce používá pro zvýraznění aktivních elementů a je to zažitá věc.
Tlačítko (button) je naproti tomu prvek, který po aktivování vyvolává akci uvnitř aktuální stránky. Plně mu odpovídá element <button>
.
Pokud tedy prvek vyvolává akci, ale nemění lokaci, je správnější použít značku <button>
.
Neznamená to však, že byste měli pro všechny komponenty rozhraní s vizuálem tlačítka používat zásadně jen <button>
. Občas je kvůli jednotnosti rozhraní potřeba odkaz nastylovat vizuálem tlačítka.
Znamená to především, že byste neměli používat prvek <a>
tam, kde je významově vhodnější tlačítko. Prostě pro akce, které nemění URL prohlížeče. Neměli byste dělat ošklivárny tohoto typu:
<input type="text">
<a href="#" class="button">
Tlačítko pro ovládání inputu
</a>
Nebo takhle: Když už to udělat potřebujete, měli byste přidat všechny očekávané funkce tlačítka.
Odkaz s vizuálem tlačítka: na co všechno myslet?
Pojďme si to ukázat na příkladu. Předpokládeme, že se jedná z významového pohledu o tlačítko, tedy nepřecházíme na novou URL. Pojďme to zkusit udělat špatně, odkazem:
<a href="#" class="button">
Problémové tlačítko
</a>
Prvek bude mít díky třídě vizuál tlačítka. Čtečky dávají prvku <a>
jiný význam než prvku <button>
. Proto bychom museli přidat WAI-ARIA roli pro tlačítko:
<a href="#" class="button" role="button">
Problémové tlačítko
</a>
Ale je tu i další problém: Odkaz není na rozdíl od tlačítka možné v prohlížečích aktivovat mezerníkem. Tlačítko má být aktivovatelné mezerníkem i enterem, odkaz jen enterem. Více o tom píší třeba na MDN.
Jak to vyřešit? Mohlo by vás napadnout třeba zanoření nativních prvků:
<a href="#">
<button>
Problémové tlačítko
</button>
</a>
Jenže to dobře fungovat nebude. Při ovládání z klávesnice musí uživatel zápasit se dvěmi zaměřeními, s dvojitým focusem. Nebude pro něj snadné vybrat ten správný.
Zkusme tedy další pokus s odkazem. Hlídání stisknutí mezerníku musíme ošetřit Javascriptem:
<a href="#" role="button" class="btn btn-secondary"
onkeypress="if(event.keyCode==13){alert('Ahoj!')};
onclick="alert('Ahoj!')">
Problémové tlačítko
</a>
Můžete si to zkusit na Codepenu: cdpn.io/e/eExXmy.
A teď úplná prasárna: prvek SPAN jako tlačítko
Existence ARIA role="button"
by mohla napovídat, že bychom snad měli možnost udělat tlačítko z čehokoliv, třeba z prvku <span>
:
<span role="button">
Tlačítko prasátko
</span>
Je to samozřejmě blbost. Pojďme si na tabulce ukázat, jaké všechny funkce jsou skryté v prvku <button>
a které prvky <span>
ani <a>
nemají.
Prvek | Vzhled | Klik/touch | Focus | Význam | Mezerník |
---|---|---|---|---|---|
<span> |
+ | + | |||
<a> |
+ | + | + | ||
<button> |
+ | + | + | + | + |
Do vytvoření tlačítka pomocí jiných prvků než <button>
se proto ideálně nepouštějte.
Paul J. Adam píše i o dalších věcech, které se mi sem nevešly. Cituji:
There’s a lot to consider when making a custom button control fully accessible with an experience equal to a native button. You need tabindex=0, role=button, onkeydown, .keyCode == 13, .keyCode == 32, event.preventDefault(), and extra CSS to make it look like a real button.
Ano, sémanticky správné tlačítko totiž vypadá úplně jednoduše:
<button>
Správné tlačítko
</button>
Jak navíc ve své skvělé knize píše Heydon Pickering, jen tlačítko udělané z prvku <button>
je – a teď cituji – „resizable, translatable, focusable, interoperable, stylable, restylable, maintainable, mutable, simple“.
A jak za chvilku uvidíte, používat pro prvek <button>
označení „tlačítko“ trochu zavání podceňováním.
Značka BUTTON jako univerzální iteraktivní prvek
Button je zaměřitelný a aktivovatelný dotykem, myší i z klávesnice. To je věc, kterou potřebujeme fakt často. Co třeba akordeony a další rozklikávací rozhraní?
Aktivační prvek akordeonu je totiž významem typické tlačítko:
<h3>
<button
aria-expanded="false" aria-controls="collapsible-0">
Rozklikávač
</button>
</h3>
<div id="collapsible-0" aria-hidden="true">
<p>Rozklikávaný obsah…</p>
</div>
Příklad s akordeonem jsem si vypůjčil z ukázek Heydona Pickeringa.
Další možnosti jsou vidět na webu Inclusive Components. Jednou z nich je stylování vlastních přepínačů – dvoupolohových tlačítek:
<span id="notify-email">
Notify by email
</span>
<button role="switch"
aria-checked="true" aria-labelledby="notify-email">
<span>on</span>
<span>off</span>
</button>
Vidíte, že pomocí atributu role=""
měníme význam tlačítka na „přepínač“. Věnujte prosím pozornost i dalším atributům začínajícím slovem aria-
.
Takovéto prvky v rozhraní jako běžná tlačítka nevypadají, přesto u nich může být prvek <button>
díky svým vlastnostem velmi užitečný.
Vzpomeňte si na něj až budete nějakou takovou komponentu stylovat. <a>
pro tlačítka používejte jen tam, kde se to významově hodí. Jiné elementy nejlépe vůbec pro tlačítka nevyužívejte.
Vzhůru do (responzivního) designu
Průvodce návrhem a implementací responzivních uživatelských rozhraní. Vyšlo v květnu 2017. Koupit e-book.
Velmi pekny clanok, kto raz zacne riesit web accessibility, tak vsetky tieto rady vyuzije. Mam vsak otazku na autora, nakolko vyzera ze sa v tejto teme fakt vyzna. Ide o pomerne bezny use-case: na stranke sa zobrazuju nejake dlazdice (napr. grid 9 dlazdic) pricom kazda z nich je vlastne odkazom na bud inu podstranku, alebo vyskoci modalne okno a pod.. Vzhladom na design, kazda dlazdica ma ramcek, obsahuje nadpis, nejaky popis a na spodku button, ktory vyvolava danu akciu. Lenze aby to bolo user-friendly, reagovat ma cela dlazdica, nielen ten button v nej (ten je fakt akoby len do poctu kvoli dizajnu). Ako to spravne urobit? Urobit z celej dlazdice button (a vyuzit ze ide o tag parovy a teda vieme do neho vnorit svoj bordel), alebo to v takomto pripade moze byt div ktoremu akurat namapujeme cez JS danu akciu s tym, ze to bude dostupne len mysou a citacky o tom ani vediet nebudu, pre klavesnicu vlastne zostane ten button vnutri stale plne accessible?
Pokud jde o seznam typu výpis produktů v e-shopu, volil bych nějakou takovou strukturu:
<button>
je totiž typu tlačítko, takže pro ovládání lokálních interakcí. Hodí se tam<a>
. To může obalovat celý blok, pokud v něm není další<a>
.<article>
tam mám proto, že ve čtečkách označuje začátek a konec strukturované položky v seznamu.https://www.vzhurudolu.cz/prirucka/html5-struktura#code-lt-article-role-article-gt-code
Dakujem, zvacsa to robim podobne (aj ked priznavam, miesto
a
tam este obcas hodim lendiv
). V takomto pripade teda ak bude vo vnutri tohoarticle
dalsibutton
bude to v poriadku? Citacka tak vlastne 2x zahlasi moznost prechodu na detail clanku/produktu (raz prea
a raz prebutton
).Proč by uvnitř byl
button
? Kvůli nějaké lokální interakci?Pokud je to odkaz na detail produktu nebo podobná věc, měl by to být link. Odkážu vás na původní článek, na zdrojáku neumím kotvy doprostřed textu: https://www.vzhurudolu.cz/prirucka/button#neplette-si-tlacitko-s-odkazem
pretoze niekedy tam nieje link ale len akcia typu popup a pod.
Rozumím, pak to dává smysl.
Hlavní výhoda buttonu oproti inputu je je podle mě jednoduše to, že value (zasílaná na server) je oddělená od zobrazovaného textu. Třeba taková vícejazyčná aplikace, s několika tlačítky v jednom formuláři se pomocí inputů programuje fakt docela blbě.
Ale jinak dobrý článek.
Bezva. Díky za doplnění!