@charset "UTF-8";

/*doc
---
title: "Attribute should not contain whitespace"
name: attribute-whitespace
category: Errors
---

### Description
Some HTML attributes should not contain any whitespace —namely `[id]`, `[lang]` and `map[name]`.

### Reference
* <https://html.spec.whatwg.org/#the-id-attribute>
* <https://html.spec.whatwg.org/#the-map-element>

### Selector
```css
[id*=" "],
[lang*=" "],
map[name*=" "]
```

### Test
```html
<p id="my id">This is my beautiful element with an ID</p>
```
*/
[id*=" "],
[lang*=" "],
map[name*=" "] {
	@include error('attribute-whitespace');

	@include void-tags {
		@include error('attribute-whitespace', $self-closing: true);
	}
}


/*doc
---
title: "[tabindex] > 0"
name: tab-order
category: Errors
---

### Description
The `[tabindex]` attribute should never be greater than 0.

### References
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L337>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F44>
* <https://www.scottohara.me/blog/2019/05/25/tabindex.html>

### Selector
```css
[tabindex]:not([tabindex="0"], [tabindex^="-"])
```

### Test
```html
<button tabindex="1" type="button">Positive tabindex is bad</button>
```
*/
[tabindex]:not([tabindex="0"], [tabindex^="-"]) {
	@include error('tab-order');

	@include void-tags {
		@include error('tab-order', $self-closing: true);
	}
}


/*doc
---
title: "Empty [href]"
name: empty-href
category: Errors
---

### Description
The `[href]` attribute, if present, should not be empty. A link *to* something, right?

### References
* <https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L161>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L165>

### Selector
```css
a[href=""],
a[href=" "]
```

### Test
```html
<a href=" ">Who am I? Where do I link?</a>
```
*/
a[href=""],
a[href=" "] {
	@include error('empty-href');
}


/*doc
---
title: "Empty link"
name: empty-link
category: Errors
---

### Description
An empty link should have a label, within `[title]`, `[aria-label]` or targeted by `[aria-labelledby]`.
By the way, why would you use an empty link?

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#6.2>
* <https://www.w3.org/TR/WCAG22/#non-text-content>
* <https://www.w3.org/TR/WCAG22/#link-purpose-in-context>
* <https://www.w3.org/TR/WCAG22/#link-purpose-link-only>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H30>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G91>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L193>

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

### Test
``` html
<a href="/" class="inbl w-20" id="empty-link_code"></a>
```
*/
a:empty[title=""],
a:empty[aria-label=""],
a:empty[aria-labelledby=""],
a:empty:not([title], [aria-label], [aria-labelledby]) {
	@include error('empty-link');
}


/*doc
---
title: "Missing alternative for img"
name: no-alt
category: Errors
---

### Description
An `<img>` must have an `[alt]`. Always.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#1.1>
* <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/H36>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H37>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H24>
* <https://www.w3.org/WAI/WCAG22/Techniques/failures/F65>

### Selector
```css
img[alt=" "],
area[alt=" "],
input[type="image"][alt=" "],
img:not([alt]),
area:not([alt]),
input[type="image"]:not([alt])
```

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


/*doc
---
title: "Missing label for [role=img]"
name: no-aria-label
category: Errors
---

### Description
`[role=img]` without `[aria-hidden=true]` should either have `[aria-label]` or `[aria-labelledby]`.
If image is decorative, please use `[role=presentation]` instead.

### References
* <https://www.w3.org/TR/wai-aria-1.3/#img>
* <https://www.w3.org/TR/WCAG22/#non-text-content>
* <https://www.w3.org/WAI/tutorials/images/decision-tree/>
* <https://www.w3.org/TR/wai-aria-1.3/#presentation>

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

### Test
``` html
<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>
```
*/
[role="img"]:not([aria-hidden="true"], [aria-label], [aria-labelledby]) {
	@include error('no-aria-label');
}

svg[role="img"]:not([aria-hidden="true"], [aria-label], [aria-labelledby]) {
	@include error('no-aria-label', $self-closing: true);
}


/*doc
---
title: "Missing source for img"
name: no-src
category: Errors
---

### Description
An `<img>` must have an `[src]` or an `[srcset]`, and it should be a valid one. Obviously.

### References
* <https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-src>
* <https://scottjehl.github.io/picturefill/>

### Selector
```css
img:not([src], [srcset]),
img[src=""],
img[src=" "],
img[src="#"],
img[src="/"],
img[srcset=""],
img[srcset=" "],
img[srcset="#"],
img[srcset="/"],
input[type="image"]:not([src], [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
``` html
<img alt="Missing src" width="144" height="144"/>
```
*/
img:not([src], [srcset]),
input[type="image"]:not([src], [srcset]) {
	@include error('no-src');
}


img[src=""],
img[src=" "],
img[src="#"],
img[src="/"],
input[type="image"][src=""],
input[type="image"][src=" "],
input[type="image"][src="#"],
input[type="image"][src="/"] {
	@include error('bad-src');
}

img[srcset=""],
img[srcset=" "],
img[srcset="#"],
img[srcset="/"],
input[type="image"][srcset=""],
input[type="image"][srcset=" "],
input[type="image"][srcset="#"],
input[type="image"][srcset="/"] {
	@include error('bad-srcset');
}


/*doc
---
title: "A label with an empty [for] attribute"
name: empty-for
category: Errors
---

### Description
A `<label>` with a `[for]` attribute should label something with an `[id]` attribute, obviously.

### 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[for=""],
label[for=" "]
```

### Test
``` html
<label for=" ">Guess what?</label>
```
*/
label[for=""],
label[for=" "] {
	@include error('empty-for');
}


/*doc
---
title: "Missing some kind of label"
name: no-id
category: Errors
---

### Description
How to label a field? You have a few choices: `[id]`, `[title]`, `[aria-label]` and `[aria-labelledby]`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.1>
* <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>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H44>

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

### Test
``` html
<input type="text" /><span>†</span>
```
*/
input:not([type="button"], [type="submit"], [type="hidden"], [type="reset"], [type="image"], [id], [aria-label], [title], [aria-labelledby]),
textarea:not([id], [aria-label], [aria-labelledby]),
select:not([id], [aria-label], [aria-labelledby]) {
	@include error('no-id', $self-closing: true);
}


/*doc
---
title: "Missing a value"
name: no-value
category: Errors
---

### Description
How to label a `[reset]`, `[submit]` or `[button]` type input?
You still have a few choices: `[value]`, `[title]`, `[aria-label]` and `[aria-labelledby]`.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.9>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H91>

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

### Test
``` html
<input type="submit" /><span>†</span>
```
*/
input[type="reset"]:not([value], [title], [aria-label], [aria-labelledby]),
input[type="submit"]:not([value], [title], [aria-label], [aria-labelledby]),
input[type="button"]:not([value], [title], [aria-label], [aria-labelledby]) {
	@include error('no-value', $self-closing: true);
}


/*doc
---
title: "Empty button"
name: empty-button
category: Errors
---

### Description
A `<button>` should either have content or an `[aria-label]`, `[aria-labelledby]` or `[title]`. Those attributes, if present, should not be empty.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.9>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H91>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L193>

### Selector
```css
button:empty:not([aria-label], [aria-labelledby], [title])
```

### Test
``` html
<button type="button"></button>
```
*/
button:empty:not([aria-label], [aria-labelledby], [title]) {
	@include error('empty-button');
}


/*doc
---
title: "Empty button attribute"
name: empty-button-attr
category: Errors
---

### Description
`[aria-label]`, `[aria-labelledby]` or `[title]` on a `<button>` must not be empty.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.9>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H91>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L193>

### Selector
```css
button[title=""],
button[aria-label=""],
button[aria-labelledby=""]
```

### Test
``` html
<button title="" type="button">Test</button>
```
*/
button[title=""] {
	@include error('empty-button-title');
}

button[aria-label=""] {
	@include error('empty-button-aria-label');
}

button[aria-labelledby=""] {
	@include error('empty-button-aria-labelledby');
}


/*doc
---
title: "Form button"
name: not-form-button
category: Errors
---

### Description
A `<button>` has a defaut `[type]` value of `"submit"`, in order to send a `<form>`.

However outside a form, if it's intended to send a form it should mention it with one of those attributes: `[form]`, `[formaction]`, `[formtarget]`.

If it doesn't submit anything, it should have the `[type="button"]`.

### References
* <https://html.spec.whatwg.org/multipage/forms.html#the-button-element>
* <https://github.com/Heydon/REVENGE.CSS/blob/master/revenge.css#L189>

### Selector
```css
button:not([type], [form], [formaction], [formtarget])
```

### Test
``` html
<button>I just don't know what todo with myself</button>
```
*/
button:not([type], [form], [formaction], [formtarget]) {
	@include error('not-form-button');
}

form button:not([type], [form], [formaction], [formtarget]) {
	@extend %a11y-reset;
}

/*doc
---
title: "Button not submitting"
name: not-submit-button
category: Errors
---

### Description
If a `<button>`'s`[type]` is either `"reset"` or `"button"`, it should not use the following attributes:
* `[formmethod]`;
* `[formaction]`;
* `[formtarget]`;
* `[formenctype]`;
* `[formnovalidate]`.

### References
* <https://html.spec.whatwg.org/multipage/forms.html#the-button-element>

### Selector
```css
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
``` html
<button type="button" formmethod="GET">I have a method!</button>
```
*/
button[type="reset"],
button[type="button"] {
	&[formmethod],
	&[formaction],
	&[formtarget],
	&[formenctype],
	&[formnovalidate] {
		@include error('not-submit-button');
	}
}

/*doc
---
title: "Disabled button"
name: disabled-button
category: Errors
---

### Description
A `<button>` styled to be disabled should be disabled *for real*.
Use `[disabled]` and `[readonly]`.

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

### Selector
```css
button[class*="disabled"]:not([disabled], [readonly])
```

### Test
``` html
<button class="is-disabled" type="button">To be or not to be (disabled)?</button>
```
*/
button[class*="disabled"]:not([disabled], [readonly]) {
	@include error('disabled-button');
}

/*doc
---
title: "input without [type]"
name: no-type
category: Errors
---

### Description
`<input>` needs a `[type]` in order to tell the user what kind of data is wanted.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.11>
* <https://www.w3.org/TR/WCAG22/#error-suggestion>

### Selector
```css
input:not([type]),
input[type=" "],
input[type=""]
```

### Test
``` html
<label for="No-type">No type</label>
<input value="Whatever you want" id="No-type"/><span>†</span>
```
*/
input:not([type]),
input[type=" "],
input[type=""] {
	@include error('no-type', $self-closing: true);
}


/*doc
---
title: "optgroup without label"
name: optgroup
category: Errors
---

### Description
`<optgroup>` needs a `[label]` to explain what's inside the group.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.8>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H85>
* <https://www.w3.org/TR/2014/NOTE-WCAG20-TECHS-20140916/H85>

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

### Test
``` html
<form action="/">
	<label for="optgroup-test">Oh, hey</label>
	<select id="optgroup-test">
		<optgroup label="I'm a group">
			<option value="1">I'm an option</option>
			<option value="2">I'm another option</option>
		</optgroup>
		<optgroup>
			<option value="3">I'm an option, but from another group</option>
			<option value="4">I'm another option, still from another group</option>
		</optgroup>
	</select>
</form>
```
*/
optgroup:not([label]) {
	@include error('optgroup', $self-closing: true);
}


/*doc
---
title: "iframe without [title]"
name: no-title
category: Errors
---

### Description
`<iframe>` needs a `[title]` in order to tell the user what to expect inside the iframe.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#2.1>
* <https://www.w3.org/TR/WCAG22/#name-role-value>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H64>

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

### Test
``` html
<iframe srcdoc="<!DOCTYPE html><title>Missing [title]</title>"></iframe><span>†</span>
```
*/
iframe:not([title]),
iframe[title=" "],
iframe[title=""] {
	@include error('no-title', $self-closing: true);
}


/*doc
---
title: "form missing an [action]"
name: no-action
category: Errors
---

### Description
`<form>` should do something, isnt'it? Well, `[action]` is meant to define what.

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

### Selector
```css
form:not([action]),
form[action=" "],
form[action=""]
```

### Test
``` html
<form>
	<label for="input">Guess what do we do with your datas?</label>
	<input id="input" type="text" />

	<input type="submit" value="No idea, huh?"/>
</form>
```
*/
form:not([action]),
form[action=" "],
form[action=""] {
	@include error('no-action');
}


/*doc
---
title: "No valid language defined"
name: no-lang
category: Errors
---

### Description
`<html>` must indicate to User Agents the human language used in the document.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.3>
* <https://accessibilite.numerique.gouv.fr/methode/glossaire/#langue-par-defaut>
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.4>
* <https://www.w3.org/TR/WCAG22/#language-of-page>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H57>
* <https://html.spec.whatwg.org/#attr-lang>
* <https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang>
* <https://www.w3.org/WAI/WCAG22/Understanding/language-of-page>
* <https://www.w3.org/WAI/WCAG22/Understanding/language-of-parts.html>
* <https://www.matuzo.at/blog/lang-attribute/>
* <https://codepen.io/matuzo/project/editor/ZyrVee>

### Selector
```css
html:not([lang]),
html[lang*=" "],
html[lang=""]
```

### Test
``` html
<iframe title="No language defined example" 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>
```
*/
html:not([lang]),
html[lang*=" "],
html[lang=""] {
	@include error('no-lang');
}


/*doc
---
title: "table used for layout"
name: table-for-layout
category: Errors
---

### Description
`<table>` may be used for layout if a [role="presentation"] is added.
However, semantics tags and attributes aiming to organize datas mustn't be used. Here's a list:
* `<th>`;
* `<thead>`;
* `<tfoot>`;
* `<caption>`;
* `[axis]`;
* `[scope]`;
* `[headers]`;
* `[colgroup]`.

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

### Selector
```css
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
``` html
<table role="presentation">
	<caption>I do not mean anything!</caption>
	<tbody>
		<tr>
			<td colspan="2">It works</td>
		</tr>
	</tbody>
</table>
```
*/
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] {
	@include error('table-for-layout');
}


/*doc
---
title: "[width] & [height] attributes"
name: dimensions
category: Errors
---

### Description
`[width]` and `[height]` are presentation informations.
Therefore it shouldn't be used in markup, except for a few elements. Use CSS instead.

### References
* <https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#10>
* <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
:not(img, object, embed, svg, canvas, picture > source, iframe)[width],
:not(img, object, embed, svg, canvas, picture > source, iframe)[height]
```

### Test
``` html
<p width="20">Damned! I feel sooo strait :(</p>
```
*/
:not(img, object, embed, svg, canvas, picture > source, iframe)[width],
:not(img, object, embed, svg, canvas, picture > source, iframe)[height] {
	@include error('dimensions');

	@at-root #{selector-unify($void-tags-dimensions, &)} {
		@include error('dimensions', $self-closing: true);
	}
}


/*doc
---
title: "Javascript events attributes"
name: js-events
category: Errors
---

### Description
Javascript event attributes (such as `[onmouseover]`) should not be used.
Prefer either CSS pseudo-classes (`:hover`, `:focus`, `:active`, etc.) or JS event listeners.

### References
* <https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes>
* <https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener>

### Selector
```css
[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
``` html
<span onclick="alert('You clicked!');">Click click click</span>
```
*/
[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] {
	@include error('js-events');
}


/*doc
---
title: "Namespaces"
name: namespace
category: Errors
---

### Description
Did you know that some characters should be avoided as first characters in class names and identifiers?
Yep. Digits, two hyphens, or hyphen followed by a digit.

### References
* <https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#w3cselgrammar>
* <https://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/>
* <https://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/tests/css3-modsel-175a.html>

### Selector
```css
[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
``` html
<div id="2">Hello! My ID is 2.</div>
```
*/
[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"] {
	@include error('id-namespace');
}

[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"] {
	@include error('class-namespace');
}


/*doc
---
title: "Empty title tag"
name: no-page-title
category: Errors
---

### Description
The `<title>` tag is the first thing read aloud by screen readers — to announce the page&hellip; title — and also the first thing displayed on search engines' results pages.

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://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#8.5>
* <https://accessibilite.numerique.gouv.fr/methode/glossaire/#titre-de-page>
* <https://html.spec.whatwg.org/multipage/semantics.html#the-title-element>
* <https://www.w3.org/TR/WCAG22/#page-titled>
* <https://www.w3.org/WAI/WCAG22/quickref/#page-titled>
* <https://www.w3.org/WAI/WCAG22/Understanding/page-titled.html>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G88>
* <https://www.w3.org/WAI/WCAG22/Techniques/general/G127>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H25>
* <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
title:empty
```

### Test
``` html
<title></title>
```
*/
title:empty {
	@include error('no-page-title');
	@include a11y-head;
}


/*doc
---
title: "Unaccessible viewport attribute"
name: unaccessible-viewport
category: Errors
---

### Description
User should be able to zoom in or out the page to improve readability and comfort; this is usually allowed by the viewport `<meta>`.

### References
* <https://bitsofco.de/linting-html-using-css/>
* <https://dequeuniversity.com/rules/axe/2.1/meta-viewport>
* <https://www.w3.org/TR/WCAG22/#resize-text>
* <https://www.w3.org/WAI/WCAG22/Understanding/resize-text.html>
* <https://www.accede-web.com/notices/html-et-css/bonnes-pratiques/ne-pas-brider-le-zoom-avec-la-propriete-user-scalable/>
* <https://adrianroselli.com/2015/10/dont-disable-zoom.html>

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

### Test
``` html
<iframe title="Wrong viewport instruction example" srcdoc="<!DOCTYPE html>
	<html lang='en'>
		<head>
			<meta charset='utf-8'/>
			<title>Wrong viewport instruction</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>Wrong <code>viewport</code> instruction</h1>">
</iframe>
```
*/
meta[name="viewport"][content*="maximum-scale"],
meta[name="viewport"][content*="minimum-scale"],
meta[name="viewport"][content*="user-scalable=no"] {
	@include error('unaccessible-viewport', $self-closing: true, $head: true);
	@include a11y-head($self-closing: true);
}


/*doc
---
title: "Incorrect charset"
name: incorrect-charset
category: Errors
---

### Description
Using `utf-8` character encoding is recommended by the W3C itself:
> supports many languages and can accommodate pages and forms in any mixture of those languages.

Moreover it avoids some security issues exploiting some other charsets…

### References
* <https://bitsofco.de/linting-html-using-css/#incorrectcharacterset>
* <https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-charset>
* <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta>
* <https://validator.w3.org/docs/help.html#faq-charset>
* <https://www.w3.org/TR/WCAG22/#readable>
* <https://validator.w3.org/i18n-checker/>
* <https://www.w3.org/International/tutorials/tutorial-char-enc/>

### Selector
```css
meta[charset]:not([charset="utf-8"], [charset="UTF-8"])
```

### Test
``` html
<meta charset="Windows-1252"/><link>†</link>
```
*/
meta[charset]:not([charset="utf-8"], [charset="UTF-8"]) {
	@include error('incorrect-charset', $self-closing: true, $head: true);
	@include a11y-head($self-closing: true);
}


/*doc
---
title: "Charset should come first"
name: late-charset
category: Errors
---

### Description
As explained on the Mozilla Developer Network:

> The `<meta>` element declaring the encoding must be inside the `<head>` element
> and **within the first 1024 bytes** of the HTML, as some browsers only look at
> those bytes before choosing an encoding.

It's also meant to prevent an old security exploit using UTF-7. Declaring the charset
before the `<title>` tag is the simplest way to cover it.

### References
* <https://bitsofco.de/linting-html-using-css/#incorrectcharacterset>
* <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta>
* <https://html.spec.whatwg.org/multipage/semantics.html#charset>

### Selector
```css
head :first-child:not([charset])
```

### Test
``` html
<iframe title="Late charset example" 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>How am I encoded, buddy?</h1>">
</iframe>
```
*/
head :first-child:not([charset]) {
	@include error('late-charset', $self-closing: false, $head: true);
	@include a11y-head($self-closing: true);
}


/*doc
---
title: "Invalid [dir] attribute"
name: invalid-dir
category: Errors
---

### Description
The `[dir]` attribute — used to specify the element’s text directionality — only accepts three values: `rtl`, `ltr` and `auto`.

### References
* <https://github.com/karlgroves/diagnostic.css/blob/39ede15ff46bd59af9f8f30efb04cbb45b6c1ba5/diagnostic.css#L113>
* <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
[dir]:not([dir="rtl"], [dir="ltr"], [dir="auto"])
```

### Test
``` html
<p dir="wtf">Well, I'm kinda disoriented…</p>
```
*/
[dir]:not([dir="rtl"], [dir="ltr"], [dir="auto"]) {
	@include error('invalid-dir');
}


/*doc
---
title: "[accesskey] is a bad idea"
name: accesskey
category: Errors
---

### Description
The `[accesskey]` attribute is meant to implement site specific keyboard shortcuts.
This is usually a bad idea since keys might be already used by either the operating system,
the browser, browser extension and even user's settings…

This is opinionated: in a perfect world, `[accesskey]` could be used wisely. Yup. Could be.

### References
* <https://github.com/karlgroves/diagnostic.css/blob/39ede15ff46bd59af9f8f30efb04cbb45b6c1ba5/diagnostic.css#L159>
* <https://jkorpela.fi/forms/accesskey.html>
* <https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey>
* <https://html.spec.whatwg.org/multipage/interaction.html#the-accesskey-attribute>
* <https://john.foliot.ca/more-reasons-why-we-dont-use-accesskeys/>
* <https://www.alsacreations.com/article/lire/568-Accesskey-le-grand-echec-de-l-accessibilite-du-Web.html>

### Selector
```css
[accesskey]
```

### Test
``` html
<a id="key" name="key" accesskey="1">Skip to this link using <kbd>1</kbd></a>
```
*/
[accesskey] {
	@include error('accesskey');
}


/*doc
---
title: "Grouping inputs"
name: inputs-group
category: Errors
---

### Description
Inputs with a type of `radio` or `checkbox` are usually grouped. The `[name]` attribute is meant to programmatically associate them,
thus is needed.

### References
* <https://www.w3.org/WAI/tutorials/forms/grouping/>
* <https://html.spec.whatwg.org/multipage/forms.html#checkbox-state-typecheckbox>
* <https://html.spec.whatwg.org/multipage/forms.html#radio-button-state-typeradio>
* <https://html.spec.whatwg.org/multipage/forms.html#element-attrdef-formelements-name>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H71>

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

### Test
``` html
<form action="/">
	<fieldset>
		<legend>Options</legend>
		<p>
			<label for="option-1">Option N<sup>o</sup>1</label>
			<input type="radio" id="option-1"><span>†</span>
		</p>
		<p>
			<label for="option-2">Option N<sup>o</sup>2</label>
			<input type="radio" id="option-2" name="options">
		</p>
	</fieldset>
</form>
```
*/
[type="radio"]:not([name]),
[type="checkbox"]:not(:only-of-type, [name]) {
	@include error('inputs-group', $self-closing: true);
}


/*doc
---
title: "[radio] outside a fieldset"
name: radio-group
category: Errors
---

### Description
Inputs with a type of `radio` should be grouped by a parent `<fieldset>`, described by its `<legend>`.

Please note that WCAG doesn't actually require this but strongly recommends it:
"where the individual label associated with each particular control provides a sufficient description,
the use of the fieldset and legend elements is not required."

This test could be a warning…

### References
* <https://www.w3.org/WAI/tutorials/forms/grouping/#radio-buttons>
* <https://html.spec.whatwg.org/multipage/forms.html#radio-button-state-typeradio>
* <https://html.spec.whatwg.org/multipage/forms.html#element-attrdef-formelements-name>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H71>
* <https://www.w3.org/WAI/WCAG22/Techniques/html/H44>

### Selector
```css
[type="radio"]
```

### Test
``` html
<form action="/">
	<p>
		<label for="option-1">Option N<sup>o</sup>1</label>
		<input type="radio" id="option-1" name="options"><span>†</span>
	</p>

	<br>

	<fieldset>
		<legend>Trying within a fieldset, shouldn't match</legend>
		<p>
			<label for="option-2">Option N<sup>o</sup>2</label>
			<input type="radio" id="option-2" name="options"><span>†</span>
		</p>
	</fieldset>
</form>
```
*/
[type="radio"] {
	@include error('radio-group', $self-closing: true);
}

fieldset [type="radio"] {
	@extend %a11y-reset;
}


/*doc
---
title: "[role=slider] missing attributes"
name: role-slider
category: Errors
---

### Description
`[role="slider"]` requires a few attributes:

* `[aria-valuemin]`
* `[aria-valuemax]`
* `[aria-valuenow]`

Also `[aria-valuetext]` is welcome, even though it's not required by ARIA specification.

### References
* <https://github.com/imbrianj/debugCSS/blob/master/debugCSS.css#L378>
* <https://www.w3.org/TR/wai-aria-1.3/#slider>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuenow>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuemin>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuemax>
* <https://www.tpgi.com/aria-slider-part-1/>
* <https://www.tpgi.com/aria-slider-part-2/>
* <https://www.tpgi.com/aria-slider-part-3/>
* <https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role>

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

### Test
``` html
<label for="slider">Slider</label>
<input id="slider" role="slider" type="range" /><span>†</span>
```
*/
[role="slider"]:not([aria-valuemin]),
[role="slider"]:not([aria-valuemax]),
[role="slider"]:not([aria-valuenow]) {
	@include error('role-slider');

	@include void-tags {
		@include error('role-slider', $self-closing: true);
	}
}


/*doc
---
title: "[role=spinbutton] missing attributes"
name: role-spinbutton
category: Errors
---

### Description
`[role="spinbutton"]` requires a few attributes:

* `[aria-valuemin]`
* `[aria-valuemax]`
* `[aria-valuenow]`

### References
* <https://www.w3.org/TR/wai-aria-1.3/#spinbutton>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuenow>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuemin>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuemax>

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

### Test
``` html
<label for="spinbutton">Spinbutton</label>
<input id="spinbutton" role="spinbutton" type="range" /><span>†</span>
```
*/
[role="spinbutton"]:not([aria-valuemin]),
[role="spinbutton"]:not([aria-valuemax]),
[role="spinbutton"]:not([aria-valuenow]) {
	@include error('role-spinbutton');

	@include void-tags {
		@include error('role-spinbutton', $self-closing: true);
	}
}


/*doc
---
title: "[role=checkbox] missing state"
name: role-checkbox
category: Errors
---

### Description
`[role="checkbox"]` requires an attribute: `[aria-checked]`

### References
* <https://www.w3.org/TR/wai-aria-1.3/#checkbox>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-checked>

### Selector
```css
[role="checkbox"]:not([aria-checked])
```

### Test
``` html
<img src="/static/ffoodd.png" alt="Checkbox" role="checkbox" width="36" height="36"/><span>†</span>
```
*/
[role="checkbox"]:not([aria-checked]) {
	@include error('role-checkbox');

	@include void-tags {
		@include error('role-checkbox', $self-closing: true);
	}
}


/*doc
---
title: "[role=combobox] missing [state]"
name: role-combobox
category: Errors
---

### Description
`[aria-expanded]` is required on `[role="combobox"]`.

### References
* <https://www.w3.org/TR/wai-aria-1.3/#combobox>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-expanded>

### Selector
```css
[role="combobox"]:not([aria-expanded])
```

### Test
``` html
<input type="text" aria-label="Combobox" role="combobox" id="combobox"><span>†</span>
```
*/
[role="combobox"]:not([aria-expanded]) {
	@include error('role-combobox');

	@include void-tags {
		@include error('role-combobox', $self-closing: true);
	}
}


/*doc
---
title: "[role=scrollbar] required properties"
name: role-scrollbar
category: Errors
---

### Description
Some properties are required to comply the `[role="scrollbar"]` pattern:

* `[aria-controls]`
* `[aria-valuemin]`
* `[aria-valuemax]`
* `[aria-valuenow]`
* `[aria-orientation]`

### References
* <https://www.w3.org/TR/wai-aria-1.3/#scrollbar>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-controls>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuemin>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuemax>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-valuenow>
* <https://www.w3.org/TR/wai-aria-1.3/#aria-orientation>

### Selector
```css
[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
``` html
<div role="scrollbar">↓</div>
```
*/
[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]) {
	@include error('role-scrollbar');
}


/*doc
---
title: "Nested interactive elements"
name: nested-interactive
category: Errors
---

### Description
An interactive element should not be contained in another interactive element (e.g. `<a>` in `<button>`).


### 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://www.w3.org/TR/xhtml1/#prohibitions>
* <https://html.spec.whatwg.org/multipage/dom.html#interactive-content-2>
* <https://html.spec.whatwg.org/multipage/forms.html#the-form-element>
* <https://html.spec.whatwg.org/multipage/forms.html#the-progress-element>
* <https://html.spec.whatwg.org/multipage/forms.html#the-meter-element>
* <https://html.spec.whatwg.org/multipage/forms.html#the-button-element>
* <https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element>
* <https://html.spec.whatwg.org/multipage/forms.html#the-label-element>

### Selector
```css
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
``` html
<a href="https://www.ffoodd.fr">
	<button type=button">Oh wait, what should I trigger?</button>
</a>
```
*/
$tags: ();

@each $tag in $interactive {
	$tags: append($tags, unquote('a #{$tag}, button #{$tag}'), 'comma');
}

#{$tags},
form form,
label label,
meter meter,
progress progress {
	@include error('nested-interactive');
}
