Is it possible to position nested shadow DOMs on top of each other?
With normal DOM, nested divs just stack by default:
.d1 {
width: 150px;
height: 150px;
background-color: lightseagreen;
}
.d2 {
width: 100px;
height: 100px;
background-color: darkslateblue;
}
.d3 {
width: 50px;
height: 50px;
background-color: lightgray;
}
<div class="container">
<div class="d1">
<div class="d2">
<div class="d3">
</div>
</div>
</div>
</div>
But with shadow DOM, how can this be done?
id = 0;
depth = 3;
customElements.define('box-component', class extends HTMLElement {
constructor() {
super();
if (id > depth)
return;
this.id = id++;
var template = document.getElementById("box-template");
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = template.innerHTML;
// The only goal of all of the following boilerplate is to set 'exportparts' attribute,
// such that each parent exports its *descendants* (not just *children*) parts.
// This is done by accessing the shadow dom of the child from its parent.
// (note: the outermost component doesn't need to export its parts)
if (id == 0)
return;
const parts = [...this.shadowRoot.children]
.filter(elem => elem.getAttribute('part'))
let thisExportParts = null;
let childExportParts = null;
thisExportParts = parts.map(elem => [
[elem.getAttribute('part'), `${elem.getAttribute('part')}${this.id}`].join(':')
].join(','));
if (this.shadowRoot && this.shadowRoot.children) {
const childShadowRoot =
[...this.shadowRoot.children].filter(elem => elem.shadowRoot)[0];
if (childShadowRoot) {
const fullChildExportParts = childShadowRoot.getAttribute('exportparts');
if (fullChildExportParts) {
childExportParts = fullChildExportParts.split(',').map(part => {
return part.includes(':') ? part.split(':')[1] : part;
}).join(',');
}
}
}
this.setAttribute('exportparts', [thisExportParts, childExportParts].filter(_ => _).join(','));
}
});
box-component::part(box1) {
width: 150px;
height: 150px;
background-color: lightseagreen;
}
box-component::part(box2) {
width: 100px;
height: 100px;
background-color: darkslateblue;
}
box-component::part(box3) {
width: 50px;
height: 50px;
background-color: lightgray;
}
<template id="box-template">
<style>
</style>
<div part="box"></div>
<box-component></box-component>
</template>
<box-component class="container"></box-component>
exportparts
– Dalt