Skip to content

Shadow DOM Style Guide

Benny Powers edited this page Jul 7, 2022 · 7 revisions

Selectors

  • DO use simple selectors and IDs
    <header>
      <slot name="header"></slot>
      <button id="close-button">x</button>
    </header>
  • DO use class names for repeated elements or with classMap
    <header class=${classMap({ mobile, hasHeader })}>
      <slot name="header"></slot>
      <button id="close-button">x</button>
      <nav>${this.links.map(x => html`
        <a href=${x.href} class="header-link">${x.text}</a>`}
      </nav>
    </header>
  • DON'T use class names, unless (a) for repeated elements or (b) with classMap (for performance)
    <header class="rh-jazz-hands__header>
      <slot name="header"></slot>
      <button class="rh-jazz-hands__header__btn__close______x__________sm-sm-lg-sm">x</button>
    </header>

Parts

  • DO expose shadow parts for content containers
    <header part="header">
      <slot name="header"></slot>
    </header>
  • ⚠️ AVOID exposing shadow parts for 'layout containers'
    <div id="container" part="container">
      <header part="header">
        <slot name="header"></slot>
      </header>
    </div>

Slot Names

  • DO use "header" as a slot name
    <header part="header">
      <slot name="header"></slot>
    </header>
  • DO use single words, lower case
    <footer part="footer">
      <slot name="footer"></slot>
    </header>
  • ⚠️ AVOID using multiple words, but when you do, use lower-dash-case, and name left-to-right from the general to the specific
    <footer part="footer">
      <slot name="footer-prefix">
        <rh-icon icon="foot"></rh-icon>
      </slot>
      <slot name="footer"></slot>
    </header>
  • DON'T use "heading" as a slot name (use "header")
    <slot name="heading"></slot>
  • DON'T prefix with the element's name, or include the word slot
    <slot name="rh-header-head-slot"></slot>
  • DON'T use BEM or other complex naming conventions
    <slot name="rh-header--r--TopLeft__after"></slot>

Formatting

Keep attributes inline so long as the line doesn't exceed 80 chars.

For sets of attributes that break lines:

  • Place the ID inline with the tag name
  • Place attributes at 2 indents from the open tag
  • Group related attributes, preferably alphabetically
  • Place children at 1 indent from the open tag
  • For cleaner git diffs, try to use an attr that's unlikely to be removed as the last in a multiline set
<button id="close-button"
    aria-hidden=${String(this.disabled)}
    aria-label="close"
    ?hidden=${!this.open}
    @click=${this.onClick}>
  <slot name="close-button-text"></slot>
</button>
Clone this wiki locally