Skip to content
Open
Changes from all commits
Commits
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
22 changes: 11 additions & 11 deletions site/src/pages/components/link-area-delegation-explainer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ We are currently incubating and exploring a new idea. Chime in!

## Overview
Historically and for very good reasons, interactive elements on the web cannot be nested within other interactive elements. Examples of interactive elements include links and buttons.
Interactive elements (such as buttons and hyperlinks) not allowing descendent interactive elements is a well established rule in HTML - where interactive elements or elements with a `tabindex` attribute within such elements are specifically called out as invalid (for instance, see [the `a` element's content model](https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element). Additionally, the [ARIA in HTML specification]([https://w3c.github.io/html-aria/](https://w3c.github.io/html-aria/#allowed-descendants-of-aria-roles)) provides additional guidance to discourage the use of interactive elements as descendent of ARIA roles which are themselves considered "widget" (interactive) roles.
Interactive elements (such as buttons and hyperlinks) not allowing descendent interactive elements is a well established rule in HTML - where interactive elements or elements with a `tabindex` attribute within such elements are specifically called out as invalid (for instance, see [the `a` element's content model](https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element). Additionally, the [ARIA in HTML specification](https://w3c.github.io/html-aria/) provides [additional guidance](https://w3c.github.io/html-aria/#allowed-descendants-of-aria-roles) to discourage the use of interactive elements as descendent of ARIA roles which are themselves considered "widget" (interactive) roles.

Despite this long-standing rule, there are websites which ignore it. In doing so, these sites end up with UI which can be difficult if not impossible to use with assistive technology, such as a screen reader. On the flip-side, there are websites which have created clickable containers in a way that passes HTML validation, and often with the goal of making the pattern, at least, keyboard and screen reader accessible. This can be achieved by implementing such markup patterns in specific ways, along with using CSS, JS, or both to extend a primary target's (often link, sometimes button) clikcable area. The end UX/accessibility of such endevors is commonly variable, due to a lack of standardization and common lack of knowledge about how assistive technology accesses content through the browser's accessibility APIs.

Expand All @@ -40,17 +40,17 @@ Commonly a clickable container, often referred to as a "card", will present a gr
### Existing ways to achieve clickable containers
Today, making a container/card clickable can be achieved with a few different approaches, each with its own tradeoffs:
1. Using the `a` element to wrap the content that needs to be clickable. The issue with this is:
a. doesn't support nested interactive elements without creating accessibility issues.
b. using an `a` element to wrap content is not supported in certain contexts - e.g., such as trying to wrap a row within a table. The HTML parser will remove such hyperlinks from the rendered table markup.
c. even without nested interactive elements, the accessible name of the hyperlink can become overly verbose, or may not be exposed as all depending on the roles of the elements that are descendents of the hyperlink.
1. doesn't support nested interactive elements without creating accessibility issues.
2. using an `a` element to wrap content is not supported in certain contexts - e.g., such as trying to wrap a row within a table. The HTML parser will remove such hyperlinks from the rendered table markup.
3. even without nested interactive elements, the accessible name of the hyperlink can become overly verbose, or may not be exposed as all depending on the roles of the elements that are descendents of the hyperlink.
2. Using CSS to position / stack interactive elements. For instance, using CSS to put a duplicate hyperlink, or the call to action of the container's `::before` or `::after` pseudo element "behind" the "nested" interactive elements, so that the link catches clicks that are not handled by these other interactive targets. The issue with these can be:
a. again, no standardized way to do this, with some version of this implementation better than others. For instance, implementations that use duplicate links, creating redundancy for keyboard and/or screen reader users (even if the duplicate link is `tabindex=-1`), being some of the worst.
b. this sort of stacking/overlaying implementation often makes it difficult if not impossible for some users to select what appears to be static text, and can lead to some instances of accidental activation of the hyperlink. For instance, due to lack of interactive affordance that the static text / white space areas of the component are clickable.
c. Such a pattern usually relies on all intermediate elements between the container/card and the primary action within to have `display: static`. Depending on the visual design requirements, this may not be feasible.
1. again, no standardized way to do this, with some version of this implementation better than others. For instance, implementations that use duplicate links, creating redundancy for keyboard and/or screen reader users (even if the duplicate link is `tabindex=-1`), being some of the worst.
2. this sort of stacking/overlaying implementation often makes it difficult if not impossible for some users to select what appears to be static text, and can lead to some instances of accidental activation of the hyperlink. For instance, due to lack of interactive affordance that the static text / white space areas of the component are clickable.
3. Such a pattern usually relies on all intermediate elements between the container/card and the primary action within to have `display: static`. Depending on the visual design requirements, this may not be feasible.
3. Using JavaScript to Capture clicks: have the container element capture clicks, and delegate them to the main link only if the original target is not another interactive target.
a. requires the use of JS, which in itself is not a bad thing, but may undesired by some developers - leading them to use alternate patterns, or,
b. can lead to other UX issues, such as activation on `mousedown` rather than 'up', or people forgoing the inclusion of a nested hyperlink in favor of only using the JS, leading to the element being accessible to pointer events, but often not to keyboard or assistive techology users.
c. additionally, some JS implementations have the potential to conflict with default browser behaviors - such as context menus, or popup blocking.
1. requires the use of JS, which in itself is not a bad thing, but may undesired by some developers - leading them to use alternate patterns, or,
2. can lead to other UX issues, such as activation on `mousedown` rather than 'up', or people forgoing the inclusion of a nested hyperlink in favor of only using the JS, leading to the element being accessible to pointer events, but often not to keyboard or assistive techology users.
3. additionally, some JS implementations have the potential to conflict with default browser behaviors - such as context menus, or popup blocking.

These are ways to achieve this kind of experience that have their own constraints and compromises. At this point, this became a common enough pattern in the web, so perhaps it is time it became a first class citizen.

Expand All @@ -64,7 +64,7 @@ Some more detailed points on what this means for the UI and UX of the feature:
3. Potentially, user agents can expand the hit-testing area for some of the descendants, to prioritize clicking them vs. clicking on the card (see [WCAG 2.5.8: Target Size (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html)).
4. This feature has no effect on keyboard navigation, and would prevent the potential for otherwise unnecessary duplicate hyperlinks. It's a pointer click affordance, and would not affect the "semantics" of the container element (see also [the `popover` attribute](https://html.spec.whatwg.org/multipage/popover.html#the-popover-attribute:~:text=The%20popover%20attribute%20is%20a%20global%20attribute%20that%20allows%20authors%20flexibility%20to%20ensure%20popover%20functionality%20can%20be%20applied%20to%20elements%20with%20the%20most%20relevant%20semantics.)).
5. At this time, it is not expected that this feature would be exposed to the accessibility tree, much like a `label` element is not overtly exposed to the accessibility tree/to assistive technology users. It's purpose is to extend the clickable area of the referenced hyperlink - which is expected to be the accessibile object for people using AT/keyboard to interact with.
a. **NOTE:** some screen readers, such as NVDA, may announce "clickable" for current instances of the JS variant of this pattern. This is not necessarily because it's important for users to know the container is clickable in this specific context - but because the screen reader is _only_ aware there is a click event on the container, but not what the click event will do. If the screen reader were aware of the relationship between the container and the nested hyperlink, and that they would perform the same function, it is far more likely that such instances of the "clickable" announcement would not be needed.
1. **NOTE:** some screen readers, such as NVDA, may announce "clickable" for current instances of the JS variant of this pattern. This is not necessarily because it's important for users to know the container is clickable in this specific context - but because the screen reader is _only_ aware there is a click event on the container, but not what the click event will do. If the screen reader were aware of the relationship between the container and the nested hyperlink, and that they would perform the same function, it is far more likely that such instances of the "clickable" announcement would not be needed.

### Approach 1: Link delegation attributes
Expressing link area delegation in HTML can look something like this:
Expand Down