DEV Community 👩‍💻👨‍💻

Bryan Ollendyke
Bryan Ollendyke

Posted on

Targeting CSS Shadow Parts via URL search params

Yeah I know; your jelly you didn't think to mash those words together for great SEO. No, I assure you it's a real thing courtesy of this fun issue came as an idea from Paul Hibbits, an educator who loves Doxify / GravCMS. The idea was to be able to let users (or the developer) send links to people with parts of the UI disabled. This has a few possible use-cases:

  • Quick A/B test of thing vs not thing
  • Allow removing share links and other distractions
  • Allow for removing parts of the UI when embedding in an iframe

In order to achieve this, I mixed together some interesting solutions. First, we allow a URL search parameter like this welcome-page?disable-features=footer,site-menu-content. We can parse this into a string like so

const urlParams = new URLSearchParams(;
const disableFeatures = urlParams.get("disable-features");
if (disableFeatures != null) {
  this.disableFeatures = disableFeatures;
Enter fullscreen mode Exit fullscreen mode

This allows us to set the internal disableFeatures property in our web component based on the URL's search location. In LitElement we then reflect that attribute so that we can do CSS selectors like this haxcms-site-builder[disable-features="thing"].

Understanding *=

Reading the Moz Doc page on attribute selectors we see a *= selector which says:

Represents elements with an attribute name of attr whose value contains at least one occurrence of value within the string.

This means that if we have things,and,stuff we can match on *="and" successfully. Using this knowledge, We can create a selector like: haxcms-site-builder[disable-features*="site-menu-content"] and successfully target that URL condition.

Show me the Shadow Parts

The ::part syntax + attribute, is a relative newcomer to HTML spec. It allows for targeting parts of elements that lay within shadowRoots of other elements in order to provide specific styling.

haxcms-site-builder[disable-features*="site-menu"] .haxcms-theme-element::part(site-menu)

Combining these approaches we get a solution like so which can successfully allow (smart) users to target and disable parts of the UI via the URL parameter while safely only allowing the targeting of ones we allow.

TLDR the fun video

You got it

The full CSS selector

haxcms-site-builder[disable-features*="site-menu"] .haxcms-theme-element::part(site-menu),
haxcms-site-builder[disable-features*="page-breadcrumb"] .haxcms-theme-element::part(page-breadcrumb),
haxcms-site-builder[disable-features*="print-branch-btn"] .haxcms-theme-element::part(print-branch-btn),
haxcms-site-builder[disable-features*="rss-btn"] .haxcms-theme-element::part(rss-btn),
haxcms-site-builder[disable-features*="git-corner-btn"] .haxcms-theme-element::part(git-corner-btn),
haxcms-site-builder[disable-features*="search-btn"] .haxcms-theme-element::part(search-btn),
haxcms-site-builder[disable-features*="site-menu-content"] .haxcms-theme-element::part(site-menu-content),
haxcms-site-builder[disable-features*="footer"] .haxcms-theme-element::part(footer),
haxcms-site-builder[disable-features*="qr-code-btn"] .haxcms-theme-element::part(qr-code-btn),
haxcms-site-builder[disable-features*="right-col"] .haxcms-theme-element::part(right-col),
haxcms-site-builder[disable-features*="left-col"] .haxcms-theme-element::part(left-col)
  display: none !important;
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.