Targeting CSS Shadow Parts via URL search params
Tags: javascript, webcomponents, css, tutorial
Published: 2022-08-23 20:08:00

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](https://github.com/elmsln/issues/issues/609) 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

```js
const urlParams = new URLSearchParams(window.location.search);
const disableFeatures = urlParams.get("disable-features");
if (disableFeatures != null) {
  this.disableFeatures = disableFeatures;
}
```

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](https://developer.mozilla.org/en-US/docs/Web/CSS/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](https://developer.mozilla.org/en-US/docs/Web/CSS/::part), 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
{% embed https://youtu.be/kMMIcnOTuAI %}

## The full CSS selector
```css
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;
}
```