Domínio .COM.BR GRÁTIS a partir do período anual - Toque e garanta agora Seta para garantir domínio grátis no plano anual.

Web Components: como criar elementos reutilizáveis que funcionam em qualquer lugar

O problema que todo desenvolvedor frontend já enfrentou Você cria um botão perfeito em React para um projeto. Semanas depois, precisa do mesmo botão em um projeto Vue. Depois, em...

Blog dia

O problema que todo desenvolvedor frontend já enfrentou

Você cria um botão perfeito em React para um projeto. Semanas depois, precisa do mesmo botão em um projeto Vue. Depois, em uma página simples sem framework. E de repente você está mantendo três versões do mesmo componente em três bases de código diferentes.

Esse é o problema central do desenvolvimento de interfaces modernas: componentes são presos ao ecossistema em que foram criados. Um componente React não funciona em Vue. Um componente Angular não funciona em Svelte. Cada framework fala uma língua diferente.

Os Web Components existem para resolver exatamente isso. São uma coleção de APIs nativas do navegador, sem framework, sem dependência, que permitem criar elementos HTML customizados, reutilizáveis e encapsulados que funcionam em qualquer contexto: React, Vue, Angular, ou HTML puro.

Neste artigo, você vai entender o que são Web Components, como funcionam as três tecnologias que os compõem, como criar seu primeiro componente do zero e quando faz sentido usá-los.

O que são Web Components?

Web Components não é uma tecnologia única, é um conjunto de quatro padrões nativos do navegador que trabalham juntos:

  1. Custom Elements: permite definir suas próprias tags HTML (<meu-botao>, <card-produto>)
  2. Shadow DOM: encapsula o estilo e a estrutura do componente, isolando-o do restante da página
  3. HTML Templates: define marcação reutilizável que não é renderizada até ser ativada
  4. ES Modules: permite importar e exportar componentes como módulos JavaScript (padrão atual da plataforma)

Juntos, esses padrões permitem escrever algo assim:

<card-produto
  nome="Tênis Minimalista"
  preco="R$ 299"
  imagem="tenis.jpg">
</card-produto>

E esse elemento funciona em qualquer página HTML, independentemente de qual framework, ou nenhum, está sendo usado.

Como funciona cada tecnologia

Custom Elements

Custom Elements é a espinha dorsal dos Web Components. Você define uma classe JavaScript que estende HTMLElement e registra uma nova tag no navegador usando customElements.define().

class MeuBotao extends HTMLElement {
  connectedCallback() {
    this.innerHTML = `<button>${this.getAttribute('label')}</button>`;
  }
}

customElements.define('meu-botao', MeuBotao);

A partir daí, você pode usar <meu-botao label="Clique aqui"></meu-botao> em qualquer HTML e o navegador sabe como renderizá-lo.

Os ciclos de vida do Custom Element são os momentos em que o navegador chama métodos específicos da sua classe:

  • connectedCallback(): quando o elemento é inserido no DOM
  • disconnectedCallback(): quando o elemento é removido do DOM
  • attributeChangedCallback(): quando um atributo observado muda de valor
  • adoptedCallback(): quando o elemento é movido para um novo documento

Shadow DOM

O Shadow DOM cria um DOM separado e encapsulado dentro do seu componente. Estilos definidos dentro do Shadow DOM não vazam para fora, e estilos externos não entram, uma solução real para o problema de colisão de CSS em projetos grandes.

class CardProduto extends HTMLElement {
  connectedCallback() {
    // Cria a shadow root
    const shadow = this.attachShadow({ mode: 'open' });

    shadow.innerHTML = `
      <style>
        /* Este CSS só afeta o componente, nunca o restante da página */        .card {
          border: 1px solid #e0e0e0;
          border-radius: 8px;
          padding: 16px;
          font-family: sans-serif;
        }
        h2 { font-size: 18px; margin: 0 0 8px; }
        .preco { color: #2e7d32; font-weight: bold; }
      </style>

      <div class="card">
        <h2>${this.getAttribute('nome')}</h2>
        <p class="preco">${this.getAttribute('preco')}</p>
      </div>
    `;
  }
}

customElements.define('card-produto', CardProduto);

O parâmetro mode: 'open' significa que o Shadow DOM ainda pode ser acessado via JavaScript externo. mode: 'closed' torna o encapsulamento total, nem o JavaScript externo consegue acessar o interior do componente.

HTML Templates

O elemento <template> define marcação que o navegador analisa mas não renderiza. É como um molde que fica em espera até ser clonado e inserido no DOM.

<template id="card-template">
  <style>
    .card { padding: 16px; border-radius: 8px; }
  </style>
  <div class="card">
    <slot name="titulo"></slot>
    <slot name="conteudo"></slot>
  </div>
</template>

O elemento <slot> é o mecanismo de composição, define onde o conteúdo passado pelo usuário do componente vai ser inserido.

class CardTemplate extends HTMLElement {
  connectedCallback() {
    const template = document.getElementById('card-template');
    const clone = template.content.cloneNode(true);
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.appendChild(clone);
  }
}

Uso no HTML:

<card-template>
  <span slot="titulo">Meu Card</span>
  <p slot="conteudo">Conteúdo flexível aqui.</p>
</card-template>

Exemplo completo: um componente de alerta reutilizável

Vamos construir um componente <alerta-mensagem> que exibe mensagens de sucesso, erro ou aviso com estilos encapsulados, e que funciona em qualquer projeto.

Uso em JavaScript:

class AlertaMensagem extends HTMLElement {
  static get observedAttributes() {
    return ['tipo', 'mensagem'];
  }

  connectedCallback() {
    this.render();
  }

  attributeChangedCallback() {
    this.render();
  }

  render() {
    const tipo = this.getAttribute('tipo') || 'info';
    const mensagem = this.getAttribute('mensagem') || '';

    const cores = {
      sucesso: { fundo: '#e8f5e9', borda: '#2e7d32', texto: '#1b5e20' },
      erro:    { fundo: '#ffebee', borda: '#c62828', texto: '#b71c1c' },
      aviso:   { fundo: '#fff8e1', borda: '#f57f17', texto: '#e65100' },
      info:    { fundo: '#e3f2fd', borda: '#1565c0', texto: '#0d47a1' },
    };

    const cor = cores[tipo] || cores.info;

    if (!this.shadowRoot) {
      this.attachShadow({ mode: 'open' });
    }

    this.shadowRoot.innerHTML = `
      <style>
        .alerta {
          padding: 12px 16px;
          border-left: 4px solid ${cor.borda};
          background-color: ${cor.fundo};
          color: ${cor.texto};
          border-radius: 4px;
          font-family: sans-serif;
          font-size: 14px;
          line-height: 1.5;
        }
      </style>
      <div class="alerta" role="alert">${mensagem}</div>
    `;
  }
}

customElements.define('alerta-mensagem', AlertaMensagem);

Uso em HTML puro:

<alerta-mensagem tipo="sucesso" mensagem="Cadastro realizado com sucesso!"></alerta-mensagem>
<alerta-mensagem tipo="erro" mensagem="Ops! Algo deu errado. Tente novamente."></alerta-mensagem>

Uso em React:

// React 19+ tem suporte nativo completo a Web Components
function FormularioCadastro() {
  return (
    <div>
      <alerta-mensagem tipo="aviso" mensagem="Preencha todos os campos obrigatórios."></alerta-mensagem>
    </div>
  );
}

Uso em Vue:

<template>
  <alerta-mensagem tipo="info" mensagem="Sua sessão expira em 5 minutos."></alerta-mensagem>
</template>

O mesmo componente, o mesmo arquivo JavaScript, funcionando em três contextos completamente diferentes.

Quando usar Web Components?

Web Components não são a solução para tudo, como qualquer tecnologia, brilham em contextos específicos.

Use Web Components quando:

  • Você precisa compartilhar componentes entre projetos com frameworks diferentes
  • Está construindo um design system ou biblioteca de componentes para uma organização
  • Quer criar widgets embarcáveis (um chat, um player de áudio, um formulário) que qualquer site pode incluir com uma tag
  • Precisa de encapsulamento real de estilos sem depender de CSS Modules ou soluções de framework
  • O projeto precisa durar muito tempo, Web Components são padrão do navegador e não vão quebrar com atualizações de framework

Considere frameworks quando:

  • O projeto é novo e toda a equipe usa o mesmo framework
  • Você precisa de reatividade avançada e gerenciamento de estado complexo
  • O ecossistema de plugins e ferramentas do framework é importante para o projeto
  • A equipe não tem familiaridade com APIs nativas do navegador

Web Components e frameworks: parceiros, não concorrentes

Uma dúvida comum: “Se uso React ou Vue, ainda faz sentido aprender Web Components?”

Sim, e cada vez mais. O padrão atual do mercado para grandes organizações é usar Web Components para o design system base (botões, inputs, cards, modais) e os frameworks para a lógica de aplicação (roteamento, estado, integração com APIs).

Isso significa que o time de design de sistema entrega um <ds-button> que funciona em todos os projetos da empresa, independentemente do framework que cada time usa. É a melhor solução para consistência visual em escala.

Empresas como Google (Material Web), Adobe (Spectrum Web Components) e Salesforce (Lightning Web Components) adotam exatamente esse modelo.

Ferramentas que facilitam o desenvolvimento

Criar Web Components com JavaScript puro funciona, mas algumas ferramentas reduzem o código repetitivo:

Lit: biblioteca criada pelo Google que adiciona reatividade, templates declarativos e decorators aos Web Components nativos. É a escolha mais popular para quem quer produtividade sem abrir mão dos padrões nativos.

Stencil: compilador criado pelo time do Ionic que gera Web Components otimizados com TypeScript. Ótimo para design systems corporativos.

Shoelace / Spectrum / Material Web: bibliotecas prontas de componentes construídas em Web Components. Se você não precisa criar do zero, pode usar uma dessas como base.

Compatibilidade com navegadores

Todos os navegadores modernos (Chrome, Firefox, Safari, Edge) suportam Web Components sem necessidade de polyfills. O suporte é estável e consistente desde 2020.

Se o seu projeto precisa suportar navegadores muito antigos (IE11, por exemplo), existem polyfills disponíveis, mas esse cenário é cada vez mais raro.

Conclusão: o padrão que sobrevive aos frameworks

Frameworks vêm e vão. jQuery dominou, depois AngularJS, depois React, e agora dividimos atenção entre React, Vue, Svelte, Astro e outros. Cada ciclo, código que dependia de uma tecnologia específica precisou ser reescrito.

Web Components são diferentes: são padrão do navegador, especificados pelo W3C e implementados nativamente em todos os motores modernos. Código escrito hoje com Web Components vai funcionar em 10 anos sem nenhuma atualização.

Para quem quer construir interfaces que realmente duram, design systems, bibliotecas de componentes, widgets embarcáveis, Web Components são a fundação mais sólida disponível hoje.

Você pode gostar também:

Capa Blog O Verdadeiro Gargalo das Aplicações Modernas Não é CPU: É Latência

Hospedagem Web

O Verdadeiro Gargalo das Aplicações Modernas Não é CPU: É Latência

Durante anos olhamos para o lugar errado. Quando uma aplicação ficava lenta, a explicação parecia óbvia: faltava processamento. A solução...

BLOG

Hospedagem Web

Shadow AI e Vazamento de Dados: Como Proteger a Infraestrutura da sua Empresa na Era dos Modelos Públicos

A rápida popularização das ferramentas públicas de Inteligência Artificial generativa trouxe consigo uma revolução indiscutível na produtividade corporativa de empresas...

BLOG

Hospedagem Web

AI-Driven DevOps: Como o Monitoramento Preditivo Está Matando os Alertas de Madrugada

Para qualquer profissional de infraestrutura de TI, desenvolvedor ou administrador de sistemas, poucas situações causam tanto desgaste físico e estresse...