Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Created August 23, 2020 23:54
Show Gist options
  • Save tomhodgins/53d9f7d109c92f49b8dd2e693e95a4c2 to your computer and use it in GitHub Desktop.
Save tomhodgins/53d9f7d109c92f49b8dd2e693e95a4c2 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Deep Combinator</title>
<style>
[--deep] h1,
[--deep] span {
color: red;
}
</style>
<script type=module>
import jsincss from 'https://unpkg.com/jsincss/index.vanilla.js'
import {selector, process} from 'https://unpkg.com/cssomtools'
import {parseACommaSeparatedListOfComponentValues} from 'https://tomhodgins.github.io/parse-css/index.js'
// Find and support deep selectors
function deepCombinator() {
const lightCSS = []
// Find all rules with [--deep]
process(selector('[--deep]'), rule => {
// Split by selector lists to find relevant [--deep]-using selectors
const selectors = parseACommaSeparatedListOfComponentValues(rule.selectorText)
.map(selector => selector.map(token => token.toSource()).join('').trim())
.filter(selector => selector.includes('[--deep]'))
// For each selector in selector list to include [--deep]…
selectors
.map(selector => selector.split(/\s*\[--deep\]\s*/))
.forEach(([before, after]) => {
const shadows = [...document.querySelectorAll(before || '*')].filter(tag =>
tag.shadowRoot
)
// Find shadowDOM's and apply properties inside
shadows.forEach(shadow =>
shadow.shadowRoot.querySelectorAll(after).forEach(child =>
[...rule.style].forEach(property =>
child.style[property] = rule.style[property]
)
)
)
})
// Output a copy to light DOM styles without [--deep]
lightCSS.push(
`
${
selectors
.map(selector => selector.replace(/\s*\[--deep\]\s*/, ''))
.join(', ')
} {
${
[...rule.style]
.map(property => `${property}: ${rule.style[property]}`)
.join(';')
}
}
`
)
})
return lightCSS.join('')
}
// Run on 'load' and 'reprocessDeepCombinator' events on window
jsincss(
() => deepCombinator(),
window,
['load', 'reprocessDeepCombinator']
)
// Declarative <shadow-dom> support
class ShadowDom extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({mode: 'open'})
shadow.append(...this.childNodes)
}
}
customElements.define('shadow-dom', ShadowDom)
</script>
<div>
<h1>Light DOM</h1>
<span>Light DOM</span>
<shadow-dom>
<h1>ShadowDOM</h1>
<span>ShadowDOM</span>
</shadow-dom>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment