Skip to content

Instantly share code, notes, and snippets.

@jonathantneal
Last active December 8, 2022 08:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathantneal/f88e2a0f162a712bebbc95be8f00cbc5 to your computer and use it in GitHub Desktop.
Save jonathantneal/f88e2a0f162a712bebbc95be8f00cbc5 to your computer and use it in GitHub Desktop.
ShadowRoot QSA ::part() Polyfill

ShadowRoot QSA Part Polyfill

This polyfill lets you use CSS ::part() selectors in querySelector and querySelectorAll on ShadowRoot.

The script is 442 bytes minified, 300 bytes gzipped.

Usage

Include this polyfill somewhere in your document.

<script src="https://gist.githack.com/jonathantneal/f88e2a0f162a712bebbc95be8f00cbc5/raw/c1db6fdcc9d3ee4c2e2a0d080a695142ba4a30c1/2.ShadowRootQSAPartPolyfill.js"></script>

That’s it! Start using ::part()!

const host = document.createElement('div')
const root = host.attachShadow({ mode: 'open' })

root.innerHTML = '<p part="super fun">'

root.querySelector('::part(super)')     // <p part="super fun">
root.querySelector(':host::part(fun)')  // <p part="super fun">
root.querySelector('::part(super fun)') // <p part="super fun">
/** ShadowRoot QSA Part Polyfill @version 0.1.1 @license CC0-1.0 @author Jonathan Neal (https://github.com/jonathantneal) */
((
/** Host HTMLElement, created to test querySelector support for ::part(). */
host = document.createElement('p'),
/** ShadowRoot, created to test querySelector support for ::part(). */
root = host.attachShadow({ mode: 'open' }),
/** HTML used to test querySelector support for ::part(). */
html = root.innerHTML = '<p part=p>',
/** Whether ShadowRoot querySelector supports ::part(). */
does = root.querySelector('::part(p)'),
/** Regular Expression used to match CSS ::part() selectors. */
part = /^(:host(.*))?::part\(([^)]+)\)/g,
/** Returns the selector with ::part()s replaced with [part~=""]s. */
call = (_0, _1, $2 = '', $3) => $2 + $3.trim().split(/\s+/).map(join),
/** Returns the given ::part() name as an attribute selector. */
join = part => `[part~=${JSON.stringify(part)}]`,
/** Native querySelector functions. */
{ querySelector, querySelectorAll } = root
// polyfill ShadowRoot if querySelector does not support ::part()
) => does || Object.assign(ShadowRoot.prototype, {
querySelector(selectors) {
return querySelector.call(this, selectors.replace(part, call))
},
querySelectorAll(selectors) {
return querySelectorAll.call(this, selectors.replace(part, call))
},
}))()
((e=document.createElement('p'),t=e.attachShadow({mode:'open'}),r=(t.innerHTML='<p part=p>'),l=t.querySelector('::part(p)'),a=/^(:host(.*))?::part\(([^)]+)\)/g,o=((e,t,r='',l)=>r+l.trim().split(/\s+/).map(p)),p=(e=>`[part~=${JSON.stringify(e)}]`),{querySelector:c,querySelectorAll:n}=t)=>{l||Object.assign(ShadowRoot.prototype,{querySelector(e){return c.call(this,e.replace(a,o))},querySelectorAll(e){return n.call(this,e.replace(a,o))}})})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment