Atributo contenteditable do HTML
O atributo contenteditable define se o conteúdo de um elemento é editável. Veja valores, uso com JavaScript e dicas de acessibilidade.
O atributo HTML contenteditable especifica se o conteúdo de um elemento pode ser editado diretamente no navegador. Quando ativado, o usuário pode clicar dentro do elemento e digitar, apagar e formatar texto como em um processador de texto — sem precisar de <input> ou <textarea>.
Por funcionar em quase qualquer elemento, contenteditable pode transformar uma <div>, um <p> ou uma seção inteira em uma superfície de edição. Ele faz parte dos Atributos Globais, portanto está disponível em todos os elementos HTML.
Quando usar contenteditable
contenteditable é a base da edição em página. Você o encontrará por trás de:
- Editores de rich-text (as caixas "WYSIWYG" em CMSes, clientes de e-mail e formulários de comentários). Ao contrário de um
<textarea>, um elemento editável pode conter HTML real — texto em negrito, links, listas e imagens — então o usuário vê a saída formatada enquanto digita. - Edição inline — permitir que um usuário clique em um título ou célula de tabela para renomeá-lo no lugar, sem abrir um formulário separado.
- UIs de prévia ao vivo e anotações, onde a área de edição é o resultado renderizado.
Escolha um <textarea> ou <input> quando precisar apenas de texto simples que é enviado com um formulário: eles são campos de formulário reais, validam e postam seu valor automaticamente. Use contenteditable quando precisar de conteúdo formatado (HTML) ou quiser que a edição ocorra dentro do layout existente da página.
Sintaxe
<tag contenteditable="true">...</tag>O atributo aceita os seguintes valores:
| Valor | Significado |
|---|---|
true (ou "") | O elemento é editável. Uma string vazia se comporta da mesma forma que true. |
false | O elemento não é editável. |
inherit | O elemento herda seu estado editável do pai mais próximo. Este também é o padrão quando o atributo é omitido. |
plaintext-only | O elemento é editável, mas a formatação rich-text é desativada — apenas texto simples é aceito. Com suporte em navegadores modernos, mas verifique a compatibilidade antes de depender disso. |
Exemplo
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<p contenteditable="false">
This is a paragraph. It is not editable.
</p>
<p contenteditable="true">
This is a paragraph. It is editable. Try to change this text.
</p>
</body>
</html>Herança com o valor inherit
Quando você não define contenteditable em um elemento filho, ele herda o estado editável do pai. Você pode tornar toda uma região editável no pai e depois excluir um filho específico com contenteditable="false":
<!DOCTYPE html>
<html>
<head>
<title>contenteditable inherit example</title>
</head>
<body>
<div contenteditable="true">
<p>This paragraph inherits editing from the div, so you can change it.</p>
<p contenteditable="false">
This paragraph opts out — it is locked and cannot be edited.
</p>
<p contenteditable="inherit">
This one explicitly inherits, so it is editable again.
</p>
</div>
</body>
</html>Leitura e salvamento do conteúdo editado com JavaScript
Um elemento contenteditable não é um campo de formulário, portanto seu valor não é enviado com um formulário e não existe a propriedade value. Em vez disso, você lê o conteúdo diretamente do elemento:
element.innerHTML— o conteúdo editado como HTML (mantém negrito, links, listas).element.textContent— o conteúdo editado como texto simples (formatação removida).
Para reagir às edições à medida que acontecem, ouça o evento input, que é disparado a cada alteração:
<!DOCTYPE html>
<html>
<head>
<title>Save editable content</title>
</head>
<body>
<div id="editor" contenteditable="true">
Edit me, then reload the page.
</div>
<script>
const editor = document.getElementById("editor");
// Restore any previously saved content.
const saved = localStorage.getItem("note");
if (saved !== null) {
editor.innerHTML = saved;
}
// Save on every edit.
editor.addEventListener("input", () => {
localStorage.setItem("note", editor.innerHTML);
// In a real app you would debounce this and POST it to a server, e.g.
// fetch("/api/save", { method: "POST", body: editor.innerHTML });
});
</script>
</body>
</html>Salvar innerHTML diretamente em um servidor armazena HTML bruto. Sempre sanitize HTML não confiável no servidor (ou com uma biblioteca cliente homologada) antes de salvá-lo ou exibi-lo novamente, para evitar cross-site scripting (XSS).
Acessibilidade
Um elemento contenteditable simples parece editável mas, ao contrário de um campo de formulário real, ele não expõe nenhuma semântica de campo para tecnologias assistivas — leitores de tela podem não anunciá-lo como algo em que o usuário pode digitar. Ao criar um editor personalizado, ajude-os:
- Adicione
role="textbox"para que seja anunciado como um campo de texto editável. Adicionearia-multiline="true"se aceitar múltiplas linhas. - Adicione um
aria-label(ou associe um<label>visível viaaria-labelledby) para que o campo tenha um nome acessível. - Adicione
tabindex="0"se o elemento não for naturalmente focalizável, para que usuários de teclado possam acessá-lo.
<div
contenteditable="true"
role="textbox"
aria-multiline="true"
aria-label="Comment"
tabindex="0"
>
Type your comment…
</div>Inconsistências entre navegadores
contenteditable é poderoso, mas seu comportamento não é uniforme entre os navegadores — este é o principal motivo pelo qual aplicações em produção geralmente se baseiam em uma biblioteca (ou usam plaintext-only) em vez do contenteditable bruto:
- A marcação da tecla Enter difere. Pressionar Enter pode envolver uma nova linha em uma
<div>, um<p>ou inserir um<br>, dependendo do navegador. Não presuma a estrutura HTML gerada. - Colar frequentemente traz estilos e tags da fonte; pode ser necessário interceptar o evento
pastee limpá-los. plaintext-onlydesativa a formatação rich-text, mas não tem suporte em todos os lugares — faça a detecção de recurso antes de depender disso.
Atributos relacionados
spellcheck— ativa ou desativa a verificação ortográfica do navegador dentro de uma região editável.draggable— controla se um elemento pode ser arrastado.- Atributos Globais — o conjunto completo de atributos utilizáveis em qualquer elemento.