diff --git a/__tests__/spelling-ignore.yml b/__tests__/spelling-ignore.yml index 81316f10c55..acecafba088 100644 --- a/__tests__/spelling-ignore.yml +++ b/__tests__/spelling-ignore.yml @@ -209,6 +209,11 @@ - dom-meta-content - showModal +# Javascript identifiers +- clientRects +- getBoundingClientRect +- getClientRects + # Unsure why the dictionary does not have these words - programmatically - personalization @@ -237,6 +242,7 @@ - focusability - unitless - luminance +- checkboxes # this seems tè be the correct plural # Parts of Unicode - 000A @@ -271,6 +277,13 @@ - 25px - 30px - 32px +- 35px +- 41px +- 44px +- 45px +- 48px +- 50px +- 54px # Language codes - da diff --git a/_rules/target-size-enhanced-gi8qkf.md b/_rules/target-size-enhanced-gi8qkf.md new file mode 100755 index 00000000000..7766cc18933 --- /dev/null +++ b/_rules/target-size-enhanced-gi8qkf.md @@ -0,0 +1,739 @@ +--- +id: gi8qkf +name: +rule_type: atomic +description: | + This rule checks that elements that can receive pointer events have a size of at least 44×44 pixels. +accessibility_requirements: + wcag21:2.5.5: # Target size (enhanced) (AAA) + forConformance: true + failed: not satisfied + passed: further testing needed + inapplicable: further testing needed + wcag22:2.5.8: # Target Size (Minimum) (AA) + secondary: 'This success criterion is **less strict** than this rule. This is because this criterion has a lower size requirement. Some of the failed examples may satisfy this success criterion.' +input_aspects: + - DOM Tree + - CSS Styling +acknowledgments: + authors: + - Jean-Yves Moyen + test_assets: Map Image by Freepik +--- + +## Applicability + +This rule applies to any [HTML element][namespaced element] which [can be targeted by a pointer event][]. + +## Expectation + +For each test target, at least one of the following is true: + +- though scrolling, the element can be brought into viewport with a [clickable area][] containing an [horizontal rectangle][] with width and height of at least 44 CSS pixels; or +- the element has an empty [clickable area][], and its [clickable area][] cannot be made non-empty through scrolling; or +- the target is [rendered on a line][]; or +- the target is a [User Agent controlled component][]; or +- The size has [essential target size][]; or +- There is an [instrument][] to achieve an equivalent goal on the same page, and through scrolling this [instrument][] can be brought into viewport with a [clickable area][] containing an [horizontal rectangle][] with width and height of at least 44 CSS pixels. + +## Assumptions + +- This rule assumes that [focusable][] `widget` are effectively clickable. If a widget is [focusable][] without being clickable, it may fail this rule while [Success Criterion 2.5.5 Target Size (enhanced)][sc255] is satisfied. + +## Accessibility Support + +Hit testing isn't properly defined, and this has been an [issue in the CSS specification](https://github.com/w3c/csswg-drafts/issues/2325) for years. Therefore, different User Agents may perform it differently, resulting in different [clickable areas][clickable area] for the same element. As of February 2023, the ACT rules Community Group is not aware of actual cases resulting in significantly different [clickable areas][clickable area]. + +## Background + +While the rule, and [Success Criterion 2.5.5 Target Size (enhanced)][sc255], apply targets of any shape, the test cases mostly focus on targets whose [clickable area][] is itself an [horizontal rectangle][]. This acknowledges the fact that the [border box][] of an element can easily be queried by automated tools (e.g., through the `getBoundingClientRect` function), and therefore it is expected that most automated tools will perform better on such elements. For elements with "weird" clickable shape, including `area` elements, nested targets, or elements that have been rotated or clipped, the actual [clickable area][] is much harder to determine and may be much smaller than the [border box][]. These elements could fail the rule while their [border box][] contain a large enough [horizontal rectangle][]. In order to allow automated tools to have a consistent implementation of this rule, it does not contain such test cases, notably all Failed test cases have a [border box][] which is too small. + +### Bibliography + +- [Understanding Success Criterion 2.5.5: Target Size (enhanced)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-enhanced.html) + +## Test Cases + +> **Note:** Several examples draw borders around some of the elements or texts. This is purely for aesthetic purpose and to clearly show the [clickable areas][clickable area] that are not obvious. These borders are solid green when showing good cases, or relevant areas; and dashed red when showing bad cases, or irrelevant areas. + +> **Note:** Several examples illustrate overlapping and partially obscured content with fully transparent `div` (with a dashed red border), in order to still show the underlying target. This often results in very "artificial" examples where in real page the overlapping element would not be transparent and would actually hide the target. + +### Passed + +#### Passed Example 1 + +This `link` has a [clickable area][] of approximately 210×55 pixels. + +```html + +ACT rules +``` + +#### Passed Example 2 + +This button has a [clickable area][] of exactly 44×44 pixels. + +```html + + +``` + +#### Passed Example 3 + +This `input` element, combined with its [implicit label][] and its padding, has a [clickable area][] containing a rectangle of approximately 81×48px. Note that this rectangle has to intersect both the `input` element itself, and the text of the label (within the solid green border), as none of the individual components are enough. + +```html + + Passed Example 3 + + + + + +``` + +#### Passed Example 4 + +This `input` element, combined with its [explicit label][] and its padding, has a [clickable area][] containing a rectangle of approximately 81×45px. Note that this rectangle has to intersect both the `input` element itself, and the text of the label (within the solid green border), as none of the individual components are enough. + +```html + + Passed Example 4 + + + + + + +``` + +#### Passed Example 5 + +This button has a clickable area of approximately 212×54px due to the overflowing text being clickable. The `div` element is only here to visually display the clickable area of the text. + +```html + + Passed Example 5 + + + + + + + + + +``` + +#### Passed Example 6 + +This button, together with its padding and border, has a [clickable area][] of more than 44×44px. The solid green border shows the [clickable area][] while the dashed red one shows the inner text (without sizing nor padding). + +```html + + Passed Example 6 + + + + + +
Hi
+ + +``` + +#### Passed Example 7 + +These links are [rendered on a line][]. + +```html +

+ The size of the target for + pointer inputs is at least 44 by 44 + CSS pixels. +

+``` + +#### Passed Example 8 + +This checkbox is an [User-Agent controlled component][]. + +```html +

+ + I agree with the terms and conditions. +

+``` + +#### Passed Example 9 + +The pin (red square) on this map has [essential size][] because it is important to pinpoint the exact location. + +```html + + +Location of ACT rules headquarters: +
+ +``` + +#### Passed Example 10 + +The `#small` button has a [clickable area][] of only 35×35px, but there is an [instrument][] to achieve the same function with a 44×44px [clickable area][] (namely, the `#large` button). + +```html + + + +``` + +#### Passed Example 11 + +This button has a [clickable area][] containing a 44×44px rectangle. Even though it is partially obscured by the dashed red `div`, its remaining [clickable area][] contains a 44×44px rectangle delimited by prolonging the solid green lines. + +```html + + Passed Example 9 + + + + + +
+
+
+``` + +#### Passed Example 12 + +This button has a [clickable area][] of roughly 73×50px. The `div` element with a dashed red border does not obscure it because of its `pointer-events: none` CSS property that let the clicks go through. + +```html + + Passed Example 10 + + + + + +
+``` + +#### Passed Example 13 + +This button has a 50×50px [clickable area][]. The `div` with a dashed red border is not obscuring it because it can be scrolled out of the way. The solid green lines hint at a 44×44px area inside the button. + +```html + + Passed Example 12 + + + + +
+
+
+
+ + +
+
+``` + +#### Passed Example 14 + +The [clickable area][] of this button contains a 44×44px [horizontal rectangle][]. Note that the actual [border box][] has to be much larger to account for the rounded corners. + +```html + + +``` + +#### Passed Example 15 + +This button has been clipped, leaving a [clickable area][] containing a 45×45px [horizontal rectangle][]. + +```html + + Failed Example + + + +
+ Hello +
+``` + +### Failed + +#### Failed Example 1 + +This `button` has a [clickable area][] of only 35×35 pixels. + +```html + + +``` + +#### Failed Example 2 + +This link only has a [clickable area][] of approximately 66×18 pixels, as shown by its border. + +```html + + Failed Example 2 + + + + + ACT rules + +``` + +#### Failed Example 3 + +This custom button has a [clickable area][] of approximately 18×20px, as shown by its dashed red border. + +```html + + Failed Example 3 + + +Hi +``` + +#### Failed Example 4 + +This input, together with its [implicit label][] and its padding has a [clickable area][] whose height is below 41px. + +```html + +``` + +#### Failed Example 5 + +The `#small` button has a [clickable area][] of only 35×35px. The `#large` button has a [clickable area][] of 44×44px, but it does not achieve the same objective. + +```html + + + +``` + +#### Failed Example 6 + +This button only has a [clickable area][] of approximately 20×45px, because it is obscured by the `div` with a dashed red border. The solid green lines hint at how a 44×44px area would fit inside the button, but not inside the non-obscured part. + +```html + + Failed Example 6 + + + + + +
+
+
+``` + +#### Failed Example 7 + +This button only has a [clickable area][] of approximately 20×45px, because it is obscured by the `div` with a dashed red border. Even though the `div` is scrollable, it is not scrollable fully out of the way and always obscures the button. The solid green lines hint at how a 44×44px area would fit inside the button, but not inside the never obscured part. + +```html + + Failed Example 7 + + + + +
+
+
+
+ + +
+
+``` + +#### Failed Example 8 + +These radio buttons have their size modified by the author and are therefore not [User-Agent controlled components][]. Their [clickable area][] is too small. + +```html + +
+ Pick a color (required) + + +
+``` + +#### Failed Example 9 + +The [clickable area][] of this button does not contain a 44×44px [horizontal rectangle][]. + +```html + + +``` + +#### Failed Example 10 + +The [clickable area][] of this button does not contain a 44×44px [horizontal rectangle][]. + +```html + + +``` + +#### Failed Example 11 + +The [clickable area][] of this button only contains a 25×45px [horizontal rectangle][]. + +```html + + Failed Example + + + +
+ Hello +
+``` + +### Inapplicable + +#### Inapplicable Example 1 + +These `input` elements and `button` are `disabled` and therefore not [focusable][]. + +```html +
+
+
+ +
+``` + +#### Inapplicable Example 2 + +This button cannot be [targeted by a pointer event][] because it is entirely covered by the `div` element with a dashed red border. + +```html + + Inapplicable Example + + + + + +
+``` + +[border box]: https://www.w3.org/TR/css-box-3/#border-box 'CSS definition of Border Box' +[can be targeted by a pointer event]: #can-be-targeted-by-pointer-event 'Definition of Can be Targeted by a Pointer Event' +[clickable area]: #clickable-area 'Definition of Clickable Area' +[essential target size]: #essential-target-size ' Definition of Essential Target Size' +[explicit label]: #programmatic-label:explicit 'Definition of Explicit Label' +[focusable]: #focusable 'Definition of Focusable' +[horizontal rectangle]: #horizontal-rectangle 'Definition of Horizontal Rectangle' +[implicit label]: #programmatic-label:implicit 'Definition of Implicit Label' +[instrument]: #instrument-to-achieve-an-objective 'Definition of Instrument to Achieve an Objective' +[namespaced element]: #namespaced-element 'Definition of Namespaced Element' +[rendered on a line]: #rendered-on-a-line 'Definition of Rendered on a Line' +[sc255]: https://www.w3.org/TR/WCAG22/#target-size-enhanced 'Success Criterion 2.5.5 Target Size (enhanced)' +[targeted by a pointer event]: #can-be-targeted-by-pointer-event 'Definition of Can be Targeted by a Pointer Event' +[user agent controlled component]: #user-agent-controlled-component 'Definition of UI Controlled Component' diff --git a/pages/examples/programmatic-label.md b/pages/examples/programmatic-label.md index 37fbc0b445d..c79f2614db9 100644 --- a/pages/examples/programmatic-label.md +++ b/pages/examples/programmatic-label.md @@ -56,13 +56,13 @@ The `div` element is not [labelable][]. Therefore, it is not a [labeled control]
My name is Bond. James Bond.
``` -## aria-labelledby on div +## aria-labelledby on aside -The `span` element is referenced by the `aria-labelledby` attribute on the `div` element. Therefore, the `span` element is a programmatic label of the `div` element. Note that the `aria-labelledby` attribute works on any element, not just on the [labelable][] elements. +The `span` element is referenced by the `aria-labelledby` attribute on the `aside` element. Therefore, the `span` element is a programmatic label of the `div` element. Note that the `aria-labelledby` attribute works on any element, not just on the [labelable][] elements. ```html Full name: -
My name is Bond. James Bond.
+ ``` [programmatic label]: /glossary/#programmatic-label diff --git a/pages/glossary/can-be-targeted-by-pointer-event.md b/pages/glossary/can-be-targeted-by-pointer-event.md new file mode 100644 index 00000000000..4a5a8c0168c --- /dev/null +++ b/pages/glossary/can-be-targeted-by-pointer-event.md @@ -0,0 +1,36 @@ +--- +title: Can be target by a pointer event +key: can-be-targeted-by-pointer-event +unambiguous: true +objective: true +input_aspects: + - CSS styling + - DOM tree +--- + +An element _can be targeted by pointer events_ when all the following conditions are true: + +- the element is a [semantic `widget`][semantic role]; and +- the element is [focusable][]; and +- the element [computed value][] of the `pointer-events` CSS property is `auto`; and +- through scrolling, it is possible to have parts of the element's [border box][] which intersect the viewport and are not entirely covered by the [border boxes][] of elements with greater [computed][computed value] `z-index` and a [computed][computed value] `pointer-events` of `auto`. + +#### Background + +This definition tries to capture which HTML elements can actually react to pointer events. It is not possible to have an exact definition of these for two main reasons: + +- Sometimes, the element that handles the event is not the element that appear to react to it, but an ancestor (or descendant) capturing the event during propagation or bubbling. In the most extreme case, the `body` element of a page could be the only one with an event handler, acting differently depending on where the event actually occurred. In such a case, a button would be perceived by users as something that can be targeted by a pointer event, while technically it is the `body` element which is targeted. +- It is not possible to query the list of event listeners on a given elements. Some User Agents offer way to monitor events fired at a given element, but none offer a way to query for event listeners. Additionally, an event listener might ultimately do nothing and thus, for users, the corresponding element wouldn't look like it can be targeted by pointer events (since it effectively wouldn't react to them). + +As a consequence, this definition has these two known limitations: + +- Not all HTML elements that can actually be targeted by a pointer event match this definition. For example, an author may build custom buttons without giving them an appropriate role or making them [focusable][]; or content overflowing the [border box][] of an element is clickable, but that element might not match the definition if the [border box][] is off-screen. Elements that can actually be targeted by pointer events but do not match this definition likely fail either [Success Criterion 4.1.2 Name, Role, Value][sc412] or [Success Criterion 2.1.1 Keyboard][sc211]. +- Not all HTML elements that match this definition can actually be targeted by a pointer event. For example, when the actual clickable area does not cover the full [border box][] and is entirely covered by other elements, or when the element has an event handler that does nothing. Elements that match this definition but cannot actually be targeted by pointer events likely fail [Success Criterion 2.5.6 Concurrent Input Mechanisms][sc256]. + +[border box]: https://www.w3.org/TR/css-box-3/#border-box 'CSS definition of Border Box' +[computed value]: https://www.w3.org/TR/css-cascade-3/#computed 'CSS definition of Computed Value' +[focusable]: #focusable 'Definition of Focusable' +[sc211]: https://www.w3.org/TR/WCAG22/#keyboard 'Success Criterion 2.1.1 Keyboard' +[sc256]: https://www.w3.org/TR/WCAG22/#concurrent-input-mechanisms 'Success Criterion 2.5.6 Concurrent Input Mechanisms' +[sc412]: https://www.w3.org/TR/WCAG22/#name-role-value 'Success Criterion 4.1.2 Name, Role, Value' +[semantic role]: #semantic-role 'Definition of Semantic Role' diff --git a/pages/glossary/clickable-area.md b/pages/glossary/clickable-area.md new file mode 100644 index 00000000000..97d8c649a31 --- /dev/null +++ b/pages/glossary/clickable-area.md @@ -0,0 +1,17 @@ +--- +title: Clickable area +key: clickable-area +unambiguous: true +objective: false +input_aspects: + - CSS styling + - DOM tree +--- + +The _directly clickable area_ of an element is the set of all viewport coordinates for which the element is the [topmost event target][] + +The _clickable area_ of an element is the union of its _directly clickable area_ and that of its [implicit][implicit label] or [explicit label][]. Clickable areas may contain several disconnected parts. + +[explicit label]: #programmatic-label:explicit 'Definition of Explicit Label' +[implicit label]: #programmatic-label:implicit 'Definition of Implicit Label' +[topmost event target]: https://w3c.github.io/uievents/#topmost-event-target 'CSS definition of Topmost Event Target' diff --git a/pages/glossary/essential-target-size.md b/pages/glossary/essential-target-size.md new file mode 100644 index 00000000000..49eaa865048 --- /dev/null +++ b/pages/glossary/essential-target-size.md @@ -0,0 +1,13 @@ +--- +title: Essential Target Size +key: essential-target-size +unambiguous: true +objective: false +--- + +An element which [can be targeted by a pointer event][] has _essential target size_ if at least one of the following is true: + +- the element is a pin on a map, indicating a precise position, and larger size would create confusion regarding this position; or +- the element is part of a graphical representation of data (e.g., a graph), indicating a precise value, and larger size would create confusion regarding this value. + +[can be targeted by a pointer event]: #can-be-targeted-by-pointer-event 'Definition of Can be Targeted by a Pointer Event' diff --git a/pages/glossary/horizontal-rectangle.md b/pages/glossary/horizontal-rectangle.md new file mode 100644 index 00000000000..06255958dbe --- /dev/null +++ b/pages/glossary/horizontal-rectangle.md @@ -0,0 +1,13 @@ +--- +title: Horizontal rectangle +key: horizontal-rectangle +unambiguous: true +objective: true +input_aspects: +--- + +A set of coordinates R is an _horizontal rectangle_ if there exist a coordinate _(x, y)_ and numbers _w_ and _h_ such that all coordinates _(a, b)_ with _x ⩽ a ⩽ x+w_ and _y ⩽ b ⩽ y+h_ are part of R. + +R is then said to have corner _(x, y)_, width _w_, and height _h_. + +Note that the rectangle is "horizontal" in the sense that its sides align with the axis of the coordinate system. diff --git a/pages/glossary/programmatic-label.md b/pages/glossary/programmatic-label.md index 83af78845a6..4f93566512e 100755 --- a/pages/glossary/programmatic-label.md +++ b/pages/glossary/programmatic-label.md @@ -16,5 +16,9 @@ For more details, see [examples of programmatic label][]. **Note**: a given element may have more than one programmatic label. +The [labeled control][] L of an element T is its explicit label if L has a `for` attribute referencing T's `id` attribute. + +The [labeled control][] L of an element T is its implicit label if L has a no `for` attribute and is an ancestor of T in the DOM tree. Note that explicit labels take precedence over implicit label, and that [labeled controls][labeled control] do not cross shadow boundaries nor content documents. + [labeled control]: https://html.spec.whatwg.org/multipage/forms.html#labeled-control 'Definition of labeled control' [examples of programmatic label]: https://act-rules.github.io/pages/examples/programmatic-label/ diff --git a/pages/glossary/rendered-on-a-line.md b/pages/glossary/rendered-on-a-line.md new file mode 100644 index 00000000000..1228f22d051 --- /dev/null +++ b/pages/glossary/rendered-on-a-line.md @@ -0,0 +1,27 @@ +--- +title: Rendered on a line +key: rendered-on-a-line +unambiguous: true +objective: true +input_aspects: + - CSS styling + - DOM tree +--- + +All nodes that generate an [inline box][] that are part of a [line box][] are considered _rendered on a line_. These are _line rendering nodes_. + +Any [flat tree][] [descendants][] of line rendering nodes are also considered part of a line if one of its [clientRects][] overlaps with the position of the [line box][], and if all the following is true for each [ancestor][] in the [flat tree][] up to the line rendering node: + +- the ancestor is an [inline box][]; and +- the ancestor is not [floating][]; and +- the ancestor does not have an [absolute][] or [fixed][] position. + +[absolute]: https://drafts.csswg.org/css-position-3/#valdef-position-absolute 'Definition of absolute' +[ancestor]: https://dom.spec.whatwg.org/#concept-tree-ancestor 'Definition of ancestor' +[clientrects]: https://drafts.csswg.org/cssom-view/#dom-element-getclientrects 'Definition of getClientRects' +[descendants]: https://dom.spec.whatwg.org/#concept-tree-descendant 'Definition of descendant' +[fixed]: https://drafts.csswg.org/css-position-3/#valdef-position-fixed 'Definition of fixed' +[flat tree]: https://drafts.csswg.org/css-scoping/#flat-tree 'Definition of flat tree' +[floating]: https://www.w3.org/TR/CSS2/visuren.html#floats 'Definition of float' +[inline box]: https://drafts.csswg.org/css-display/#inline-box 'Definition of inline box' +[line box]: https://drafts.csswg.org/css2/visuren.html#line-box 'Definition of line box' diff --git a/pages/glossary/user-agent-controlled-component.md b/pages/glossary/user-agent-controlled-component.md new file mode 100644 index 00000000000..1cadad0a1e6 --- /dev/null +++ b/pages/glossary/user-agent-controlled-component.md @@ -0,0 +1,31 @@ +--- +title: User-Agent Controlled Component +key: user-agent-controlled-component +unambiguous: true +objective: true +input_aspects: + - CSS styling + - DOM tree +--- + +A _User-Agent Controlled Component_ is an [HTML element][namespace element] for which all the following are true: + +- the element has an [implicit role][] which is a [semantic `widget`][semantic role]; and +- the [computed values][] of the element's `height` and `width` CSS properties do not depend on content provided by the author; and +- the [computed values][] of the element's `height` and `width` CSS properties do not depend on any CSS property with a [cascaded value][] with "Author" [origin][]. + +#### Examples + +Typically, radio buttons or checkboxes are User-Agent controlled, until an author does change their dimensions. + +Links and buttons usually aren't, because their (text) content is provided by the author and the width depends on it. + +Days in a calendar widget build with an `` element are also User-Agent controlled since their content isn't provided by the author and their dimension do not depend on values provided by the author. + +Directly setting the `height` or `width` CSS properties makes an element not User-Agent controlled. Changing the `max-height` or `min-width` properties can make it not User-Agent controlled, if the added constraint impacts the [computed][computed values] `height` or `width` properties (i.e., if the `height` would be larger than `max-height` and is restricted by it; or if the `width` would be smaller than `min-width` and is changed by it). + +[cascaded value]: https://www.w3.org/TR/css-cascade-5/#cascade-value 'CSS definition of computed value' +[computed values]: https://www.w3.org/TR/css-cascade-3/#computed 'CSS definition of Computed Value' +[implicit role]: #implicit-role 'Definition of Implicit Role' +[origin]: https://drafts.csswg.org/css-cascade-5/#cascading-origins 'CSS definition of Cascading Origin' +[semantic role]: #semantic-role 'Definition of Semantic Role' diff --git a/test-assets/target-size/highlight-rect.js b/test-assets/target-size/highlight-rect.js new file mode 100644 index 00000000000..b170bb71d86 --- /dev/null +++ b/test-assets/target-size/highlight-rect.js @@ -0,0 +1,31 @@ +/** + * Create an element with class "highlight" around a node. + * The node needs to be non-static to allow for z-index lower than + * the highlighted element, otherwise the .highlight element will prevent + * click events to reach the node. + * + * An optional set of classes can also be added to the highlighted element, + * these are mostly intended to be either ['good'] (default) or ['bad'] to set + * the color and style of the highlighting border. + */ +function highlightRect(node, classes = ['good']) { + // Get the bounding client rect of the node + const range = document.createRange() + range.setStart(node, 0) + // Take the length of text nodes, if it exists, otherwise (element), take + // all child nodes + range.setEnd(node, node?.length ?? node.childNodes.length) + const rect = range.getBoundingClientRect() + + // Create a div sized to that rect + // See https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects#javascript + const div = document.createElement('div') + div.classList.add('highlight', ...classes) + div.style.top = `${rect.top}px` + div.style.left = `${rect.left}px` + div.style.width = `${rect.width - 2}px` + div.style.height = `${rect.height - 2}px` + document.body.appendChild(div) + + return div +} diff --git a/test-assets/target-size/highlight.css b/test-assets/target-size/highlight.css new file mode 100644 index 00000000000..0ce20f3e455 --- /dev/null +++ b/test-assets/target-size/highlight.css @@ -0,0 +1,16 @@ +.highlight { + position: absolute; + z-index: 0; +} + +.good { + border: green solid 1px; +} +.bad { + border: red dashed 1px; +} + +.highlightable { + position: relative; + z-index: 5; +} diff --git a/test-assets/target-size/map-background.jpg b/test-assets/target-size/map-background.jpg new file mode 100644 index 00000000000..1b7858a7f6c Binary files /dev/null and b/test-assets/target-size/map-background.jpg differ