How to Check If a Browser Supports Shadow Dom

How to check if a browser supports shadow DOM

One simple feature test would be:

if (document.head.createShadowRoot || document.head.attachShadow) {
// I can shadow DOM
} else {
// I can't
}

This will work even if you include the script in the head section and assumes no malicious scripts were added prior to yours (a safe assumption).

Currently, Chrome, Opera, and derived browsers (like Android browsers) support it.
For more information, visit: https://caniuse.com/#feat=shadowdomv1 and http://caniuse.com/#feat=shadowdom

Check support for shadow dom v1 in browser using javascript

As explained in Shadow DOM v1 presentation:

To feature detect shadow DOM, check for the existence of attachShadow:

const supportsShadowDOMV1 = !!HTMLElement.prototype.attachShadow;

There's no performance concern unless you deal with thousands of Shadow DOM at the same time.

How to check if a browser supports Polymer?

Short answer:

Quick test: Firefox 38.0.5 alerts "No", while Chrome 44.0.2403.130 m alerts "Yes"

function supportsPolymer() {  return 'content' in document.createElement('template') && 'import' in document.createElement('link') && 'registerElement' in document && document.head.createShadowRoot;}
if(supportsPolymer()) { //Good to go alert("Yes"); } else { //Is not supported alert("No"); }

How do we detect if a shadow root was made with v0 or v1 API?

I went a similar direction to Hayato Ito's answer. However, instead of creating slot elements, I target content elements. I was not able to find a way to detect the version off of any API method detection.

I targeted content elements since content elements do not natively have events for them, unlike slotchange on the slot event, which hopefully could lead to a small performance boost. Plus the function returns v1 a little faster if the browser does not support v0 at all.

function shadowType(shadowRoot) {
if (!shadowRoot) {
// closed shadow dom does not appear to have a shadowRoot...
// It could be assumed that it is v1, but for now return undefined
return;
}

const content = document.createElement('content');
// In browsers that support v1, but not v0 (ex: Safari)
if (!content.getDistributedNodes) {
return 'v1';
}

content.setAttribute('select', 'test-shadow-dom-version');
shadowRoot.appendChild(content);

const testElement = document.createElement('test-shadow-dom-version');
shadowRoot.host.appendChild(testElement);
const type = (content.getDistributedNodes().length) ? 'v0' : 'v1';
shadowRoot.removeChild(content);
shadowRoot.host.removeChild(testElement);

return type;
}

It definitely feels like a "hack", because of need to append random dom :(. I did test this in Chrome, Firefox, Safari, IE11, and Edge. I tested components made using the webcomponentsjs (v0) polyfill, and it correctly returned v0 for each component. I also tested those same browsers with just the shadydom (v1) polyfill with components created with the v1 spec, and received v1 in all of those browsers.

Check if element contains #shadow-root

If you want to check whether or not a specific element is hosting an open Shadow DOM element, you can do the following:

var el = document.querySelector('#some-element');
if (!!el.shadowRoot) {
// Then it is hosting an OPEN Shadow DOM element
}

You can also get the Shadow DOM element, and then operate on it like a normal node:

var shadowEl = el.shadowRoot;
// And for example:
console.log(shadowEl.innerHTML);

Here is an example that works in the latest version of Chrome:

const div = document.querySelector('div');
const p = document.querySelector('p');

const shadowRoot = p.attachShadow({mode: 'open'})
shadowRoot.textContent = 'A Shadow DOM Paragraph. I overrode the content specified!';

console.log('Paragraph has Shadow DOM:', !!p.shadowRoot); // true
console.log('Div has Shadow DOM:', !!div.shadowRoot); // false
<div>A Normal Div</div>
<p>A Normal Paragraph</p>

Firefox: shadow-DOM compatibility

A lot less code and more control if you create the SVG dynamically

with a W3C standard Web Component (supported in all modern Browsers)

Sample Image

<style>
svg { background: pink }
path { stroke: blue }
</style>
<game-board>
<hexagon x="46" y="0" />
<hexagon x="138" y="0" />
<hexagon x="92" y="26" />
<hexagon x="138" y="52" />
<hexagon x="92" y="78" />
<hexagon x="184" y="26" />
</game-board>
<script>
customElements.define("game-board", class extends HTMLElement {
connectedCallback() {
setTimeout(() => {
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.innerHTML = `<style>` +
`.hexagon{fill:red}.hexagon:hover{filter:grayscale(100%);cursor:pointer}` +
`.hexclicked{fill:green}` +
`</style>`;
svg.append(...[...this.querySelectorAll("hexagon")].map(hex => {
let path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("d", `m${hex.attributes.x.value} ${hex.attributes.y.value} 15 26-15 26-30 0-15-26 15-26z`);
path.classList.add("hexagon");
path.onclick = (evt) => path.classList.toggle("hexclicked");
return path;
}));
this.replaceWith(svg);
})
}
})
</script>

How can I interact with browser-inserted Shadow DOM content in an input field?

There's no way to interact with the shadow DOM. The whole purpose of a shadow tree is to isolate functionality, behavior, and styles from the outside world - even if the mode is "open". If the author of a particular component wants you to be able to control the behavior or styles, they will provide an API for doing so. If the author does not provide an API for it, they don't want you mucking around with it.

When it comes to using form fields, my rule of thumb is to always follow one of these rules:

  1. Use the browser form fields as they come - don't try to get too fancy with it as you will likely break accessibility, keyboard navigation, autofill and other things you didn't intend to break. Anything more than styling the borders, background, and padding is usually not a good idea. You might think it is, but I can likely prove you wrong by showing how you broke some default behavior.

For example, automatically displaying a time picker would take focus away from what the user was doing. Maybe the screen reader was reading some text, or a power user was tabbing through the navigation using their keyboard, and then all the sudden they're on the time picker when they didn't want to be.


  1. Use a widely tested UI library. The authors of popular UI libraries have taken into account all of the behaviors and such so as to provide a smooth and predictable experience for users. Use these when you want to do things like automatically display a date/time picker or some other fancy behavior you probably shouldn't be doing but are going to anyways.

Whatever you do, don't try to roll your own fancy form controls. I guarantee you will piss off one of your users.

How to view html and css associated with shadow dom

To see the Shadow DOM in Dartium and Chrome, you must enable it in DevTools.

  1. Right-click on your page and select "Inspect Element" to bring up DevTools

  2. Click the Settings gear in the top-right corner of the DevTools window

  3. Under the "Elements" heading, find and enable the "Show Shadow DOM" checkbox.

Now you should see #document-fragments in the Elements pane of DevTools. Those are your Shadow DOM.

Is there a way to view the Shadow DOM in IE11?

IE11 doesn't support Shadow DOM.

Better browsers (like Chrome) use something very like Shadow DOM to build every component that you see and can expose that as part of this new (and still very bleeding edge) feature.

I'm not sure on IE11, but in older versions of IE the rendering engine always used the Windows OS components for everything. I'm not sure they actually use the HTML engine to build components even now, but even if they do they'd have to enable accessing those internals.



Related Topics



Leave a reply



Submit