W3docs

Atributo contenteditable de HTML

El atributo contenteditable indica si el contenido de un elemento es editable. Aprende sus valores, uso con JavaScript y consejos de accesibilidad.

El atributo HTML contenteditable especifica si el contenido de un elemento es editable directamente en el navegador. Al activarlo, el usuario puede hacer clic dentro del elemento y escribir, borrar y dar formato al texto como en un procesador de textos — sin necesidad de <input> ni <textarea>.

Como funciona con casi cualquier elemento, contenteditable puede convertir un <div>, un <p> o toda una sección en una superficie de edición. Forma parte de los Atributos Globales, por lo que está disponible en todos los elementos HTML.

Cuándo usar contenteditable

contenteditable es la base de la edición dentro de la página. Lo encontrarás detrás de:

  • Editores de texto enriquecido (los cuadros "WYSIWYG" en CMS, clientes de correo y formularios de comentarios). A diferencia de un <textarea>, un elemento editable puede contener HTML real — texto en negrita, enlaces, listas e imágenes — por lo que el usuario ve el resultado formateado a medida que escribe.
  • Edición en línea — permite que el usuario haga clic en un encabezado o celda de tabla para cambiarle el nombre en el lugar, sin abrir un formulario separado.
  • Interfaces de vista previa en vivo y toma de notas, donde el área de edición es el resultado renderizado.

Elige <textarea> o <input> cuando solo necesites texto sin formato que se envíe con un formulario: son campos de formulario reales, se validan y publican su valor automáticamente. Recurre a contenteditable cuando necesites contenido formateado (HTML) o quieras que la edición ocurra dentro del diseño existente de la página.

Sintaxis

<tag contenteditable="true">...</tag>

El atributo acepta los siguientes valores:

ValorSignificado
true (o "")El elemento es editable. Una cadena vacía se comporta igual que true.
falseEl elemento no es editable.
inheritEl elemento toma su estado editable del padre más cercano. Este también es el valor predeterminado cuando se omite el atributo.
plaintext-onlyEl elemento es editable pero el formato de texto enriquecido está desactivado — solo se acepta texto sin formato. Compatible con los navegadores modernos, pero verifica el soporte antes de depender de él.

Ejemplo

<!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>

Herencia con el valor inherit

Cuando no estableces contenteditable en un elemento hijo, este hereda el estado editable de su padre. Puedes hacer editable toda una región en el padre y luego excluir un hijo específico con 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>

Leer y guardar contenido editado con JavaScript

Un elemento contenteditable no es un campo de formulario, por lo que su valor no se envía con un formulario y no existe la propiedad value. En cambio, lees el contenido directamente del elemento:

  • element.innerHTML — el contenido editado como HTML (conserva negritas, enlaces y listas).
  • element.textContent — el contenido editado como texto sin formato (sin formato).

Para reaccionar a las ediciones a medida que ocurren, escucha el evento input, que se dispara en cada cambio:

<!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>
Advertencia

Guardar innerHTML directamente en un servidor almacena HTML sin procesar. Siempre sanea el HTML que no sea de confianza en el servidor (o con una biblioteca de cliente validada) antes de guardarlo o mostrarlo de nuevo, para evitar ataques de cross-site scripting (XSS).

Accesibilidad

Un elemento contenteditable sencillo parece editable pero, a diferencia de un campo de formulario real, no expone semántica de campo a la tecnología de asistencia — los lectores de pantalla pueden no anunciarlo como algo en lo que el usuario puede escribir. Cuando construyas un editor personalizado, ayúdales:

  • Agrega role="textbox" para que sea anunciado como un campo de texto editable. Agrega aria-multiline="true" si acepta múltiples líneas.
  • Agrega un aria-label (o asocia un <label> visible mediante aria-labelledby) para que el campo tenga un nombre accesible.
  • Agrega tabindex="0" si el elemento no puede recibir foco de forma natural, para que los usuarios de teclado puedan alcanzarlo.
<div
  contenteditable="true"
  role="textbox"
  aria-multiline="true"
  aria-label="Comment"
  tabindex="0"
>
  Type your comment…
</div>

Inconsistencias entre navegadores

contenteditable es potente, pero su comportamiento no es uniforme entre navegadores — esta es la principal razón por la que las aplicaciones en producción suelen basarse en una biblioteca (o usar plaintext-only) en lugar de contenteditable puro:

  • El marcado de la tecla Intro difiere. Al presionar Intro, se puede envolver una nueva línea en un <div>, un <p> o insertar un <br>, según el navegador. No asumas la estructura HTML generada.
  • Al pegar a menudo se incorporan estilos y etiquetas de la fuente; puede que necesites interceptar el evento paste y limpiarlos.
  • plaintext-only desactiva el formato enriquecido, pero no es compatible en todos lados — detecta la funcionalidad antes de depender de ella.

Atributos relacionados

  • spellcheck — activa o desactiva la revisión ortográfica del navegador dentro de una región editable.
  • draggable — controla si un elemento puede ser arrastrado.
  • Atributos Globales — el conjunto completo de atributos utilizables en cualquier elemento.

Práctica

Práctica
¿Cuáles de las siguientes afirmaciones son verdaderas sobre el atributo contenteditable de HTML?
¿Cuáles de las siguientes afirmaciones son verdaderas sobre el atributo contenteditable de HTML?
Was this page helpful?