htmx: Interatividade Moderna Sem Escrever JavaScript

htmx: Interatividade Moderna Sem Escrever JavaScript

14 visualizações

Se você desenvolve para a web há alguns anos, provavelmente já passou por isto: você só queria um botão que carrega uma lista sem recarregar a página, e acabou com um projeto cheio de bundlers, gerenciadores de estado, hooks, rotas no cliente e centenas de megabytes em node_modules. A complexidade cresceu muito mais rápido do que o problema original.

É aí que entra o htmx. A ideia é simples e quase provocativa: e se o próprio HTML pudesse fazer requisições AJAX, trocar partes da página e lidar com transições, tudo isso apenas com atributos? Sem escrever uma linha de JavaScript, você ganha interatividade moderna e mantém a lógica no servidor, onde ela sempre foi mais fácil de testar, proteger e manter.

Neste artigo você vai conhecer o que é o htmx, seus principais atributos, as vantagens de adotá-lo e alguns exemplos práticos de código para começar hoje mesmo.

O que é o htmx?

O htmx é uma biblioteca JavaScript pequena, sem dependências, que estende o HTML com novos atributos. Com eles, qualquer elemento pode disparar requisições HTTP (GET, POST, PUT, PATCH, DELETE) em resposta a eventos e atualizar qualquer parte da página com o resultado.

O ponto central é que o servidor responde com HTML, e não com JSON. Em vez de o cliente receber dados e montar a interface, o servidor devolve o pedaço de HTML pronto e o htmx o encaixa no lugar certo. Essa abordagem é conhecida como HATEOAS na prática, ou "hypermedia-driven applications".

Para começar, basta incluir o script:

<script src="https://unpkg.com/htmx.org@2.0.4"></script>

Sem build, sem configuração. Pronto.

Os principais atributos

O htmx funciona com um conjunto enxuto de atributos. Estes são os mais importantes:

Atributos de requisição

Definem qual método HTTP usar e para onde enviar:

  • hx-get: faz uma requisição GET para a URL indicada
  • hx-post: faz uma requisição POST
  • hx-put, hx-patch, hx-delete: os demais verbos HTTP

hx-trigger: quando a requisição acontece

Define o evento que dispara a requisição. Por padrão, é click para botões e links, change para inputs e submit para formulários, mas você pode personalizar:

<input hx-get="/buscar" hx-trigger="keyup changed delay:500ms">

O exemplo acima só dispara a busca quando o valor mudou e o usuário parou de digitar por 500 ms (um debounce sem JavaScript). Também existem gatilhos como load, revealed (quando o elemento aparece na tela) e every 5s (polling).

hx-target: onde o resultado vai

Indica qual elemento receberá a resposta do servidor, usando um seletor CSS:

<button hx-get="/detalhes" hx-target="#painel">Ver detalhes</button> <div id="painel"></div>

hx-swap: como o conteúdo é inserido

Controla a estratégia de troca. Os valores mais usados:

  • innerHTML (padrão): substitui o conteúdo interno do alvo
  • outerHTML: substitui o próprio elemento
  • beforeend / afterbegin: adiciona ao fim ou ao início (ótimo para listas)
  • delete: remove o elemento
  • none: não troca nada

Outros atributos úteis

  • hx-indicator: mostra um indicador de carregamento durante a requisição
  • hx-confirm: exibe uma caixa de confirmação antes de enviar
  • hx-boost: transforma links e formulários comuns em requisições AJAX, deixando a navegação mais fluida
  • hx-push-url: atualiza a URL do navegador, mantendo o histórico funcionando
  • hx-vals e hx-include: enviam valores extras na requisição
  • hx-select: escolhe qual trecho da resposta será usado

Vantagens de usar o htmx

  1. Muito menos JavaScript. A maior parte das interações comuns (busca, paginação, formulários, modais, scroll infinito) vira apenas atributos HTML. Menos código significa menos bugs.
  2. Leve e sem dependências. A biblioteca tem cerca de 14 KB comprimida, contra centenas de KB de um framework típico com seu ecossistema.
  3. Zero etapa de build. Não há transpilação, bundler nem toolchain. Você edita, atualiza a página e vê o resultado.
  4. Lógica concentrada no servidor. Regras de negócio, validações e permissões ficam em um só lugar. Você evita duplicar modelos e validações entre front-end e back-end.
  5. Agnóstico de linguagem. Funciona com Python (Django, Flask, FastAPI), Go, Ruby on Rails, PHP/Laravel, Java, .NET, Node.js e qualquer outra stack que consiga devolver HTML.
  6. Curva de aprendizado suave. Se você sabe HTML, já sabe 80% do htmx. Não há conceitos como virtual DOM, estado reativo ou ciclo de vida de componentes.
  7. Melhor para SEO e acessibilidade. Como o HTML vem pronto do servidor e funciona bem com hx-boost, você mantém um comportamento próximo ao da web tradicional, com progressive enhancement.

Exemplos de código

1. Botão que carrega conteúdo

O "olá mundo" do htmx: clicar no botão busca um fragmento HTML e o coloca na página.

<button hx-get="/saudacao" hx-target="#resultado" hx-swap="innerHTML"> Clique aqui </button>
<div id="resultado"></div>

O servidor (por exemplo, em Flask) só precisa devolver um trecho de HTML:

from flask import 

Flask app = Flask(__name__) 

@app.route("/saudacao")
def saudacao(): 
    return "<p>Olá! Este conteúdo veio do servidor 🚀</p>"

2. Busca em tempo real

Um campo de pesquisa que filtra resultados enquanto o usuário digita:

<input
  type="search"
  name="q"
  placeholder="Buscar usuários..."
  hx-get="/usuarios/buscar"
  hx-trigger="keyup changed delay:400ms, search"
  hx-target="#lista-usuarios"
  hx-indicator="#carregando"
>

<span id="carregando" class="htmx-indicator">Buscando...</span>

<ul id="lista-usuarios">
  <!-- resultados aparecem aqui -->
</ul>

O valor do input (q) é enviado automaticamente como parâmetro. A classe htmx-indicator fica visível apenas enquanto a requisição está em andamento.

3. Formulário sem recarregar a página

Adicionando um item a uma lista, com o novo item inserido no final:

<form hx-post="/tarefas" hx-target="#tarefas" hx-swap="beforeend"
      hx-on::after-request="this.reset()">
  <input type="text" name="titulo" required>
  <button type="submit">Adicionar</button>
</form>

<ul id="tarefas"></ul>

O servidor responde apenas com o <li> novo:

@app.post("/tarefas")
def criar_tarefa():
    titulo = request.form["titulo"] # salvar no banco... 
    return f'<li>{escape(titulo)}</li>'
Importante: sempre escape o conteúdo vindo do usuário antes de devolvê-lo como HTML, para evitar XSS. A maioria dos motores de template faz isso por padrão.

4. Excluir com confirmação

<li id="tarefa-42">
  Estudar htmx
  <button
    hx-delete="/tarefas/42"
    hx-confirm="Tem certeza que deseja excluir?"
    hx-target="#tarefa-42"
    hx-swap="outerHTML">
    Excluir
  </button>
</li>

Se o servidor responder com um corpo vazio, o outerHTML remove o elemento da página.

5. Scroll infinito

O último item da lista carrega a próxima página quando se torna visível:

<tr hx-get="/produtos?pagina=2"
    hx-trigger="revealed"
    hx-swap="afterend">
  <td>Carregando mais...</td>
</tr>

Cada resposta do servidor traz as novas linhas e uma nova linha-gatilho apontando para a página seguinte.

6. Atualização automática (polling)

<div hx-get="/status" hx-trigger="every 5s">
  Status: carregando...
</div>

Quando o htmx não é a melhor escolha?

O htmx não é bala de prata. Ele brilha em aplicações centradas em conteúdo e formulários, como painéis administrativos, sistemas internos, e-commerces e CRUDs. Já em aplicações que exigem interface altamente interativa e com muito estado local no cliente (editores gráficos, planilhas online, jogos, apps com modo offline), um framework como React, Vue ou Svelte continua sendo uma escolha mais natural.

A boa notícia é que as duas abordagens convivem bem: muita gente usa htmx para a maior parte do sistema e reserva componentes JavaScript para os pontos que realmente precisam.

Conclusão

O htmx devolve ao HTML o poder que ele sempre deveria ter tido: o de ser, de fato, um hipertexto interativo. Com poucos atributos (hx-get, hx-post, hx-trigger, hx-target e hx-swap), você resolve a maioria dos casos de uso que antes exigiam um front-end inteiro separado.

Se você está cansado da complexidade do ecossistema JavaScript, ou só quer entregar funcionalidades mais rápido, vale reservar uma tarde para experimentar. Comece com um único botão, um único hx-get, e veja até onde isso te leva. Para se aprofundar, a documentação oficial em htmx.org é curta, clara e cheia de exemplos.

Menos código, mais produtividade. Esse é o convite do htmx.