Błędy

Atrybuty z białymi znakami

Opis

Niektóre atrybuty HTML nie powinny zawierać żadnych białych znaków - mianowicie [id], [lang] oraz map[name].

Bibliografia

Selektor

[id*=" "],
[lang*=" "],
map[name*=" "]

Test

To jest mój piękny element z ID.

<p id="my id">To jest mój piękny element z ID.</p>

[tabindex] > 0

Opis

Atrybut [tabindex] nigdy nie powinien być większy niż 0.

Bibliografia

Selektor

[tabindex]:not([tabindex="0"]):not([tabindex^="-"])

Test

<button tabindex="1" type="button">Dodatni tabindex jest zły!</button>

Pusty [href]

Opis

Atrybut [href], jeśli występuje, nie powinien być pusty. Łączy do czegoś, prawda?

Bibliografia

Selektor

a[href=""],
a[href=" "]

Test

Czym jestem? Do czego prowadzę?
<a href=" ">Czym jestem? Do czego prowadzę?</a>

Opis

Puste łącze powinno mieć etykietę wewnątrz [title], [aria-label] lub wskazaną przez [aria-labelledby]. Przy okazji, po co miałbyś używać pustego łącza?

Bibliografia

Selektor

a:empty[title=""],
a:empty[aria-label=""],
a:empty[aria-labelledby=""],
a:empty:not([title]):not([aria-label]):not([aria-labelledby])

Test

<a href="/" class="inbl w-20" id="empty-link_code"></a>

Brak alt w img

Opis

<img> musi mieć [alt]. Zawsze.

Bibliografia

Selektor

img[alt=" "],
area[alt=" "],
input[type="image"][alt=" "],
img:not([alt]),
area:not([alt]),
input[type="image"]:not([alt])

Test

<img src="./static/ffoodd.png" width="144" height="144" /><span></span>

Brak etykiety dla [role=img]

Opis

Element z [role=img] powinien mieć albo [aria-label] albo [aria-labelledby]. Jeśli obraz jest dekoracyjny, użyj [role=presentation] zamiast [role=img].

Bibliografia

Selektor

[role="img"]:not([aria-label]):not([aria-labelledby]),
svg[role="img"]:not([aria-label]):not([aria-labelledby])

Test

<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" role="img">
  <rect x="400" y="100" width="400" height="200"
        fill="forestgreen" stroke="darkgreen" stroke-width="10"  />
</svg><span></span>

Brak źródła img

Opis

Element <img> musi mieć [src] lub [srcset]. I powinno być poprawne. Oczywiście.

Bibliografia

Selektor

img:not([src]):not([srcset]),
img[src=""],
img[src=" "],
img[src="#"],
img[src="/"],
img[srcset=""],
img[srcset=" "],
img[srcset="#"],
img[srcset="/"],
input[type="image"]:not([src]):not([srcset]),
input[type="image"][src=""],
input[type="image"][src=" "],
input[type="image"][src="#"],
input[type="image"][src="/"],
input[type="image"][srcset=""],
input[type="image"][srcset=" "],
input[type="image"][srcset="#"]
input[type="image"][srcset="/"]

Test

I tylko mi src brak
<img alt="I tylko mi src brak" width="144" height="144"/>

Etykieta z pustym atrybutem [for]

Opis

Znacznik <label> z atrybutem [for] powinien oczywiście etykietować coś z atrybutem [id]. W atrybucie [for] musi być wartość [id] etykietowanego elementu. Oczywiście.

Bibliografia

Selektor

label[for=""],
label[for=" "]

Test

<label for=" ">Zgadnij, co to?</label>

Brak jakiejś etykiety

Opis

Jak oznaczyć pole? Masz kilka opcji do wyboru: [id], [title], [aria-label] oraz [aria-labelledby].

Bibliografia

Selektor

input:not([type="button"]):not([type="submit"]):not([type="hidden"]):not([type="reset"]):not([type="image"]):not([id]):not([aria-label]):not([title]):not([aria-labelledby]),
textarea:not([id]):not([aria-label]):not([aria-labelledby]),
select:not([id]):not([aria-label]):not([aria-labelledby])

Test

<input type="text" /><span></span>

Brak wartości

Opis

Jak oznaczyć etykietą pożądane dane wejściowe typu [reset], [submit] or [button]? Zawsze masz kilka opcji do wyboru: [value], [title], [aria-label] oraz [aria-labelledby].

Bibliografia

Selektor

input[type="reset"]:not([value]):not([title]):not([aria-label]):not([aria-labelledby]),
input[type="submit"]:not([value]):not([title]):not([aria-label]):not([aria-labelledby]),
input[type="button"]:not([value]):not([title]):not([aria-label]):not([aria-labelledby])

Test

<input type="submit" /><span></span>

Pusty przycisk

Opis

Przycisk <button> powinien mieć albo zawartość albo atrybut [aria-label], [aria-labelledby] lub [title]. Atrybuty te, jeśli istnieją, nie mogą być puste.

Bibliografia

Pusty atrybut przycisku

Opis

Atrybut [aria-label], [aria-labelledby] lub [title] w znaczniku <button> nie może być pusty.

Bibliografia

Selektor

button[title=""],
button[aria-label=""],
button[aria-labelledby=""]

Test

<button title="" type="button">Test</button>

Przycisk formularza

Opis

Kontrolka <button> ma domyślnie wartość [type] równą &amp;quot;submit&amp;quot;, aby wysłać <form>.

Jednak jeśli przycisk znajduje się poza <form>, jeśli ma on za zadanie wysłać formularz, powinien o tym wspomnieć za pomocą jednego z tych atrybutów: [form], [formaction], [formtarget].

Jeśli nie wysyła niczego, powinien mieć atrybut [type="button"].

Bibliografia

Selektor

button:not([type]):not([form]):not([formaction]):not([formtarget])

Test

<button>Po prostu nie wiem, co ze sobą zrobić.</button>

Przycisk, który nie wysyła

Opis

Jeśli <button> ma wartość [type] albo "reset" albo "button", nie powinien używać następujacych atrybutów:

Bibliografia

Selektor

button[type="reset"][formmethod],
button[type="reset"][formaction],
button[type="reset"][formtarget],
button[type="reset"][formenctype],
button[type="reset"][formnovalidate],
button[type="button"][formmethod],
button[type="button"][formaction],
button[type="button"][formtarget],
button[type="button"][formenctype],
button[type="button"][formnovalidate]

Test

<button type="button" formmethod="GET">Mam metodę</button>

Wyłączony przycisk

Opis

Przycisk <button> stylizowany na wyłączony powinien być faktycznie wyłączony. Użyj [disabled] i [readonly].

Bibliografia

Selektor

button[class*="disabled"]:not([disabled], [readonly])

Test

<button class="is-disabled" type="button">Być albo nie być (wyłączonym)?</button>

input bez [type]

Opis

<input> potrzebuje [type], aby powiedzieć użytkownikowi, jaki rodzaj danych jest pożądany.

Bibliografia

Selektor

input:not([type]),
input[type=" "],
input[type=""]

Test

<label for="No-type">Brak type</label>
<input value="Cokolwiek chcesz" id="No-type"/><span></span>

optgroup bez label

Opis

<optgroup> potrzebuje [label], aby wyjaśnić, co jest wewnątrz grupy.

Bibliografia

Selektor

optgroup:not([label])

Test

<form action="/">
    <label for="optgroup-test">Oh, hej</label>
    <select id="optgroup-test">
      <optgroup label="Jestem grupą">
        <option value="1">Jestem opcją</option>
        <option value="2">Jestem kolejną opcją</option>
      </optgroup>
      <optgroup>
        <option value="3">Jestem opcją, ale z następnej grupy</option>
        <option value="4">Ja też jestem inną opcją, ale z następnej grupy</option>
     </optgroup>
   </select>
</form>

iframe bez [title]

Opis

<iframe> potrzebuje [title], aby powiedzieć użytkownikowi, czego może się spodziewać w ramce.

Bibliografia

Selektor

iframe:not([title]),
iframe[title=" "],
iframe[title=""]

Test

<iframe srcdoc="<!DOCTYPE html><title>Brak [title]</title>"></iframe><span></span>

Formularz bez [action]

Opis

Przyznasz, że <form> powinien coś robić. Czyż nie? Właśnie, a [action] ma za zadanie określić, co.

Bibliografia

Selektor

form:not([action]),
form[action=" "],
form[action=""]

Test

<form>
  <label for="input">Zgadnij, co zrobimy z Twoimi danymi?</label>
  <input id="input" type="text" />

  <input type="submit" value="Nie mam pojęcia, co?"/>
</form>

Język określony nieprawidłowo

Opis

<html> musi wskazywać programom użytkownika naturalny język dokumentu.

Bibliografia

Selektor

html:not([lang]),
html[lang*=" "],
html[lang=""]

Test

<iframe title="Przykład nieokreślonego języka" srcdoc="<!DOCTYPE html>
  <html>
    <head>
      <meta charset='utf-8'/>
      <title>Je ne parle pas Français</title>
      <style>html{font:.75rem sans-serif}</style>
      <link rel='stylesheet' type='text/css' href='https://ffoodd.github.io/a11y.css/css/a11y-en_errors-only.css'>
    </head>
    <body>
      <ul>
        <li>Speak French?</li>
        <li>Habla usted francés?</li>
        <li>Sprechen Sie Französisch?</li>
    </ul>">
</iframe>

Tabela układu

Opis

Element <table> może być użyty do układu, jeśli dodana jest [role="presentation"].

Nie wolno jednak używać znaczników semantyki oraz atrybutów mających na celu uporządkowanie danych. Oto ich lista:

Bibliografia

Selektor

table[role="presentation"] th,
table[role="presentation"] thead,
table[role="presentation"] tfoot,
table[role="presentation"] caption,
table[role="presentation"] colgroup,
table[role="presentation"] [axis],
table[role="presentation"] [scope],
table[role="presentation"] [headers]

Test

Ja nic nie znaczę! Nie powinno mnie tu być!
To działa
<table role="presentation">
  <caption>Ja nic nie znaczę! Nie powinno mnie tu być!</caption>
  <tbody>
    <tr>
      <td colspan="2">To działa</td>
    </tr>
  </tbody>
</table>

Atrybuty [width] i [height]

Opis

[width] i [height] są informacjami o prezentacji (o wyglądzie). Dlatego nie powinny być używane w znacznikach, poza <img>. Zamiast tego używaj CSS.

Bibliografia

Selektor

:not(img):not(object):not(embed):not(svg):not(canvas)[width],
:not(img):not(object):not(embed):not(svg):not(canvas)[height]

Test

Cholera! Źle się czuję :(

<p width="20">Cholera! Źle się czuję :(</p>

Atrybut zdarzenia Javascript

Opis

Atrybuty zdarzeń Javascript (takie jak [onmouseover]) nie powinny być używane. Preferuj albo pseudo-klasy CSS (:hover, :focus, :active, etc.) albo obserwatory zdarzeń JS.

Bibliografia

Selektor

[onafterprint], [onbeforeprint], [onbeforeunload],
[onerror], [onhaschange], [onload], [onmessage],
[onoffline], [ononline], [onpagehide], [onpageshow],
[onpopstate], [onredo], [onresize], [onstorage],
[onundo], [onunload],
[onblur], [onchage], [oncontextmenu], [onfocus],
[onformchange], [onforminput], [oninput], [oninvalid],
[onreset], [onselect], [onsubmit],
[onkeydown], [onkeypress], [onkeyup],
[onclick], [ondblclick], [ondrag], [ondragend],
[ondragenter], [ondragleave], [ondragover],
[ondragstart], [ondrop], [onmousedown], [onmousemove],
[onmouseout], [onmouseover], [onmouseup], [onmousewheel],
[onscroll],
[onabort], [oncanplay], [oncanplaythrough],
[ondurationchange], [onemptied], [onended], [onerror],
[onloadeddata], [onloadedmetadata], [onloadstart],
[onpause], [onplay], [onplaying], [onprogress],
[onratechange], [onreadystatechange], [onseeked],
[onseeking], [onstalled], [onsuspend], [ontimeupdate],
[onvolumechange], [onwaiting]

Test

Kliknij kliknij kliknij
<span onclick="alert('Kliknięte!');">Kliknij kliknij kliknij</span>

Przestrzeń nazw

Opis

Czy wiesz, że niektórych znaków należy unikać jako pierwszych znaków w nazwach klas i identyfikatorach CSS? Tak - cyfry, dwóch myślników lub myślnika, po którym następuje cyfra.

Bibliografia

Selektor

[id^="1"],
[id^="2"],
[id^="3"],
[id^="4"],
[id^="5"],
[id^="6"],
[id^="7"],
[id^="8"],
[id^="9"],
[id^="0"],
[id^="--"],
[id^="-1"],
[id^="-2"],
[id^="-3"],
[id^="-4"],
[id^="-5"],
[id^="-6"],
[id^="-7"],
[id^="-8"],
[id^="-9"],
[id^="-0"],
[class^="1"],
[class^="2"],
[class^="3"],
[class^="4"],
[class^="5"],
[class^="6"],
[class^="7"],
[class^="8"],
[class^="9"],
[class^="0"],
[class^="--"],
[class^="-1"],
[class^="-2"],
[class^="-3"],
[class^="-4"],
[class^="-5"],
[class^="-6"],
[class^="-7"],
[class^="-8"],
[class^="-9"],
[class^="-0"]

Test

Witam! Moje ID to 2.
<div id="2">Witam! Moje ID to 2.</div>

Pusty znacznik title

Opis

Znacznik <title> jest pierwszą rzeczą czytaną na głos przez czytniki ekranu - aby ogłosić… tytuł strony - a także pierwszą rzeczą wyświetlaną na stronach wyników wyszukiwarek.

Moglibyśmy użyć pseudoklasy :blank, ale w tym momencie jej obsługa jest bardzo słaba. Moglibyśmy również użyć pseudoklasy :-moz-only-whitespace, ale jej obsługa jest ograniczona do Firefoksa, co mogłoby spowodować niepoprawność naszego stosu selektorów…

Bibliografia

Selektor

title:empty

Test

<title></title>

Niedostępny atrybut viewport

Opis

Użytkownik powinien mieć możliwość powiększania lub pomniejszania strony, aby poprawić czytelność i wygodę; jest to zwykle dozwolone w <meta> viewport.

Bibliografia

Selektor

meta[name="viewport"][content*="maximum-scale"],
meta[name="viewport"][content*="minimum-scale"],
meta[name="viewport"][content*="user-scalable=no"]

Test

<iframe title="Przykład złej instrukcji viewport" srcdoc="<!DOCTYPE html>
  <html lang='pl'>
    <head>
      <meta charset='utf-8'/>
      <title>Przykład złej instrukcji viewport</title>
      <meta name='viewport' content='user-scalable=no'/>
      <style>html{font:.75rem sans-serif}</style>
      <link rel='stylesheet' type='text/css' href='https://ffoodd.github.io/a11y.css/css/a11y-en_errors-only.css'>
    </head>
    <body>
      <h1>Zła instrukcja <code>viewport</code></h1>">
</iframe>

Niewłaściwy charset

Opis

Używanie kodowania znaków utf-8 jest zalecane przez samo W3C:

obsługuje wiele języków i może obsługiwać strony i formularze w dowolnej mieszance tych języków.

Ponadto pozwala uniknąć pewnych problemów związanych z bezpieczeństwem, wykorzystywanych przez inne zestawy znaków…

Bibliografia

Selektor

meta[charset]:not([charset="utf-8"]):not([charset="UTF-8"])

Test

<meta charset="Windows-1252"/><link></link>

Charset powinien być w head pierwszy

Opis

Jak wyjaśniono na Mozilla Developer Network:

Element <meta> deklarujący kodowanie musi znajdować się wewnątrz elementu <head> i w obrębie pierwszych 1024 bajtów HTML, ponieważ niektóre przeglądarki patrzą tylko na te bajty przed wyborem kodowania.

Ma to również na celu zapobieżenie staremu eksploitowi bezpieczeństwa wykorzystującemu UTF-7. Zadeklarowanie zestawu znaków przed znacznikiem <title> jest najprostszym sposobem, aby to ukryć.

Bibliografia

Selektor

head :first-child:not([charset])

Test

<iframe title="Spóźnione ustawienie strony kodowej" srcdoc="<!DOCTYPE html>
  <html lang=en>
    <head>
      <title>Oups !</title>
      <style>html{font:.75rem sans-serif}</style>
      <link rel=stylesheet type=text/css href=https://ffoodd.github.io/a11y.css/css/a11y-en_errors-only.css>
    </head>
    <body>
      <h1>Jak jestem zakodowany, kolego?</h1>">
</iframe>

Niepoprawny atrybut [dir]

Opis

Atrybut [dir] służący do określenia kierunku tekstu elementu - przyjmuje tylko trzy wartości: rtl, ltr oraz auto.

Bibliografia

Selektor

[dir]:not([dir="rtl"]):not([dir="ltr"]):not([dir="auto"])

Test

Cóż, jestem trochę zdezorientowany…

<p dir="wtf">Cóż, jestem trochę zdezorientowany…</p>

[accesskey] to zły pomysł

Opis

Atrybut [accesskey] jest przeznaczony do implementacji skrótów klawiaturowych specyficznych dla danej witryny. Jest to zazwyczaj zły pomysł, ponieważ skróty klawiaturowe mogą być już używane przez system operacyjny, przeglądarkę, rozszerzenie przeglądarki, a nawet ustawienia użytkownika…

To jest opinia: w idealnym świecie [accesskey] może być używany mądrze. Yup. Być może.

Bibliografia

Selektor

[accesskey]

Test

Przejdź do tego łącza, używając 1
<a id="key" name="key" accesskey="1">Przejdź do tego łącza, używając <kbd>1</kbd></a>

Grupowanie pól

Opis

Pola typu radio lub checkbox są zwykle zgrupowane. Atrybut [name] służy do ich programowego powiązania, dlatego jest potrzebny.

Bibliografia

Selektor

[type="radio"]:not([name]),
[type="checkbox"]:not(:only-of-type):not([name])

Test

Opcje

<form action="/">
  <fieldset>
    <legend>Opcje</legend>
    <p>
      <label for="option-1">Opcja N<sup>o</sup>1</label>
      <input type="radio" id="option-1"><span></span>
    </p>
    <p>
      <label for="option-2">Opcja N<sup>o</sup>2</label>
      <input type="radio" id="option-2" name="options">
    </p>
  </fieldset>
</form>

[radio] poza fieldset

Opis

Pola typu radio powinny być zgrupowane przez nadrzędny <fieldset>, opisany przez jego <legend>.

Zauważ, że WCAG tego nie wymaga, ale zdecydowanie zaleca: „w przypadku, gdy indywidualna etykieta związana z każdą konkretną kontrolą zapewnia wystarczający opis, użycie elementów fieldset i legend nie jest wymagane”

Ten test może być ostrzeżeniem…

Bibliografia

Selektor

[type="radio"]

Test


Próba w zestawie pól, nie powinna być dopasowana

<form action="/">
  <p>
    <label for="option-1">Opcja nr 1</label>
    <input type="radio" id="option-1" name="options"><span></span>
  </p>

  <br>

  <fieldset>
    <legend>Próba w zestawie pól, nie powinna być dopasowana</legend>
    <p>
      <label for="option-2">Opcja nr 2</label>
      <input type="radio" id="option-2" name="options"><span></span>
    </p>
  </fieldset>
</form>

[role=slider] - brak atrybutów

Opis

Element z [role="slider"] wymaga kilku atrybutów:

Również [aria-valuetext] jest mile widziany, mimo że nie jest wymagany przez specyfikację ARIA.

Bibliografia

Selektor

[role="slider"]:not([aria-valuemin]),
[role="slider"]:not([aria-valuemax]),
[role="slider"]:not([aria-valuenow])

Test

<label for="slider">Slider</label>
<input id="slider" role="slider" type="range" /><span></span>

[role=spinbutton] - brak atrybutów

Opis

Element z [role=spinbutton] wymaga kilku atrybutów::

Bibliografia

Selektor

[role="spinbutton"]:not([aria-valuemin]),
[role="spinbutton"]:not([aria-valuemax]),
[role="spinbutton"]:not([aria-valuenow])

Test

<label for="spinbutton">Spinbutton</label>
<input id="spinbutton" role="spinbutton" type="range" /><span></span>

[role=checkbox] nie ma stanu

Opis

Element z [role="checkbox"] wymaga atrybutu stanu [aria-checked]

Bibliografia

Selektor

[role="checkbox"]:not([aria-checked])

Test

Pole wyboru
<img src="./static/ffoodd.png" alt="Pole wyboru" role="checkbox" width="36" height="36"/><span></span>

[role=combobox] nie ma [state]

Opis

Element z [role="combobox"] wymaga atrybutu stanu [aria-expanded].

Bibliografia

Selektor

[role="combobox"]:not([aria-expanded])

Test

<input type="text" aria-label="Pole złożone" role="combobox" id="combobox"><span></span>

[role=scrollbar] wymaga właściwości

Opis

Niektóre właściwości muszą być zgodne z wzorcem projektowym [role="scrollbar"]:

Bibliografia

Selektor

[role="scrollbar"]:not([aria-controls]),
[role="scrollbar"]:not([aria-valuemin]),
[role="scrollbar"]:not([aria-valuemax]),
[role="scrollbar"]:not([aria-valuenow]),
[role="scrollbar"]:not([aria-orientation])

Test

<div role="scrollbar"></div>

Zagnieżdżony element interaktywny

Opis

Element interaktywny nie może być umieszczony w innym elemencie interaktywnym (np. <a> w <button>).

Bibliografia

Selektor

a a[href],
button a[href],
a audio[controls],
button audio[controls],
a video[controls],
button video[controls],
a button,
button button,
a details,
button details,
a embed,
button embed,
a iframe,
button iframe,
a img[usemap],
button img[usemap],
a label,
button label,
a select,
button select,
a textarea,
button textarea,
a input[type]:not([hidden]),
button input[type]:not([hidden]),
form form,
label label,
meter meter,
progress progress

Test

<a href="https://lepszyweb.pl">
  <button type=button">Chwila, co mam uruchomić?</button>
</a>