HTML para JSX

className, htmlFor, estilos em objeto, comentários e tags void. Ideal para colar templates HTML em componentes React.

{{ t("htmlToJsxHint") }}

{{ htmlToJsx.message }}

Descrição

React foi criado por Jordan Walke no Facebook em 2011, apresentado internamente como FaxJS, e aberto ao público no JSConf de maio de 2013. A primeira reação da comunidade foi de ceticismo e, em muitos casos, rejeição aberta. JSX — a sintaxe que mistura HTML dentro de JavaScript — parecia uma heresia. A separação de HTML, CSS e JavaScript em arquivos diferentes era um princípio quase sagrado do desenvolvimento web desde os anos 2000. Colocar marcação dentro de funções JavaScript parecia um passo atrás de décadas de boas práticas.

A reviravolta foi rápida. Depois de poucos meses com React em produção, a maioria dos desenvolvedores concluiu que separar HTML de JS era uma separação de tecnologias — não de preocupações reais. Um componente de botão tem markup, estilo e comportamento, e ter tudo num único arquivo de componente tornava o código mais fácil de manter do que três arquivos separados em sincronia. JSX ganhou o debate pragmático. Hoje é raro encontrar um projeto React sem JSX como padrão, e o formato influenciou Solid.js, Preact, Qwik e outros frameworks.

O conversor desta página resolve o problema prático de migrar templates HTML existentes para JSX. As mudanças são sistemáticas: `class` vira `className` (porque `class` é palavra reservada em JavaScript), `for` em labels vira `htmlFor`, atributos multi-palavra como `tabindex` e `maxlength` viram camelCase (`tabIndex`, `maxLength`), estilos inline passam de string para objeto JavaScript, comentários HTML viram expressões JSX, e tags void como `<img>` recebem fechamento explícito `<img />` porque JSX segue regras de XML bem-formado.

Detalhamento técnico

Por que o JSX pareceu uma heresia e por que venceu mesmo assim

  • Antes do JSX, criar UIs com React puro exigia chamadas aninhadas a `React.createElement('div', {className: 'container'}, React.createElement('h1', null, 'Título'))`. Era funcionalmente correto, mas completamente ilegível para qualquer coisa além de um componente trivial. O JSX foi criado como açúcar sintático que o Babel compila para essas chamadas — mas a DX (experiência do desenvolvedor) é radicalmente diferente.
  • Vue, Angular e Svelte tomaram caminhos diferentes: Vue usa templates em HTML com diretivas (`v-if`, `v-for`), Angular usa templates com sintaxe própria e Svelte compila em JavaScript puro. JSX é a abordagem mais próxima de 'JavaScript puro com extensão sintática' — o que tanto atrai desenvolvedores JS quanto incomoda designers acostumados com HTML.
  • A reinterpretação de 'separação de responsabilidades' foi o argumento que virou o debate. O princípio original (HTML/CSS/JS em arquivos separados) separava tecnologias, não preocupações de produto. Um componente de modal tem lógica, estilo e markup que mudam juntos — separá-los em arquivos diferentes só cria acoplamento à distância.
  • JSX não é exclusivo do React. Solid.js usa JSX mas compila diferente (sem Virtual DOM). Preact é uma alternativa ao React com JSX compatível e 3 KB de tamanho. Qwik usa JSX com serialização de estado para hidratação parcial. Stencil.js usa JSX para web components nativos.
  • O Babel transforma JSX em JavaScript antes de qualquer execução. O compilador moderno do React (React 17+) não requer mais o import explícito de React em cada arquivo JSX — o transform é automático. TypeScript também suporta JSX nativamente com arquivos `.tsx`.

As regras de conversão HTML → JSX: um mapeamento sistemático

  • `class` → `className`: `class` é uma palavra reservada em JavaScript usada para definir classes ES6. Em JSX, o atributo correspondente é `className`. Esquecer essa conversão é o erro mais comum ao migrar templates.
  • `for` → `htmlFor`: O atributo `for` em `<label>` também é palavra reservada (loop `for` do JavaScript). Em JSX é `htmlFor`. Da mesma forma, `<input type="text">` sem atributos problemáticos não muda.
  • Atributos camelCase: `tabindex` → `tabIndex`, `maxlength` → `maxLength`, `readonly` → `readOnly`, `autofocus` → `autoFocus`, `crossorigin` → `crossOrigin`, `enctype` → `encType`. A regra é: se o atributo HTML tem hífen ou é multi-palavra com casing inconsistente, em JSX usa-se camelCase.
  • Estilos inline: `style="color: red; font-size: 16px"` → `style={{ color: 'red', fontSize: '16px' }}`. Propriedades CSS com hífen viram camelCase. Os valores são strings (exceto números sem unidade, como `zIndex: 10`). Note as chaves duplas: a externa `{}` é a interpolação JSX, a interna `{}` é o objeto JavaScript.
  • Tags void com fechamento explícito: `<img>`, `<input>`, `<br>`, `<hr>`, `<meta>`, `<link>` em HTML5 não precisam de fechamento. Em JSX, que segue regras de XML bem-formado, todas as tags devem ser fechadas: `<img />`, `<input />`, `<br />`. Sem isso, o Babel lança erro de parse.

Exemplo de Código

Tabela de conversão HTML → JSX
// ATRIBUTOS: HTML → JSX
// class="container"         → className="container"
// for="input-id"            → htmlFor="input-id"
// tabindex="0"              → tabIndex={0}
// maxlength="100"           → maxLength={100}
// readonly                  → readOnly
// autofocus                 → autoFocus

// ESTILOS INLINE:
// style="color:red"         → style={{ color: 'red' }}
// style="font-size:16px"    → style={{ fontSize: '16px' }}
// style="background-color"  → style={{ backgroundColor: '...' }}

// COMENTÁRIOS:
// <!-- comentário HTML -->  → {/* comentário JSX */}

// TAGS VOID:
// <img src="x.png">         → <img src="x.png" />
// <input type="text">       → <input type="text" />
// <br>                      → <br />
Card Bootstrap → Componente React
// HTML original (Bootstrap card)
// <div class="card" style="width: 18rem;">
//   <img src="img.jpg" class="card-img-top" alt="Descrição">
//   <div class="card-body">
//     <h5 class="card-title">Título do Card</h5>
//     <p class="card-text">Texto descritivo.</p>
//     <a href="#" class="btn btn-primary">Ação</a>
//   </div>
// </div>

function Card({ imagem, alt, titulo, texto, href }) {
  return (
    <div className="card" style={{ width: '18rem' }}>
      <img src={imagem} className="card-img-top" alt={alt} />
      <div className="card-body">
        <h5 className="card-title">{titulo}</h5>
        <p className="card-text">{texto}</p>
        <a href={href} className="btn btn-primary">
          Ação
        </a>
      </div>
    </div>
  );
}

Exemplo

<div class="box" tabindex="0">
  <img src="/a.png" alt="">
  <!-- ok -->
</div>

Perguntas frequentes

Para que serve esta ferramenta?

Ela roda 100% no seu navegador: útil para validar, formatar ou converter dados no dia a dia de desenvolvimento.

Meus dados são enviados a algum servidor?

O processamento é feito localmente via JavaScript. Não armazenamos o conteúdo que você cola nas caixas de texto.

Posso usar em produção ou para dados reais?

Use por sua conta e risco. Para segredos (senhas, tokens), prefira ambientes controlados e políticas da sua empresa. E lembre sempre de revisar os conteúdos gerados. Nunca confie cegamente nas coisas que vê na internet.