🟑 MediumFix the CodeπŸ› Debug Challenge

Shadow DOM styles leaking via CSS custom properties

Buggy Code β€” Can you spot the issue?

class ThemedCard extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'closed' });
    shadow.innerHTML = `
      <style>
        /* Tries to isolate styles */
        .card {
          background: var(--card-bg, white); /* CSS var leaks through! */
          color: var(--card-text, black);
          padding: 16px;
        }
      </style>
      <div class="card"><slot></slot></div>
    `;
  }
}

// External page sets these β€” they WILL affect the component
// despite 'closed' shadow root!
// :root { --card-bg: red; --card-text: yellow; }

Fixed Code

class ThemedCard extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'closed' });
    shadow.innerHTML = `
      <style>
        /* Documented theming API β€” CSS vars are intentional leak points */
        :host {
          /* Define defaults for your theming API */
          --card-bg: white;
          --card-text: black;
          --card-padding: 16px;
        }

        .card {
          /* Use the vars β€” consumers can override these via :root or :host */
          background: var(--card-bg);
          color: var(--card-text);
          padding: var(--card-padding);
          /* Hard-coded styles that consumers CANNOT change: */
          border-radius: 8px;
          box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
      </style>
      <div class="card"><slot></slot></div>
    `;
  }
}
// Usage: --card-bg is your documented theming hook
// Structural styles (radius, shadow) are truly encapsulated

Bug Explained

Bug: Shadow DOM blocks regular CSS selectors and class names. But CSS custom properties (variables) inherit through shadow boundaries by design β€” they're meant to be the theming API.

Explanation: CSS custom properties inherit through shadow boundaries β€” this is intentional. Use this as your theming API: document which variables you support. Hard-code structural styles that consumers shouldn't touch.

Key Insight: Shadow DOM encapsulates regular CSS but CSS custom properties inherit through. This is by design β€” custom properties ARE the theming API for web components. Embrace this, don't fight it.

More Fix the Code Debug Challenges

🟒 EasyDeep clone breaks with JSON.stringifyβ†’πŸŸ‘ Mediumthis lost in event listenerβ†’πŸŸ‘ MediumObject mutation in array mapβ†’πŸ”΄ HardPrototype pollution vulnerabilityβ†’

Practice spotting bugs live β†’

38 debug challenges with AI hints

πŸ› Try Debug Lab