@charset "UTF-8";


/*doc
---
title: "Invalid nesting in a list"
name: invalid-list-nesting
category: Warnings
---

### Description
The only child allowed in `<ul>` and `<ol>` is `<li>` - and the converse is also true.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.2>
* <https://www.w3.org/TR/WCAG22/#parsing>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L313>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#the-li-element>

### Selector
```css
ul > :not(li),
ol > :not(li),
:not(ul, ol) > li
```

### Test
``` html
<ul>
	<p>I feel like I'm lost.</p>
</ul>
```
*/
ul > :not(li),
ol > :not(li),
:not(ul, ol) > li {
	@include warning('invalid-list-nesting');
}


/*doc
---
title: "Invalid sibling in a definition list"
name: invalid-def
category: Warnings
---

### Description
`<dt>` and `<dd>` should be direct adjacent siblings, and nothing else. Although multiple `<dd>` may follow a single `<dt>`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.2>
* <https://www.w3.org/TR/WCAG22/#parsing>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L312>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#the-dl-element>

### Selector
```css
dt + :not(dd),
:not(dt, dd) + dd
```

### Test
``` html
<dl>
	<dt>I need a definition, don't you think?</dt>
	<li>I'm a list item.</li>
</dl>
```
*/
dt + :not(dd),
:not(dt, dd) + dd {
	@include warning('invalid-def');
}


/*doc
---
title: "Invalid nesting in a definition list"
name: invalid-def-nesting
category: Warnings
---

### Description
`<div>`, `<dt>` and `<dd>` should be direct children of `<dl>`.
Any other imbrication may be a crime somewhere.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.2>
* <https://www.w3.org/TR/WCAG22/#parsing>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L318>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#the-dl-element>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#elementdef-dl>

### Selector
```css
:not(dl) > dt,
:not(dl) > dd,
dl > :not(dt, dd, div)
```

### Test
``` html
<dl>
	<li>I'm a list item.</li>
</dl>
```
*/
:not(dl) > dt,
:not(dl) > dd,
dl > :not(dt, dd, div) {
	@include warning('invalid-def-nesting');
}


/*doc
---
title: "figcaption outside a figure"
name: invalid-figcaption-nesting
category: Warnings
---

### Description
`<figcaption>` doesn't make sense outside a `<figure>`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.2>
* <https://www.w3.org/TR/WCAG22/#parsing>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#the-figcaption-element>

### Selector
```css
:not(figure) > figcaption
```

### Test
``` html
<figcaption>I'm captionning something, isn't it?</figcaption>
```
*/
:not(figure) > figcaption {
	@include warning('invalid-figcaption-nesting');
}


/*doc
---
title: "figure without an ARIA role"
name: figure-role
category: Warnings
---

### Description
`<figure>` needs `[role="figure"]` for accessibility reason.

`[role="group"]` is allowed because still suggested in RGAA v4.1.2 but `[role="figure"]` should be preferred.

### References
* <https://www.scottohara.me/blog/2019/01/21/how-do-you-figure.html>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.9>
* <https://www.w3.org/WAI/tutorials/images/groups/>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#the-figure-element>

### Selector
```css
figure:not([role="group"], [role="figure"])
```

### Test
``` html
<figure>
	<img src="/static/ffoodd.png" width="144" height="144" alt="Figcaption test"/>
	<figcaption>I'm a figcaption</figcaption>
</figure>
```
*/
figure:not([role="group"], [role="figure"]) {
	@include warning('figure-role');
}


/*doc
---
title: "Invalid nesting"
name: invalid-nesting
category: Warnings
---

### Description
Some nestings are forbidden, and do not have their own test case for now:

* `<main>` contained in any of `<nav>`, `<aside>`, `<footer>`, `<header>` or `<article>`;
* `<address>` containing any of `<address>`, `<nav>`, `<aside>`, `<section>`, `<footer>`, `<header>` or `<article>` — neither headings;
* `<option>` and `<optgroup>` outside a `<select>`;
* `<legend>` outside a `<fieldset>`;
* `<td>` or `<th>` outside a `<tr>`;
* direct children of a `<table>`;
* `<colgroup>` containing anything else than `<col>`.

Maybe other invalid nestings to test. Stay tuned.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.2>.
* <https://html.spec.whatwg.org/multipage/grouping-content.html#elementdef-main>
* <https://html.spec.whatwg.org/multipage/grouping-content.html#the-address-element>
* <https://www.w3.org/TR/WCAG22/#parsing>
* <https://www.w3.org/TR/WCAG22/#name-role-value>

### Selector
```css
nav main,
aside main,
footer main,
header main,
article main,
:not(tr) > td,
:not(tr) > th,
colgroup *:not(col),
:not(colgroup) > col,
tr > :not(td, th),
optgroup > :not(option),
:not(select) > optgroup,
:not(fieldset) > legend,
select > :not(option, optgroup),
:not(select, optgroup) > option,
table > *:not(thead, tfoot, tbody, tr, colgroup, caption),
address h1,
address h2,
address h3,
address h4,
address h5,
address h6,
address nav,
address aside,
address header,
address footer,
address address,
address article,
address section
```

### Test
``` html
<legend>I'm an legend. Am I?</legend>
```
*/
nav main,
aside main,
footer main,
header main,
article main,
:not(tr) > td,
:not(tr) > th,
colgroup *:not(col),
:not(colgroup) > col,
tr > :not(td, th),
optgroup > :not(option),
:not(select) > optgroup,
:not(fieldset) > legend,
select > :not(option, optgroup),
:not(select, optgroup) > option,
table > *:not(thead, tfoot, tbody, tr, colgroup, caption),
address h1,
address h2,
address h3,
address h4,
address h5,
address h6,
address nav,
address aside,
address header,
address footer,
address address,
address article,
address section {
	@include warning('invalid-nesting');
}


/*doc
---
title: "Misplaced div"
name: misplaced-div
category: Warnings
---

### Description
Did you know that you shouldn't add a `<div>` inside any inline element?
You could use a `<span>` instead.

### References
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L326>

### Selector
```css
b div,
i div,
q div,
em div,
abbr div,
cite div,
code div,
span div,
small div,
label div,
strong div
```

### Test
``` html
<b><div>Hey ya!</div></b>
```
*/
b div,
i div,
q div,
em div,
abbr div,
cite div,
code div,
span div,
small div,
label div,
strong div {
	@include warning('misplaced-div');
}


/*doc
---
title: "Misused sectioning tags"
name: sectioning-tags
category: Warnings
---

### Description
`<section>`, `<aside>`, `<article>` are sectioning tags.
They must not be used as wrappers!

### References
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L252>
* <https://html.spec.whatwg.org/multipage/dom.html#sectioning-content>

### Selector
```css
aside > aside:first-child,
article > aside:first-child,
aside > article:first-child,
aside > section:first-child,
section > section:first-child,
article > section:first-child,
article > article:first-child
```

### Test
``` html
<aside>
	<section>I'm wrapping, you know.</section>
</aside>
```
*/
aside > aside:first-child,
article > aside:first-child,
aside > article:first-child,
aside > section:first-child,
section > section:first-child,
article > section:first-child,
article > article:first-child {
	@include warning('sectioning-tags');
}


/*doc
---
title: "legend must be a fieldset's:first-child"
name: fieldset
category: Warnings
---

### Description
`<legend>` must be a `<fieldset>`'s`:first-child`.
Always.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.6>
* <https://www.w3.org/TR/WCAG22/#info-and-relationships>
* <https://www.w3.org/TR/WCAG22/#labels-or-instructions>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L218>

### Selector
```css
fieldset > *:not(legend):first-child,
fieldset > legend:not(:first-child)
```

### Test
``` html
<fieldset>
	<label>I'm not a legend.</label>
</fieldset>
```
*/
fieldset > *:not(legend):first-child,
fieldset > legend:not(:first-child) {
	@include warning('fieldset');
}


/*doc
---
title: "summary must be a details's:first-child"
name: details
category: Warnings
---

### Description
`<summary>` must be a `<details>`'s`:first-child`.
Always.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.6>
* <https://www.w3.org/TR/WCAG22/#info-and-relationships>
* <https://www.w3.org/TR/WCAG22/#labels-or-instructions>
* <https://html.spec.whatwg.org/multipage/interactive-elements.html#elementdef-summary>
* <https://html.spec.whatwg.org/multipage/interactive-elements.html#elementdef-details>

### Selector
```css
details > *:not(summary):first-child,
details > summary:not(:first-child)
```

### Test
``` html
<details>
	<legend>I'm not a summary.</legend>
</details>
```
*/
details > *:not(summary):first-child,
details > summary:not(:first-child) {
	@include warning('details');
}


/*doc
---
title: "abbr should have a [title]"
name: empty-title
category: Warnings
---

### Description
Any abbreviation should give an explanation about its meaning, at least on its first occurrence.

### References
* [Opquast - Rule 5](https://checklists.opquast.com/en/web-quality-assurance/the-first-occurrence-of-an-abbreviation-or-an-acronym-in-the-body-of-any-page-provides-an-explanation-of-its-meaning)
* <https://www.w3.org/TR/WCAG22/#abbreviations>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G70>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G97>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G102>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H28>

### Selector
```css
abbr:not([title]),
abbr[title=" "],
abbr[title=""]
```

### Test
``` html
<p>Do you know about <abbr>W3C</abbr>?</p>
```
*/
abbr:not([title]),
abbr[title=" "],
abbr[title=""] {
	@include warning('empty-title');
}


/*doc
---
title: "[alt] can be empty but has to be checked"
name: empty-alt
category: Warnings
---

### Description
An alternative has to be empty when image is decorative only. In any other case, `[alt]` must be defined.
That should be double-checked.

### References
* [Opquast - Rule 111](https://checklists.opquast.com/en/web-quality-assurance/each-decorative-image-has-an-appropriate-text-alternative)
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.2>
* <https://www.accede-web.com/notices/html-et-css/images-et-icones/gerer-lattribut-alt-des-balises-img-et-input-typeimage/>
* <https://www.w3.org/WAI/tutorials/images/decision-tree/>
* <https://html.spec.whatwg.org/multipage/images.html#alt>
* <https://www.w3.org/TR/WCAG22/#non-text-content>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H67>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F39>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F38>

### Selector
```css
img[alt=""],
area[alt=""],
input[type="image"][alt=""],
embed[type="image"][alt=""],
object[type="image"][alt=""]
```

### Test
``` html
<img alt="" src="/static/ffoodd.png" width="144" height="144" /><span>†</span>
```
*/
img[alt=""],
area[alt=""],
input[type="image"][alt=""] {
	@include warning('empty-alt', $self-closing: true);
}

embed[type="image"][alt=""],
object[type="image"][alt=""] {
	@include warning('empty-alt');
}


/*doc
---
title: "[alt] containing file name"
name: filename-alt
category: Warnings
---

### Description
A file name in `[alt]` is probably wrongly automated… and would never ever help any user.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.2>
* <https://www.accede-web.com/notices/html-et-css/images-et-icones/gerer-lattribut-alt-des-balises-img-et-input-typeimage/>
* <https://www.w3.org/WAI/tutorials/images/decision-tree/>
* <https://html.spec.whatwg.org/multipage/images.html#alt>
* <https://www.w3.org/TR/WCAG22/#non-text-content>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H67>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F39>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F38>

### Selector
```css
img[alt$=".pdf"],
area[alt$=".pdf"],
input[type="image"][alt$=".pdf"],
img[alt$=".doc"],
area[alt$=".doc"],
input[type="image"][alt$=".doc"],
img[alt$=".png"],
area[alt$=".png"],
input[type="image"][alt$=".png"],
img[alt$=".jpg"],
area[alt$=".jpg"],
input[type="image"][alt$=".jpg"],
img[alt$=".gif"],
area[alt$=".gif"],
input[type="image"][alt$=".gif"],
img[alt$=".mp3"],
area[alt$=".mp3"],
input[type="image"][alt$=".mp3"],
img[alt$=".mp4"],
area[alt$=".mp4"],
input[type="image"][alt$=".mp4"],
img[alt$=".mov"],
area[alt$=".mov"],
input[type="image"][alt$=".mov"],
img[alt$=".ogg"],
area[alt$=".ogg"],
input[type="image"][alt$=".ogg"],
img[alt$=".xls"],
area[alt$=".xls"],
input[type="image"][alt$=".xls"],
img[alt$=".txt"],
area[alt$=".txt"],
input[type="image"][alt$=".txt"],
img[alt$=".zip"],
area[alt$=".zip"],
input[type="image"][alt$=".zip"],
img[alt$=".rar"],
area[alt$=".rar"],
input[type="image"][alt$=".rar"],
img[alt$=".docx"],
area[alt$=".docx"],
input[type="image"][alt$=".docx"],
img[alt$=".webp"],
area[alt$=".webp"],
input[type="image"][alt$=".webp"],
img[alt$=".apng"],
area[alt$=".apng"],
input[type="image"][alt$=".apng"],
img[alt$=".svg"],
area[alt$=".svg"],
input[type="image"][alt$=".svg"],
img[alt$=".svgz"],
area[alt$=".svgz"],
input[type="image"][alt$=".svgz"],
embed[type="image"][alt$=".pdf"],
object[type="image"][alt$=".pdf"],
embed[type="image"][alt$=".doc"],
object[type="image"][alt$=".doc"],
embed[type="image"][alt$=".png"],
object[type="image"][alt$=".png"],
embed[type="image"][alt$=".jpg"],
object[type="image"][alt$=".jpg"],
embed[type="image"][alt$=".gif"],
object[type="image"][alt$=".gif"],
embed[type="image"][alt$=".mp3"],
object[type="image"][alt$=".mp3"],
embed[type="image"][alt$=".mp4"],
object[type="image"][alt$=".mp4"],
embed[type="image"][alt$=".mov"],
object[type="image"][alt$=".mov"],
embed[type="image"][alt$=".ogg"],
object[type="image"][alt$=".ogg"],
embed[type="image"][alt$=".xls"],
object[type="image"][alt$=".xls"],
embed[type="image"][alt$=".txt"],
object[type="image"][alt$=".txt"],
embed[type="image"][alt$=".zip"],
object[type="image"][alt$=".zip"],
embed[type="image"][alt$=".rar"],
object[type="image"][alt$=".rar"],
embed[type="image"][alt$=".docx"],
object[type="image"][alt$=".docx"],
embed[type="image"][alt$=".webp"],
object[type="image"][alt$=".webp"],
embed[type="image"][alt$=".apng"],
object[type="image"][alt$=".apng"],
embed[type="image"][alt$=".svg"],
object[type="image"][alt$=".svg"],
embed[type="image"][alt$=".svgz"],
object[type="image"][alt$=".svgz"]
```

### Test
``` html
<img alt="/static/ffoodd.png" src="/static/ffoodd.png" width="144" height="144" /><span>†</span>
```
*/
$alt: ();
$self-alt: ();

@each $format in $formats {
	$alt: append($alt, unquote('img[alt$=".#{$format}"], area[alt$=".#{$format}"], input[type="image"][alt$=".#{$format}"]'), 'comma');
	$self-alt: append($self-alt, unquote('embed[type="image"][alt$=".#{$format}"], object[type="image"][alt$=".#{$format}"]'), 'comma');
}

#{$alt} {
	@include warning('filename-alt', $self-closing: true);
}

#{$self-alt} {
	@include warning('filename-alt');
}


/*doc
---
title: "Decorative image shouldn't have an accessible name"
name: decoration
category: Warnings
---

### Description
Any decorative image — with `[aria-hidden="true"]` or empty `[alt]` — shouldn't have any of those:

* `[title]`;
* `[aria-label]`;
* `[aria-labelledby]`;
* `[aria-describedby]`;
* a `<title>` child;
* or a `<desc>`.

This test currently can't check if any `<title>` nor `<desc>` child is present since `<svg>` is a replaced elements.
See [Edge cases and known issues](https://github.com/ffoodd/a11y.css/wiki/Edge-cases-and-known-issues) on a11y.css' wiki.

### References
* [Opquast - Rule 111](https://checklists.opquast.com/en/web-quality-assurance/each-decorative-image-has-an-appropriate-text-alternative)
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.2>
* <https://www.accede-web.com/notices/html-et-css/images-et-icones/gerer-lattribut-alt-des-balises-img-et-input-typeimage/#ancre-01>
* <https://www.w3.org/WAI/tutorials/images/decision-tree/>
* <https://www.w3.org/TR/wai-aria-1.3/#presentation>
* <https://html.spec.whatwg.org/multipage/images.html#alt>
* <https://www.w3.org/TR/WCAG22/#non-text-content>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H67>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F39>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F38>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F65>

### Selector
```css
img[alt=""][title],
img[alt=""][aria-label],
img[alt=""][aria-labelledby],
img[alt=""][aria-describedby],
area:not([href])[alt]:not([alt=""]),
area:not([href])[alt=""][title],
area:not([href])[alt=""][aria-label],
area:not([href])[alt=""][aria-labelledby],
area:not([href])[alt=""][aria-describedby],
svg[aria-hidden="true"][title],
svg[aria-hidden="true"][aria-label],
svg[aria-hidden="true"][aria-labelledby],
svg[aria-hidden="true"][aria-describedby],
canvas[aria-hidden="true"][title],
canvas[aria-hidden="true"][aria-label],
canvas[aria-hidden="true"][aria-labelledby],
canvas[aria-hidden="true"][aria-describedby],
embed[type="image"][aria-hidden="true"][title],
embed[type="image"][aria-hidden="true"][aria-label],
embed[type="image"][aria-hidden="true"][aria-labelledby],
embed[type="image"][aria-hidden="true"][aria-describedby],
object[type="image"][aria-hidden="true"][title],
object[type="image"][aria-hidden="true"][aria-label],
object[type="image"][aria-hidden="true"][aria-labelledby],
object[type="image"][aria-hidden="true"][aria-describedby],
```

### Test
``` html
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
	xmlns="http://www.w3.org/2000/svg"
	aria-hidden="true" title="Decorative SVG, you punk!">
	<rect x="400" y="100" width="400" height="200"
		fill="forestgreen" stroke="darkgreen" stroke-width="10"/>
</svg><span>†</span>
```
*/
img[alt=""][title],
img[alt=""][aria-label],
img[alt=""][aria-labelledby],
img[alt=""][aria-describedby],
area:not([href])[alt]:not([alt=""]),
area:not([href])[alt=""][title],
area:not([href])[alt=""][aria-label],
area:not([href])[alt=""][aria-labelledby],
area:not([href])[alt=""][aria-describedby],
svg[aria-hidden="true"][title],
svg[aria-hidden="true"][aria-label],
svg[aria-hidden="true"][aria-labelledby],
svg[aria-hidden="true"][aria-describedby],
embed[type="image"][aria-hidden="true"][title],
embed[type="image"][aria-hidden="true"][aria-label],
embed[type="image"][aria-hidden="true"][aria-labelledby],
embed[type="image"][aria-hidden="true"][aria-describedby], {
	@include warning('decoration', $self-closing: true);
}

canvas[aria-hidden="true"][title],
canvas[aria-hidden="true"][aria-label],
canvas[aria-hidden="true"][aria-labelledby],
canvas[aria-hidden="true"][aria-describedby],
object[type="image"][aria-hidden="true"][title],
object[type="image"][aria-hidden="true"][aria-label],
object[type="image"][aria-hidden="true"][aria-labelledby],
object[type="image"][aria-hidden="true"][aria-describedby] {
	@include warning('decoration');
}


/*doc
---
title: "[role=presentation] shouldn't be used on image"
name: presentation
category: Warnings
---

### Description
Any decorative image should be marked up with `[aria-hidden="true"]` (or empty `[alt]` if `<img>`).
`[role=presentation]` shall do the trick but at the time of writing, its support is too low compared
to empty `[alt]` or `[aria-hidden=true]`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.2>
* <https://www.w3.org/WAI/tutorials/images/decorative/>


### Selector
```css
img[role="presentation"],
svg[role="presentation"],
area[role="presentation"],
embed[role="presentation"],
canvas[role="presentation"],
object[role="presentation"]
```

### Test
``` html
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
	xmlns="http://www.w3.org/2000/svg"
	role="presentation">
	<rect x="400" y="100" width="400" height="200"
		fill="forestgreen" stroke="darkgreen" stroke-width="10"/>
</svg><span>†</span>
```
*/
img[role="presentation"],
svg[role="presentation"],
area[role="presentation"],
embed[role="presentation"] {
	@include warning('presentation', $self-closing: true);
}

canvas[role="presentation"],
object[role="presentation"] {
	@include warning('presentation');
}


/*doc
---
title: "A role is needed for svg"
name: no-aria-role
category: Warnings
---

### Description
Any `<svg>` should either have `[aria-hidden="true"]` if decorative, or a `[role="img"]` if informative.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.2>
* <https://www.w3.org/TR/WCAG22/#non-text-content>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F65>

### Selector
```css
svg:not([aria-hidden="true"], [role="img"])
```

### Test
``` html
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
	xmlns="http://www.w3.org/2000/svg"
	aria-label="Decorative SVG, you punk!">
	<rect x="400" y="100" width="400" height="200"
		fill="forestgreen" stroke="darkgreen" stroke-width="10"/>
</svg><span>†</span>
```
*/
svg:not([aria-hidden="true"], [role="img"]) {
	@include warning('no-aria-role', $self-closing: true);
}


/*doc
---
title: "[autoplay] should probably not be used"
name: autoplay
category: Warnings
---

### Description
A time-based media like `<audio>` or `<video>` should not `[autoplay]`, because it can be quite surprising for the user.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#4.10>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#13.8>
* <https://www.w3.org/TR/WCAG22/#audio-control>
* <http://www.punkchip.com/autoplay-is-bad-for-all-users/>

### Selector
```css
video[autoplay],
audio[autoplay]
```

### Test
``` html
<video autoplay controls src=""></video><span>†</span>
```
*/
video[autoplay],
audio[autoplay] {
	@include warning('autoplay', $self-closing: true);
}


/*doc
---
title: "[controls] would be helpful"
name: controls
category: Warnings
---

### Description
A time-based media like `<audio>` or `<video>` would be easier to use if `[controls]` are activated for the user.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#4.11>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#4.12>
* <https://www.w3.org/TR/WCAG22/#audio-description-or-media-alternative-prerecorded>
* <https://www.w3.org/TR/WCAG22/#keyboard>
* <https://www.w3.org/TR/WCAG22/#no-keyboard-trap>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G4>

### Selector
```css
video:not([controls]),
audio:not([controls])
```

### Test
``` html
<video src=""></video><span>†</span>
```
*/
video:not([controls]),
audio:not([controls]) {
	@include warning('controls', $self-closing: true);
}


/*doc
---
title: "Most of DOM nodes shouldn't be :empty"
name: empty-nodes
category: Warnings
---

### Description
Obviously void elements are empty, as well as `<iframe>` and `<textarea>` could be `:empty`.
Any other `:empty` tag that is not hidden is probably useless, and should be deleted.

Please note that it's disabled for tags owning a source through `[src]`. It's pretty opinionated,
but it's meant to avoid false positives on tags such as `<video>` or `<audio>` which may be
empty if they have at least one source specified through `[src]`.

###Notes

* This test only targets tags in `<body>`, since most of head's tags should be empty.
* `<button>` and `<a>` are also excluded since `button:empty` and `a:empty` are both covered by their own error.

We could use the `:blank` pseudo-class, but at this time its support is very poor. We could also use the `:-moz-only-whitespace` pseudo-class, but support is limited to Firefox and thus could invalidate our selectors stack…

### References
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L243>
* <https://html.spec.whatwg.org/multipage/syntax.html#void-elements>
* <https://drafts.csswg.org/selectors-4/#the-blank-pseudo>
* <https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-only-whitespace>
* <https://css-tricks.com/almanac/selectors/b/blank/>

### Selector
```css
body *:empty:not([hidden], [aria-hidden], [src], button, a, iframe, textarea, area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr, title)
```

### Test
``` html
<p id="empty-node_code"></p>
```
*/
/**
 * 1. An empty tag without dimensions isn't hoverable :/
 * @note Won't do anything for inline elements.
 */
body *:empty:not([hidden], [aria-hidden], [src], button, a, iframe, textarea, area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr, title) {
	@include warning('empty-nodes');
	/* 1 */
	min-height: 1px;
	min-width: 1px;
}

svg *:empty:not(title, desc, [hidden], [aria-hidden], [src], button, a, iframe, textarea, area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr) {
	@extend %a11y-reset;
}


/*doc
---
title: "A single line table may be used for layout"
name: table-layout
category: Warnings
---

### Description
A lonely `<tr>` can be a symptom of a table used for layout.
Should be double checked!

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#5.3>
* <https://www.w3.org/TR/WCAG22/#meaningful-sequence>

### Selector
```css
table:not([role="presentation"]) > tr:only-child,
table:not([role="presentation"]) > tbody > tr:only-child
```

### Test
``` html
<table>
	<caption>I'm a caption :3</caption>
	<thead>
		<tr>
			<th scope="col">Oh boy…</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>I'm a poor lonesone table-roooow!</td>
		</tr>
	</tbody>
</table>
```
*/
table:not([role="presentation"]) > tr:only-child,
table:not([role="presentation"]) > tbody > tr:only-child {
	@include warning('table-layout');
}


/*doc
---
title: "Nested tables"
name: nested-table
category: Warnings
---

### Description
There's no good reason to nest data tables: thus it probably means we're facing a layout table…

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#5.3>
* <https://www.w3.org/TR/WCAG22/#meaningful-sequence>
* <https://www.w3.org/WAI/tutorials/tables/tips/>
* <https://github.com/karlgroves/diagnostic.css/blob/39ede15ff46bd59af9f8f30efb04cbb45b6c1ba5/diagnostic.css#L175>

### Selector
```css
table table
```

### Test
``` html
<table>
	<caption>I'm a caption :3</caption>
	<thead>
		<tr>
			<th scope="col">Oh boy…</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>I'm a table-cell!</td>
		</tr>
		<tr>
			<td>
				<table>
					<caption>I'm a caption too!</caption>
					<thead>
						<tr>
							<th scope="col">Oh boy…</th>
						</tr>
					</thead>
					<tbody>
						<tr>
							<td>I'm a table-cell!</td>
						</tr>
						<tr>
							<td>I'm a table-cell!</td>
						</tr>
					</tbody>
				</table>
			</td>
		</tr>
	</tbody>
</table>
```
*/
table table {
	@include warning('nested-table');
}


/*doc
---
title: "Every data table must have a caption"
name: table-caption
category: Warnings
---

### Description
`<caption>` is needed for data `<table>`.
And it must be the `:first-child`, by the way.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#5.4>
* <https://www.w3.org/TR/WCAG22/#info-and-relationships>
* <https://html.spec.whatwg.org/multipage/tables.html#the-caption-element>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H39>
* <https://github.com/imbrianj/debugCSS/blob/e04b489388870dd214aa1c1c1a07f6811210c8ef/debugCSS.css#L309>

### Selector
```css
table:not([role="presentation"]) > caption:not(:first-child),
table:not([role="presentation"]) > *:first-child:not(caption)
```

### Test
``` html
<table>
	<thead>
		<tr>
			<th id="th-one">I'm a table without a caption!</th>
			<th id="th-two">I'm a table without a caption!</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td colspan="2" headers="th-one th-two">I'm a table without a caption!</td>
		</tr>
		<tr>
			<td colspan="2" headers="th-one th-two">I'm a table without a caption!</td>
		</tr>
	</tbody>
</table>
```
*/
table:not([role="presentation"]) > caption:not(:first-child),
table:not([role="presentation"]) > *:first-child:not(caption) {
	@include warning('table-caption');
}


/*doc
---
title: "Invalid table structure"
name: table-structure
category: Warnings
---

### Description
`<thead>`, `<tfoot>` and `<tbody>` must be in this order.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.2>
* <https://www.w3.org/TR/WCAG22/#parsing>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://github.com/imbrianj/debugCSS/blob/e04b489388870dd214aa1c1c1a07f6811210c8ef/debugCSS.css#L314>

### Selector
```css
table > tfoot ~ thead,
table > tbody ~ tfoot,
table > tbody ~ thead,
table > tfoot ~ colgroup,
table > tbody ~ colgroup,
table > tbody ~ colgroup
```

### Test
``` html
<table>
	<caption>I'm a caption</caption>
	<thead>
		<tr>
			<th scope="col">Where's my foot?</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>I'm a table with tfoot done wrong.</td>
			<td>I'm a table with tfoot done wrong.</td>
		</tr>
		<tr>
			<td>I'm a table with tfoot done wrong.</td>
			<td>I'm a table with tfoot done wrong.</td>
		</tr>
	</tbody>
	<tfoot>
		<th id="th-1">I'm a table with tfoot done wrong.</th>
		<th id="th-2">I'm a table with tfoot done wrong.</th>
	</tfoot>
</table>
```
*/
table > tfoot ~ thead,
table > tbody ~ tfoot,
table > tbody ~ thead,
table > tfoot ~ colgroup,
table > tbody ~ colgroup,
table > tbody ~ colgroup {
	@include warning('table-structure');
}


/*doc
---
title: "Missing head for data table"
name: missing-thead
category: Warnings
---

### Description
`<thead>` is strongly needed if `<tbody>` is present.

### Selector
```css
table:not([role="presentation"]) > caption + tbody,
table:not([role="presentation"]) > tbody:first-child
```

### Test
``` html
<table>
	<caption>Missing thead</caption>
	<tbody>
		<tr>
			<td>I'm a table without thead.</td>
			<td>I'm a table without thead.</td>
		</tr>
		<tr>
			<td>I'm a table without thead.</td>
			<td>I'm a table without thead.</td>
		</tr>
	</tbody>
</table>
```
*/
table:not([role="presentation"]) > caption + tbody,
table:not([role="presentation"]) > tbody:first-child {
	@include warning('missing-thead');
}


/*doc
---
title: "th without [scope] or [id]"
name: th-no-scope
category: Warnings
---

### Description
`<th>` strongly needs an `[id]` or a `[scope]`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#5.7>
* <https://www.w3.org/TR/WCAG22/#info-and-relationships>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H43>

### Selector
```css
th:not([scope], [id])
```

### Test
``` html
<table>
	<caption>Need for a [scope] or [id]</caption>
	<thead>
		<tr>
			<th>I'm a th without [scope] or [id].</th>
			<th scope="col">I'm a th with [scope].</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>I'm a td missing something.</td>
			<td>I'm a td missing something.</td>
		</tr>
		<tr>
			<td>I'm a td feeling well.</td>
			<td>I'm a td feeling well.</td>
		</tr>
	</tbody>
</table>
```
*/
th:not([scope], [id]) {
	@include warning('th-no-scope');
}


/*doc
---
title: "spacer.gif used"
name: spacer-gif
category: Warnings
---

### Description
Believe me, this still have to be tested.

### References
* <https://www.la-grange.net/2015/03/11/visible>

### Selector
```css
img[src*="1px.gif"]:not([role="presentation"]),
img[src*="1x1.gif"]:not([role="presentation"]),
img[src*="clear.gif"]:not([role="presentation"]),
img[src*="spacer.gif"]:not([role="presentation"]),
img[src*="dotclear.gif"]:not([role="presentation"]),
img[src*="transparent.gif"]:not([role="presentation"]),
img[src*="pixel-1x1-clear.gif"]:not([role="presentation"])
```

### Test
``` html
<img src="/static/spacer.gif" alt="Spacer.gif" width="100" height="100"/><span>†</span>
```
*/
img[src*="1px.gif"]:not([role="presentation"]),
img[src*="1x1.gif"]:not([role="presentation"]),
img[src*="clear.gif"]:not([role="presentation"]),
img[src*="spacer.gif"]:not([role="presentation"]),
img[src*="dotclear.gif"]:not([role="presentation"]),
img[src*="transparent.gif"]:not([role="presentation"]),
img[src*="pixel-1x1-clear.gif"]:not([role="presentation"]) {
	@include warning('spacer-gif', $self-closing: true);
}


/*doc
---
title: "Bad computed value"
name: oops
category: Warnings
---

### Description
Don't laugh, shit happens.

### Selector
```css
[id*="NaN"],
[id*="null"],
[class*="NaN"],
[class*="null"],
[id*="undefined"],
[class*="undefined"]
```

### Test
``` html
<p class="undefined">Oups, something went wrong.</p>
```
*/
[class*="NaN"],
[class*="null"],
[class*="undefined"] {
	@include warning('undefined-class');

	@include void-tags {
		@include warning('undefined-class', $self-closing: true);
	}
}

[id*="NaN"],
[id*="null"],
[id*="undefined"] {
	@include warning('undefined-id');

	@include void-tags {
		@include warning('undefined-id', $self-closing: true);
	}
}

/*doc
---
title: "JS [href]"
name: href-js
category: Warnings
---

### Description
The `[href]` attribute should not start with "javascript".
Should probably be a `<button>` or at least a `[role="button"]`, don't you think?
The only exception shall be bookmarklets.

### References
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L165>

### Selector
```css
a[href^="javascript"]:not([role="button"])
```

### Test
``` html
<a href="javascript:(function(){a11ycss=document.createElement('LINK');a11ycss.href='https://rawgit.com/ffoodd/a11y.css/master/css/a11y-en.css';a11ycss.rel='stylesheet';a11ycss.media='all';document.body.appendChild(a11ycss);})();">Please use my bookmarklet ;)</a>
```
*/
a[href^="javascript"]:not([role="button"]) {
	@include warning('href-js');
}


/*doc
---
title: "# [href]"
name: empty-href
category: Warnings
---

### Description
The `[href]` attribute is only containing `#`.
Should probably be a `<button>` or at least a `[role="button"]`, don't you think?

### References
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L165>

### Selector
```css
a[href="#"]:not([role="button"])
```

### Test
``` html
<a href="#">Oh boy, I don't mean anything</a>
```
*/
a[href="#"]:not([role="button"]) {
	@include warning('empty-href');
}


/*doc
---
title: "[style] attribute"
name: style-attr
category: Warnings
---

### Description
Your styles should be driven by a CSS file. That's it.
And no, JS shouldn't manipulate styles: it's better to play with classes, for example.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#10.1>
* <https://www.w3.org/TR/WCAG22/#info-and-relationships>
* <https://www.w3.org/TR/WCAG22/#meaningful-sequence>

### Selector
```css
[style]
```

### Test
``` html
<div style="color: red;">I'm red. I really feel dirty.</div>
```
*/
[style] {
	@include warning('style-attr');

	@include void-tags {
		@include warning('style-attr', $self-closing: true);
	}
}


/*doc
---
title: "Missing [aria-level]"
name: no-aria-level
category: Warnings
---

### Description
Though `[aria-level]` is not required by ARIA specification, it's actually better to specify it.

### References
* <https://www.w3.org/TR/wai-aria-1.3/#aria-level>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#9.1>
* <https://github.com/DISIC/rgaa_methodologie/blob/master/Check-css/check-heading.css>
* <https://www.w3.org/TR/wai-aria-1.3/#heading>
* <https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA12>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G141>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H42>

### Selector
```css
[role="heading"]:not([aria-level])
```

### Test
``` html
<strong role="heading">Heading with undefined level</strong>
```
*/
[role="heading"]:not([aria-level]) {
	@include warning('no-aria-level');
}


/*doc
---
title: "A label without a [for] attribute"
name: no-for
category: Warnings
---

### Description
A `<label>` is labelling something, in theory.
Although implicitly labelling form controls is accepted, it's probably better to double-check that form control is *really* nested in its `<label>`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.1.2>
* <https://github.com/DISIC/rgaa_referentiel_en/blob/44e2bee0c710e37ca49901b1e6b8fae9b553fd5d/criteria.html#L3981>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H44>
* <https://www.w3.org/WAI/tutorials/forms/labels/>
* <https://make.wordpress.org/accessibility/2017/01/16/testing-form-functionality-with-different-assistive-technology/>
* <https://www.w3.org/TR/WCAG22/#labels-or-instructions>
* <https://www.w3.org/TR/WCAG22/#headings-and-labels>
* <https://www.w3.org/TR/WCAG22/#info-and-relationships>

### Selector
```css
label:not([for])
```

### Test
``` html
<label>Guess what?</label>
```
*/
label:not([for]) {
	@include warning('no-for');
}


/*doc
---
title: "Mismatching [dir] and [lang] attributes"
name: mismatched-dir
category: Warnings
---

### Description
Some languages — like Arabic or Hebrew — requires a text direction switch usin `[dir="rtl"]`, as default text direction is left-to-right.
This also requires to check any in-page language change (marked up with `[lang]`) in Arabic or Hebrew content to define `[dir]` too.

### References
* <https://alphagov.github.io/accessibility-tool-audit/test-cases.html#languageofcontent>
* <https://www.w3.org/International/questions/qa-html-dir>
* <https://www.w3.org/International/articles/inline-bidi-markup/#dirattribute>
* <https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute>

### Selector
```css
[lang="ar"]:not([dir="rtl"]),
[lang="he"]:not([dir="rtl"]),
[lang="ar"] [lang]:not([dir="ltr"]),
[lang="he"] [lang]:not([dir="ltr"]),
[dir="rtl"]:not([lang="ar"], [lang="he"])
```

### Test
``` html
<p dir="rtl" lang="en">Well, I'm kinda disoriented…</p>
```
*/
[lang="ar"]:not([dir="rtl"]),
[lang="he"]:not([dir="rtl"]),
[lang="ar"] [lang]:not([dir="ltr"]),
[lang="he"] [lang]:not([dir="ltr"]),
[dir="rtl"]:not([lang="ar"], [lang="he"]) {
	@include warning('mismatched-dir');
}
