← Back to Home

Example 3: User Card with Shadow DOM

Learn about Shadow DOM encapsulation and scoped styles

Live Demo

These user cards use Shadow DOM for style encapsulation:

JavaScript Code

class UserCard extends HTMLElement {
  constructor() {
    super();
    // Attach shadow DOM for encapsulation
    this.attachShadow({ mode: 'open' });
  }

  // Observed attributes for reactivity
  static get observedAttributes() {
    return ['name', 'role', 'avatar'];
  }

  connectedCallback() {
    this.render();
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (oldValue !== newValue) {
      this.render();
    }
  }

  render() {
    this.shadowRoot.innerHTML = `
      <style>
        .card {
          display: flex;
          align-items: center;
          gap: 1rem;
          padding: 1.5rem;
          background: white;
          border-radius: 0;
          border: 1px solid #e8e3db;
          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
        }
        
        .avatar {
          width: 64px;
          height: 64px;
          border-radius: 0;
          border: 3px solid #2d1b69;
        }
        
        .name {
          font-size: 1.25rem;
          font-weight: 600;
          margin: 0;
        }
      </style>
      <div class="card">
        <img class="avatar" src="\${this.getAttribute('avatar')}">
        <div class="info">
          <h3 class="name">\${this.getAttribute('name')}</h3>
          <p class="role">\${this.getAttribute('role')}</p>
        </div>
      </div>
    `;
  }
}

customElements.define('user-card', UserCard);

HTML Usage

<user-card 
  name="Sarah Johnson" 
  role="Frontend Developer"
  avatar="https://ui-avatars.com/api/?name=Sarah+Johnson">
</user-card>

Key Concepts

Why Shadow DOM?

Try it yourself:

Open the browser console and type:

const card = document.querySelector('user-card');
card.setAttribute('name', 'Your Name');
card.setAttribute('role', 'Your Role');

Documentation

Next Step