Advices

<select required> should start with an empty <option>'s [value]

Description

A <select required> element, which isn't [multiple] and whose [size] isn't greater than 1, should start with an empty <option>. That being said, you may use a placeholder content for this option but must ensure to use an empty [value] attribute; or set a [size] attribute to the <select>, which value should equal to the number of <option>s.

References

Selector

select[required]:not([multiple])[size="1"],
select[required]:not([multiple], [size])

Test

<select name="slices" required>
  <option value="1">Cheese</option>
  <option value="2">Salami</option>
</select><span></span>

Empty [class] attribute

Description

[class] shouldn't be present if empty. Something to improve, right?

Selector

[class=""],
[class=" "]

Test

Why is there a class here?
<b class="">Why is there a class here?</b>

Empty [id] attribute

Description

[id] shouldn't be present if empty. You'll thank me later.

Selector

[id=""],
[id=" "]

Test

Wait. Why is my ID empty?
<i id="">Wait. Why is my ID empty?</i>

A second visible main tag

Description

A single <main> should be visible at a time. Isn't that obvious?

References

Selector

main ~ main:not([hidden])

Test

I'm the main content!
No, It's me!
<main>I'm the main content!</main>
<main>No, It's me!</main>

A second figcaption tag

Description

<figcaption> should be single inside its parent. Check the spec!

References

Selector

figcaption:not(:first-of-type)

Test

I'm the caption.
Needed
I'm the caption too.
<figure role="group">
  <figcaption>I'm the caption.</figcaption>
  <img src="/static/ffoodd.png" alt="Needed" width="144" height="144" />
  <figcaption>I'm the caption too.</figcaption>
</figure>

figcaption order

Description

<figcaption> should be first or last child. Nothing else.

References

Selector

figcaption:not(:first-child, :last-child)

Test

Needed
I'm the caption.

I'm something else. Oh, wait.

<figure role="group">
  <img src="/static/ffoodd.png" alt="Needed" width="144" height="144" />
  <figcaption>I'm the caption.</figcaption>
  <p>I'm something else. Oh, wait.</p>
</figure>

An email link should be valid

Description

A <href="mailto:"> should contain a valid email. Otherwise you may annoy your users.

Selector

[href^="mailto"]

Test

Surpri-ise!
<a href="mailto:myself">Surpri-ise!</a>

A phone link should call a real number

Description

A <href="tel:"> should contain a valid phone number. Otherwise you may make your users to call anubody.

Selector

[href^="tel"]

Test

Who will I call?
<a href="tel:012345678">Who will I call?</a>

button [role] on a link

Description

Obviously, a button role on a link is probably not so hard to move to an authentic button tag, isn't it?

References

Selector

a[role="button"]

Test

Submit
<a href="/" role="button">Submit</a>

Link opening new tab

Description

A link opening new tab or window should warn user about its behaviour. You could use a [title], for example.

References

Selector

[target$="blank"]

Test

New tab
<a href="/" target="_blank" rel="noopener noreferrer">New tab</a>

Linking to a file

Description

A link to a file should indicate the file format, the file size and if different from the main document, the file language.

References

Selector

[download],
[href$=".pdf"]:not(link),
[href$=".doc"]:not(link),
[href$=".png"]:not(link),
[href$=".jpg"]:not(link),
[href$=".gif"]:not(link),
[href$=".mp3"]:not(link),
[href$=".mp4"]:not(link),
[href$=".mov"]:not(link),
[href$=".ogg"]:not(link),
[href$=".xls"]:not(link),
[href$=".txt"]:not(link),
[href$=".zip"]:not(link),
[href$=".rar"]:not(link),
[href$=".docx"]:not(link),
[href$=".webp"]:not(link),
[href$=".apng"]:not(link),
[href$=".svg"]:not(link),
[href$=".svgz"]:not(link)

Test

Wanna file?
<a href="/static/ffoodd.png">Wanna file?</a>

Duplicated roles

Description

Some ARIA roles should be unique: at least [main], [search], [banner], [contentinfo].

References

Selector

[role="main"] ~ [role="main"],
[role="search"] ~ [role="search"],
[role="banner"] ~ [role="banner"],
[role="contentinfo"] ~ [role="contentinfo"]

Test



<main role="main"><br /></main>
<div role="main"><br /></div>

May have a search [role]?

Description

A [class] or [id] containing search may carry the search ARIA [role].

References

Selector

[id*="search"]:not([role="search"]),
[class*="search"]:not([role="search"])

Test

<form class="search" action="">
  <label for="field">Search</label>
  <input type="search" id="field" /><span></span>
</form>

Does this look like [required]?

Description

A [required] or [aria-required] should be visually understandable.

References

Selector

[required],
[aria-required]

Test

<form action="">
  <label for="field">Fied</label>
  <textarea id="field" required></textarea><span></span>
</form>

Not :empty [hidden] things

Description

A [hidden] or [aria-hidden] may not be a good idea if hiding content.

References

Selector

[hidden]:not(:empty),
[aria-hidden="true"]:not(:empty)

Test

<a href="/" aria-hidden="true">Important thing!</a>

Placeholder can't replace a label

Description

A [placeholder] is not a label, is it?

Selector

[placeholder]:not([title], [aria-label], [aria-labelledby])

Test

<input type="text" placeholder="Look Ma, no label!" id="test"><span></span>

video or audio things

Description

A <video> or <audio> needs a few things to be accessible, like a transcript, subtitles, controls. This kind of things.

References

Selector

video,
audio

Test

<video src="/" controls></video><span></span>

[title] should be equal to alternative

Description

A [title] on any graphic content should be equal to [aria-label] or [alt].

References

Selector

img[alt][title],
area[alt][title],
svg[aria-label][title]

Test

I'm an alternative text!
<img src="/static/ffoodd.png" alt="I'm an alternative text!" title="I'm a title!" height="144" width="144"><span></span>

Date and time should be understandable

Description

A <time> or [datetime] content should be an understandable and well formated date.

Selector

time,
[datetime]

Test

<time>Yesterday</time>

[scope] should be either col or row

Description

A [scope] can be col or row (and nothing else) and it has to be relevant.

References

Selector

th[scope]

Test

I'm a caption
First column Second column
First cell Second cell
First cell Second cell
<table>
  <caption>I'm a caption</caption>
  <thead>
    <tr>
      <th scope="col">First column</th>
      <td>Second column</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>First cell</td>
      <td>Second cell</td>
    </tr>
    <tr>
      <td>First cell</td>
      <td>Second cell</td>
    </tr>
  </tbody>
</table>

Layout table in use

Description

A [role="presentation"] is a good idea for any <table> used for layout, but a bad thing for a data table. Double check this!

References

Selector

table[role="presentation"]

Test

First cell Second cell
First cell Second cell
<table role="presentation">
  <tr>
    <td>First cell</td>
    <td>Second cell</td>
  </tr>
  <tr>
    <td>First cell</td>
    <td>Second cell</td>
  </tr>
</table>

No [href]

Description

Yet it's valid to skip the [href] attribute on a link, it's probably better to double check, isn't it?

References

Selector

a:not([href])

Test

Who am I? Where do I link?
<a>Who am I? Where do I link?</a>

Non HTTPS URL

Description

When possible, try to use HTTPS.

References

Selector

[src^="http:"],
[href^="http:"]

Test

My target's protocol isn't secured
<a href="http://www.ffoodd.fr/">My target's protocol isn't secured</a>