W3docs

HTML contenteditable Attribute

The contenteditable attribute specifies whether an element's content is editable. Learn its values, JavaScript handling, and accessibility tips.

The HTML contenteditable attribute specifies whether or not the content of an element is editable directly in the browser. When you turn it on, the user can click inside the element and type, delete, and format text just like in a word processor — no <input> or <textarea> required.

Because it works on almost any element, contenteditable can turn a <div>, a <p>, or a whole section into an editing surface. It is part of the Global Attributes, so it is available on every HTML element.

When to use contenteditable

contenteditable is the foundation of in-page editing. You will see it behind:

  • Rich-text editors (the "WYSIWYG" boxes in CMSes, email clients, and comment forms). Unlike a <textarea>, an editable element can hold real HTML — bold text, links, lists, and images — so the user sees formatted output as they type.
  • Inline editing — letting a user click a heading or table cell to rename it in place, instead of opening a separate form.
  • Live-preview and note-taking UIs, where the editing area is the rendered result.

Choose a <textarea> or <input> when you only need plain text that submits with a form: they are real form fields, validate, and post their value automatically. Reach for contenteditable when you need formatted (HTML) content or want the edit to happen inside existing page layout.

Syntax

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

The attribute accepts the following values:

ValueMeaning
true (or "")The element is editable. An empty string behaves the same as true.
falseThe element is not editable.
inheritThe element takes its editable state from its nearest parent. This is also the default when the attribute is omitted.
plaintext-onlyThe element is editable but rich-text formatting is disabled — only plain text is accepted. Supported in modern browsers, but check support before relying on it.

Example

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

Inheritance with the inherit value

When you do not set contenteditable on a child, it inherits the editable state of its parent. You can make a whole region editable on the parent and then opt a specific child back out with 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>

Reading and saving edited content with JavaScript

A contenteditable element is not a form field, so its value is not submitted with a form and there is no value property. Instead you read the content directly from the element:

  • element.innerHTML — the edited content as HTML (keeps bold, links, lists).
  • element.textContent — the edited content as plain text (formatting stripped).

To react to edits as they happen, listen for the input event, which fires on every change:

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

Saving innerHTML straight to a server stores raw HTML. Always sanitize untrusted HTML on the server (or with a vetted client library) before saving or re-displaying it, to prevent cross-site scripting (XSS).

Accessibility

A plain contenteditable element looks editable but, unlike a real form field, it exposes no field semantics to assistive technology — screen readers may not announce it as something the user can type into. When you build a custom editor, help them out:

  • Add role="textbox" so it is announced as an editable text field. Add aria-multiline="true" if it accepts multiple lines.
  • Add an aria-label (or associate a visible <label> via aria-labelledby) so the field has an accessible name.
  • Add tabindex="0" if the element is not naturally focusable, so keyboard users can reach it.
<div
  contenteditable="true"
  role="textbox"
  aria-multiline="true"
  aria-label="Comment"
  tabindex="0"
>
  Type your comment…
</div>

Browser inconsistencies

contenteditable is powerful but its behavior is not uniform across browsers — this is the main reason production apps usually build on a library (or use plaintext-only) rather than raw contenteditable:

  • Enter key markup differs. Pressing Enter may wrap a new line in a <div>, a <p>, or insert a <br>, depending on the browser. Don't assume the generated HTML structure.
  • Pasting often brings along styles and tags from the source; you may need to intercept the paste event and clean it up.
  • plaintext-only disables rich formatting but is not supported everywhere — feature-detect before relying on it.
  • spellcheck — toggle the browser's spell-checking inside an editable region.
  • draggable — control whether an element can be dragged.
  • Global Attributes — the full set of attributes usable on any element.

Practice

Practice
Which of the following statements are true regarding the HTML contenteditable attribute?
Which of the following statements are true regarding the HTML contenteditable attribute?
Was this page helpful?