Skip to content

New rule: Content triggered on hover is hoverable (ep1s13) #1396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 73 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
f109b97
Create additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 17, 2020
5c20803
Create hovered.md
carlosapaduarte Jul 17, 2020
090fbb3
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 17, 2020
393c4de
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 17, 2020
cb5b248
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 17, 2020
33c9b18
Update hovered.md
carlosapaduarte Jul 17, 2020
d0a18d4
Create visible-changes-in-content copy.md
carlosapaduarte Jul 17, 2020
6cbddb3
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 17, 2020
e223fd1
Update spelling-ignore.yml
carlosapaduarte Jul 17, 2020
234efdd
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Jul 21, 2020
94d5bb8
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Jul 24, 2020
2c2e2d3
Rename file
carlosapaduarte Jul 24, 2020
46a2d85
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 24, 2020
395db17
Create scripts.js
carlosapaduarte Jul 24, 2020
d6acc0e
Create styles.css
carlosapaduarte Jul 24, 2020
fae5c5e
Add passed example
carlosapaduarte Jul 24, 2020
4333a26
Add failed example
carlosapaduarte Jul 24, 2020
0d80d3b
Update scripts.js
carlosapaduarte Jul 24, 2020
d1c5415
Add inapplicable example
carlosapaduarte Jul 24, 2020
39dd0b9
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Jul 24, 2020
6385d29
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Sep 3, 2020
fbc3aa9
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Sep 28, 2020
58c7d33
Updated description and assumptions
carlosapaduarte Sep 28, 2020
fec59f6
Merge branch 'content-triggered-on-hover-is-hoverable-ep1s13' of http…
carlosapaduarte Sep 28, 2020
6762af2
Update visible-changes-in-content.md
carlosapaduarte Oct 8, 2020
ff84c74
Update visible-changes-in-content.md
carlosapaduarte Oct 9, 2020
8916e70
fix test
carlosapaduarte Oct 9, 2020
c0ea1e0
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Oct 26, 2020
b464dae
New definition and changes to the applicability
carlosapaduarte Oct 26, 2020
8cb273e
Update assumption
carlosapaduarte Oct 27, 2020
c1d16c9
Create distinguishable-styles.md
carlosapaduarte Oct 27, 2020
71a73d8
Delete distinguishable-styles.md
carlosapaduarte Oct 27, 2020
e31b821
Create contained-area.md
carlosapaduarte Oct 27, 2020
527f9cd
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Oct 27, 2020
45c552f
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Oct 27, 2020
050a60d
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Nov 3, 2020
a693b76
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Nov 3, 2020
bf5528c
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Nov 9, 2020
35d92db
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Nov 16, 2020
c6ed956
update examples
carlosapaduarte Nov 16, 2020
8d6c6bc
updated expectation
carlosapaduarte Nov 16, 2020
4cb492d
update script for new example
carlosapaduarte Nov 16, 2020
f5ce160
Create styles_menu.css
carlosapaduarte Nov 16, 2020
e8b272d
new passed example
carlosapaduarte Nov 16, 2020
2a36383
Update spelling-ignore.yml
carlosapaduarte Nov 19, 2020
5994410
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Nov 24, 2020
fdfca64
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Nov 25, 2020
9eae6f9
Back to changes of pixels in the page
carlosapaduarte Nov 25, 2020
70eb886
Update area-affected-visible-changes.md
carlosapaduarte Nov 25, 2020
f2c882f
timer for applicabiltiy and expectation
carlosapaduarte Nov 25, 2020
db0d914
correct link to definition
carlosapaduarte Nov 25, 2020
f86a116
remove no longer used definitions
carlosapaduarte Dec 2, 2020
40618d3
new definitions
carlosapaduarte Dec 2, 2020
e06744e
Remove unused defintions
carlosapaduarte Dec 2, 2020
d7f0ef8
Update additional-content-triggered-on-hover-is-hoverable-ep1s13.md
carlosapaduarte Dec 2, 2020
876bab4
Remove unused definition
carlosapaduarte Dec 2, 2020
5bfaa59
Missing definitions
carlosapaduarte Dec 2, 2020
034aaab
Missing definitions and add spelling
carlosapaduarte Dec 2, 2020
5f7cf90
Spelling fix
carlosapaduarte Dec 2, 2020
74bcce6
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Dec 2, 2020
08926d1
update overlap definition
carlosapaduarte Dec 7, 2020
e6155c2
editorial fix to center definition
carlosapaduarte Dec 7, 2020
00b9758
update definition of adjacent
carlosapaduarte Dec 7, 2020
dc254c0
update definitions of content that becomes visible and invisible
carlosapaduarte Dec 7, 2020
ca18503
Update adjacent.md
carlosapaduarte Dec 16, 2020
141ff43
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Dec 16, 2020
6ccf74c
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Dec 18, 2020
d6c03c9
update definition of distance in adjacent definition
carlosapaduarte Dec 18, 2020
65e7c42
remove rounding down from center definition
carlosapaduarte Dec 18, 2020
30e6850
Update content-that-becomes-visible.md
carlosapaduarte Dec 18, 2020
996b043
Update adjacent.md
carlosapaduarte Dec 18, 2020
602745c
Merge branch 'develop' into content-triggered-on-hover-is-hoverable-e…
carlosapaduarte Jan 4, 2021
7af8cad
rewriting using states
carlosapaduarte Mar 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions __tests__/spelling-ignore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@
- presentational
- sc
- dropdown
- hoverable
- getModifierState
- accesskey
- Accesskeys
- getBoundingClientRect

# spell checker checks against strict casing & hence some repeated words here
- Autocomplete
Expand Down Expand Up @@ -207,6 +209,7 @@
- cornsilk
- subtree
- unicity
- submenu

# Parts of Unicode
- 000A
Expand Down
171 changes: 171 additions & 0 deletions _rules/additional-content-triggered-on-hover-is-hoverable-ep1s13.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
---
id: ep1s13
name: Additional content triggered on hover is hoverable
rule_type: atomic
description: |
This rule checks that any additional content that was triggered by hovering an element can be reached from that element and remains available to the user while the mouse pointer is over the element or the additional content
accessibility_requirements:
wcag21:1.4.13: # Content on Hover or Focus (AA)
forConformance: true
failed: not satisfied
passed: further testing needed
inapplicable: further testing needed
input_aspects:
- DOM Tree
- CSS Styling
- Mouse pointer
acknowledgments:
authors:
- Carlos Duarte
---

## Applicability

The rule applies to any element in a [web page][] with [content that becomes visible][].

### Applicable states (transitions?)

This rule applies if all of the following is true:

- the [content becomes visible][content that becomes visible] after the test target transitions from the not [hovered][] state to the [hovered][] state; and
- the [content becomes invisible][content that becomes invisible] after the test target transitions from the [hovered][] state to the not [hovered][] state, except if the content itself is in the [hovered][] state.

## Expectation 1

The target element's [bounding box][] is [adjacent][] or [overlaps][] the [bounding box][] of the [content that becomes visible][].

## Expectation 2

The [content that becomes visible][] remains [visible][].

Comments for reviewers: how to test this in practice? A tester will never know for sure if in the next second the content won't vanish. The previous version of the rule required this for only 1 minute (the assumption is still below).

### Expected state (transitions?)

The above expectations must hold while any of the following are true:

- the test target is in the [hovered][] state; or
- the [content that became visible][content that becomes visible] is in the [hovered][] state.

## Assumptions

- The user does not dismiss the content causing the changes in content by pressing a key on the keyboard. In this instance the rule will fail while [success criterion 1.4.13: Content on Hover or Focus][sc1.4.13] might be satisfied.
- The content that becomes visible does not become irrelevant. In this instance the rule will fail while [success criterion 1.4.13: Content on Hover or Focus][sc1.4.13] might be satisfied.
- This rule assumes that the additional content that becomes visible does not disappear after 1 minute of being triggered by the hovering event. If the content disappears after this time span the rule may pass but [Success Criterion 1.4.13: Content on Hover or Focus][sc1.4.13] is not satisfied. The arbitrary 1 minute time span, selected so that testing this rule would not be impractical, is not included in WCAG.

## Accessibility Support

_No accessibility support issues known._

## Background

- [Understanding Success Criterion 1.4.13: Content on Hover or Focus][sc1.4.13]
- [F95: Failure of Success Criterion 1.4.13 due to content shown on hover not being hoverable](https://www.w3.org/WAI/WCAG21/Techniques/failures/F95)

## Test Cases

### Passed

#### Passed Example 1

This button element causes [content to become visible][content that becomes visible] by presenting a tooltip when [hovered][]. The tooltip is [adjacent][] to the button element and remains displayed while the mouse pointer does not leave its boundaries.

```html
<link rel="stylesheet" type="text/css" href="/test-assets/ep1s13/styles.css" />
<script src="/test-assets/ep1s13/scripts.js"></script>

<body onload="bindEvents({tooltipRemains: true})">
<div class="tooltip-container">
<button aria-labelledby="tooltip">
<span>WCAG</span>
</button>
<p id="tooltip" role="tooltip" hidden>Web Content Accessibility Guidelines</p>
</div>
</body>
```

#### Passed Example 2

This list item element causes [content to become visible][content that becomes visible] by presenting a menu item when [hovered][]. The menu item is [adjacent][] to the list item element and remains displayed while the mouse pointer does not leave its boundaries.

```html
<link rel="stylesheet" type="text/css" href="test-assets/ep1s13/styles_menu.css" />
<script src="test-assets/ep1s13/scripts.js"></script>

<body onload="bindEvents({tooltipRemains: true})">
<div>
<ul class="tooltip-container">
<li>menu</li>
<div role="tooltip" hidden>
<ul class="tooltip-container">
<li>submenu</li>
<div role="tooltip" hidden>
<ul>
<li>subsubmenu</li>
</ul>
</div>
</ul>
</div>
</ul>
</div>
</body>
```

### Failed

#### Failed Example 1

This button element causes [content to become visible][content that becomes visible] by presenting a tooltip when [hovered][]. However, the tooltip is not [adjacent][] neither [overlaps][] the button.

```html
<link rel="stylesheet" type="text/css" href="/test-assets/ep1s13/stylesbad.css" />
<script src="/test-assets/ep1s13/scripts.js"></script>

<body onload="bindEvents({tooltipRemains: true})">
<div class="tooltip-container">
<button aria-labelledby="tooltip">
<span>WCAG</span>
</button>
<p id="tooltip" role="tooltip" hidden>Web Content Accessibility Guidelines</p>
</div>
</body>
```

#### Failed Example 2

This button element causes [content to become visible][content that becomes visible] by presenting a tooltip when [hovered][]. The tooltip is [adjacent[] to the button element but does not remain visible when the mouse pointer is inside its boundaries.

```html
<link rel="stylesheet" type="text/css" href="/test-assets/ep1s13/styles.css" />
<script src="/test-assets/ep1s13/scripts.js"></script>

<body onload="bindEvents({tooltipRemains: false})">
<div class="tooltip-container">
<button aria-labelledby="tooltip">
<span>WCAG</span>
</button>
<p id="tooltip" role="tooltip" hidden>Web Content Accessibility Guidelines</p>
</div>
</body>
```

### Inapplicable

#### Inapplicable Example 1

This element does not cause [content to become visible][content that becomes visible] when [hovered][].

```html
<button>WCAG</button>
```

[adjacent]: #adjacent 'Definition of adjacent'
[bounding box]: https://www.w3.org/TR/css-ui-3/#valdef-box-sizing-border-box
[center]: #center 'Definition of center of a bounding box'
[content that becomes invisible]: #content-that-becomes-invisible 'Definition of content that becomes invisible'
[content that becomes visible]: #content-that-becomes-visible 'Definition of content that becomes visible'
[hovered]: #hovered 'Definition of hovered'
[overlaps]: #overlap 'Definition of overlap'
[sc1.4.13]: https://www.w3.org/WAI/WCAG21/Understanding/content-on-hover-or-focus.html 'Understanding Success Criterion 1.4.13: Content on Hover or Focus, July 24, 2020'
[visible]: #visible 'Definition of visible'
[web page]: #web-page-html 'Definition of HTML web page'
15 changes: 15 additions & 0 deletions pages/glossary/adjacent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Adjacent
key: adjacent
unambiguous: true
objective: true
input_aspects:
- CSS styling
- DOM tree
---

[Bounding boxes][] A and B are _adjacent_ if they do not [overlap][] and at least one point from box A is at the Euclidean distance of 1 [CSS pixel][] from one point in box B.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little nervous about this being exactly 1px with no margin of error. I think we should include anything less than 2, and greater than 0.


[bounding boxes]: https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect 'Definition of getBoundingClientRect'
[CSS pixel]: https://drafts.csswg.org/css-values-3/#visual-angle-unit
[overlap]: #overlap 'Definition of overlap'
22 changes: 22 additions & 0 deletions pages/glossary/center.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: Center
key: center
unambiguous: true
objective: true
input_aspects:
- CSS styling
- DOM tree
---

The _center_ of a [bounding box][] is the point given by the following coordinates:

- The [x coordinate][] is equal to the [left coordinate][] of the [bounding box][] plus half its [width][]; and
- The [y coordinate][] is equal to the [top coordinate][] of the [bounding box][] plus half its [height][].

[bounding box]: https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect 'Definition of getBoundingClientRect'
[height]: https://drafts.fxtf.org/geometry/#rectangle-height-dimension
[left coordinate]: https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left
[top coordinate]: https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top
[width]: https://drafts.fxtf.org/geometry/#rectangle-width-dimension
[x coordinate]: https://drafts.fxtf.org/geometry/#rectangle-x-coordinate
[y coordinate]: https://drafts.fxtf.org/geometry/#rectangle-y-coordinate
25 changes: 25 additions & 0 deletions pages/glossary/content-that-becomes-invisible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: Content that becomes invisible
key: content-that-becomes-invisible
unambiguous: true
objective: true
input_aspects:
- CSS styling
- DOM tree
---

The _content that becomes invisible_ is the [root][] element of the [tree][], if a [tree][] exists, that contains all elements that, after half a second of an [event][] [firing][], meet any of the following:

- the element is removed from the [web page][] where the [event][] was [fired][firing] and the element had [visible text content][]; or
- the element has [attributes][] whose [values][] changed from what they were before the [event][] [firing][] and the change caused some or all of the element's [text nodes][] to stop being [visible][].

[attributes]: https://dom.spec.whatwg.org/#concept-attribute 'Definition of attribute'
[event]: https://dom.spec.whatwg.org/#concept-event 'Definition of event'
[firing]: https://dom.spec.whatwg.org/#concept-event-fire 'Definition of event firing'
[root]: https://dom.spec.whatwg.org/#concept-tree-root 'Definition of root'
[text nodes]: https://dom.spec.whatwg.org/#text 'Definition of DOM text'
[tree]: https://dom.spec.whatwg.org/#concept-tree 'Definition of tree'
[values]: https://dom.spec.whatwg.org/#concept-attribute-value 'Definition of attribute value'
[visible]: #visible 'Definition of visible'
[visible text content]: #visible-text-content 'Definition of visible text content'
[web page]: #web-page-html 'Definition of web page'
21 changes: 21 additions & 0 deletions pages/glossary/content-that-becomes-visible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Content that becomes visible
key: content-that-becomes-visible
unambiguous: true
objective: true
input_aspects:
- CSS styling
- DOM tree
---

The _content that becomes visible_ after an [event][] [firing][] is any element for which all of the following is true:

- 500 milliseconds after the [event][] [firing][] the element has [visible text content][]; and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to capture an assumption that content on hover will appear within 500ms.

- a tick before the [event][] [firing][] there was no element with the same [descendant text content][] that the element has after the [event][] [firing][]; and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me like this would apply to elements that update their content too. If I have a button that changes its text on hover, it 1. has visible content after the event. and 2. does not have the same descendant text content. Additionally, descendant text content does not take shadow DOM into account.

- the element has no [descendants][] for which the above two conditions are true.

[descendants]: https://dom.spec.whatwg.org/#concept-tree-descendant
[descendant text content]: https://dom.spec.whatwg.org/#concept-descendant-text-content 'Definition of descendant text content'
[event]: https://dom.spec.whatwg.org/#concept-event 'Definition of event'
[firing]: https://dom.spec.whatwg.org/#concept-event-fire 'Definition of event firing'
[visible text content]: #visible-text-content 'Definition of visible text content'
10 changes: 10 additions & 0 deletions pages/glossary/hovered.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: Hovered
key: hovered
unambiguous: true
objective: true
input_aspects:
- DOM tree
---

An element is hovered (by a pointing device) when that element matches the [`:hover` pseudo-class](https://drafts.csswg.org/selectors-4/#hover-pseudo).
22 changes: 22 additions & 0 deletions pages/glossary/overlap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: Overlap
key: overlap
unambiguous: true
objective: true
input_aspects:
- CSS styling
- DOM tree
---

[Bounding boxes][] A and B _overlap_ if one of the following is true:

- the value of the [x coordinate][] property of box A is between the values of the [top][] and [bottom][] properties of box B and the value of the [y coordinate][] of box A is between the values of the [left][] and [right][] properties of box B; or
- the value of the [x coordinate][] property of box B is between the values of the [top][] and [bottom][] properties of box A and the value of the [y coordinate][] of box B is between the values of the [left][] and [right][] properties of box A.

[bounding boxes]: https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect 'Definition of getBoundingClientRect'
[bottom]: https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-bottom
[left]: https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-left
[right]: https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-right
[top]: https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-top
[x coordinate]: https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-x
[y coordinate]: https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-y
27 changes: 27 additions & 0 deletions test-assets/ep1s13/scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function bindEvents(bind) {
let containers;
if (bind.tooltipRemains)
containers = document.querySelectorAll(".tooltip-container");
else
containers = document.querySelectorAll("button");
for (const container of containers) {
container.addEventListener("mouseenter", () => {
console.log(container);
showTooltip(container);
});
container.addEventListener("mouseleave", () => {
hideTooltip(container);
});
}
}

function showTooltip(elem) {
const tooltip = elem.querySelector("[role=tooltip]");
console.log(tooltip);
tooltip.removeAttribute("hidden");
}

function hideTooltip(elem) {
const tooltip = elem.querySelector("[role=tooltip]");
tooltip.setAttribute("hidden", "hidden");
}
30 changes: 30 additions & 0 deletions test-assets/ep1s13/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
:root {
--tooltip-thingy-width: 0.5em;
}

.tooltip-container {
position: relative;
display: inline-block;
}

[role="tooltip"] {
position: absolute;
top: 0%;
left: 100%;
transform: translateY(-60%) translateX(2%);
padding: 0.5em 0.5em;
color: white;
background: black;
min-width: max-content;
}

[role="tooltip"]::before {
position: absolute;
left: 0;
top: 0;
transform: translateY(50%) translateX(-99%);
border: var(--tooltip-thingy-width) solid transparent;
border-right-color: black;
content: "";
}

Loading