Targeting by Reference in the Shadow DOM

Published 2 hours past

I’ve long made it clear that I don’t particularly care for the whole Shadow DOM thing.  I believe I understand the problems it tries to solve, and I fully acknowledge that those are problems worth solving.  There are just a bunch of things about it that don’t feel right to me, like how it can break accessibility in a number of ways.

One of those things is how it breaks stuff like the commandFor attribute on <button>s, or the popoverTarget attribute, or a variety of ARIA attributes such as aria-labelledby.  This happens because a Shadow DOMmed component creates a whole separate node tree, which creates a barrier (for a lot of things, to be clear; this is just one class of them).

At least, that’s been the case.  There’s now a proposal to fix that, and prototype implementations in both Chrome and Safari!  In Chrome, it’s covered by the Experimental Web Platform features flag in chrome://flags.  In Safari, you open the Develop > Feature Flags… dialog, search for “referenceTarget”, and enable both flags.

(Disclosure: My employer, Igalia, with support from NLnet, did the WebKit implementation, and also a Gecko implementation that’s being reviewed as I write this.)

If you’re familiar with Shadow DOMming, you know that there are attributes for the <template> element like shadowRootClonable that set how the Shadow DOM for that particular component can be used.  The proposal at hand is for a shadowRootReferenceTarget attribute, which is a string used to identify an element within the Shadowed DOM tree that should be the actual target of any references.  This is backed by a ShadowRoot.referenceTarget API feature.

Take this simple setup as a quick example.

 <label for="consent">I agree to join your marketing email list for some reason</label>
<sp-checkbox id="consent">
	<template>
		<input id="setting" type="checkbox" aria-checked="indeterminate">
		<span id="box"></span>	
	</template> </sp-checkbox> 

Assume there’s some JavaScript to make that stuff inside the Shadow DOM work as intended.  (No, nothing this simple should really be a web component, but let’s assume that someone has created a whole multi-faceted component system for handling rich user interactions or whatever, and someone else has to use it for job-related reasons, and this is one small use of that system.)

The problem is, the <label> element’s for is pointing at consent, which is the ID of the component.  The actual thing that should be targeted is the <input> element with the ID of setting .  We can’t just change the markup to <label for="setting"> because that <input> is trapped in the Shadow tree, where none in the Light beyond may call for it.  So it just plain old doesn’t work.

Under the Reference Target proposal, one way to fix this would look something like this in HTML:

 <label for="consent">I agree to join your marketing email list for some reason</label>
<sp-checkbox id="consent">
	<template shadowRootReferenceTarget="setting">
		<input id="setting" type="checkbox" aria-checked="indeterminate">
		<span id="box"></span>	
	</template> </sp-checkbox> 

With this markup in place, if someone clicks/taps/otherwise activates the label, it points to the ID consent .  That Shadowed component takes that reference and redirects it to an effective target  —  the reference target identified in its shadowRootReferenceTarget attribute.

You could also set up the reference with JavaScript instead of an HTML template:

 <label for="consent">I agree to join your marketing email list for some reason</label>
<sp-checkbox id="consent"></sp-checkbox> 
class SpecialCheckbox extends HTMLElement {
	checked = "mixed";
	constructor() {
		super();
		this.shadowRoot_ = this.attachShadow({ 
			referenceTarget: "setting"
		});
		
		// lines of code to Make It Go
	
	}
} 

Either way, the effective target is the <input> with the ID of setting .

This can be used in any situation where one element targets another, not just with for .  The form and list attributes on inputs would benefit from this.  So, too, would the relatively new popoverTarget and commandFor button attributes.  And all of the ARIA targeting attributes, like aria-controls and aria-errormessage and aria-owns as well.

If reference targets are something you think would be useful in your own work, please give it a try in Chrome or Safari or both, to see if your use cases are being met.  If not, you can leave feedback on issue 1120 to share any problems you run into.  If we’re going to have a Shadow DOM, the least we can do is make it as accessible and useful as possible.


Add Your Thoughts

Meyerweb dot com reserves the right to edit or remove any comment, especially when abusive or irrelevant to the topic at hand.

HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <em> <i> <q cite=""> <s> <strong> <pre class=""> <kbd>


if you’re satisfied with it.

Comment Preview