This specification defines allowed values and expected behaviors for the contenteditable attribute. This specification builds on HTML5.

Problems solved

This section is not normative.

Creating a webbased texteditor requires a considerable amount of JavaScript on top of the browser code, among other things because:

  1. Browsers do not handle all editing operations the same way.
  2. Browsers are often buggy in the way they handle certain editing operations.
  3. Individual sites may have custom preferences for how they want to handle certain editing operations.
  4. The development of hihg-level text editing features in browsers has not followed the principles laid out in the Extensible Web Manifesto in that development of these features has not always been in coordination with the needs of the web developer community.

This spec seeks to alleviate the problem by providing a simple way for web developers prevent all browser default handling of editing operations at different levels without having to preventDefault each of them.

Use cases

This section is not normative.

  1. Creating a JavaScript text editor in which the <strong>-tag is used instead of the <b>-tag to mark text that the user marks as bold, using any browser-builtin way to mark a text as bold, without having access to all existing browsers.
  2. Creating a JavaScript text editor which works with a data model in the background where JavaScript takes care of rendering changes to the edited text to the DOM.
  3. Creating a JavaScript editor which only allows a subset of richtext editing (for example: bold is allowed, but italic not).
  4. Creating a collaborative editor in which JavaScript is used to render changes to the DOM, based on user intentions with users using different browsers with different ways of expressing specific intentions.
  5. Creating a JavaScript editor with different user access options, where some users only can add or delete text and other users only can add or remove certain types of formatting.
  6. Creating a JavaScript editor in which carte movement is handled differently from the default.
  7. Creating a JavaScript editor with advanced elements, such as non-editable regions, inline SVGs, canvas-elements and other elements for which contenteditable=true currently creates caret placement issues in several browsers.

Terminology

editing host
An editing host is a node that is an HTML element with a contenteditable attribute set to something else than the `false` state.
contentEditable=false element
Any element that has the contentEditable attribute set to `false`.
Inline elements
All element nodes for whom the used value of the `display` property resolves to the value `inline`.
Block elements
All element nodes for whom the used value of the `display` property resolves to the value `block`.
Stub elements
All element nodes that are void elements OR root elements using a different namespace than their parent elements (such as SVGs).
Invisible elements
All element nodes for whom the used value of the `display` property resolves to the value `none`.
Legal Caret Positions

All positions in which the caret can be placed programmatically. The placement is restricted to the following positions. Implementations MUST be able to place the caret in all of the following positions:

  1. Before or after any character in any text node.
  2. After inline elements that do not have a `nextSibling` which is a text node.
  3. Before inline elements that that do not have a `previousSibling`.
  4. Inside empty inline elements and block elements that are not stub elements.
  5. Inside empty text nodes.
  6. Before or after block elements that are also stub elements.
  7. Before or after comment nodes.
  8. In the editing hostitself, if it is empty.

There are some exceptions to these rules:

  1. Within a table, the caret can only be placed inside `TH`, `TD` and `CAPTION` elements.
  2. The caret cannot be placed inside invisible elements.
  3. The caret cannot be placed inside elements who's contentEditable attribute returns `false`.

The following items are defined in the CSS Cascading and Inheritance Level 3 specification [[!css-cascade-3]]

contenteditable

The contenteditable attribute is an enumerated attribute whose keywords are the empty string (""), "events", "caret", "typing", "plaintext-only", "true", and "false". There is one additional state, the inherit state, which is the missing value default (and the invalid value default).

The empty string and the "true" keyword map to the true state. The other keywords map to their respective states.

The false state indicates that the element is not editable. The inherit state indicates that the element has the state of its parent.

The contentEditable IDL attribute, on getting, must return the string "true" if the content attribute is set to the true state, "typing" if the content attribute is set to the typing state, "caret" if the content attribute is set to the caret state, "events" if the content attribute is set to the events state, "false" if the content attribute is set to the false state, "plaintext-only" if the content attribute is set to the plaintext-only state, and inherit otherwise.

On setting, if the new value is an ASCII case-insensitive match for the string "inherit" then the content attribute must be removed, if the new value is an ASCII case-insensitive match for a string matching the name of a state, then the content attribute must be set to the name of that state, and otherwise the attribute setter must throw a SyntaxError exception.

The isContentEditable IDL attribute, on getting, must return true if the element is either an editing host or editable, and false otherwise.

Meaning of states

The states "events", "caret", "typing" and "true" are hierarchically ordered, so that the state "caret" also includes the features of the "events" state, the "typing" state includes the features of the "caret" state, and the "true" state includes all the features of the "typing" state.

The "events" state means that beforeinput events are triggered when the user asks for an editing operation. The "caret" state adds default browser controlled movement of the caret. The "typing" state adds handling of text input through IME and keyboard, and deletion within an IME composition. The "true" state adds handling of deletion of content for keyboard input as well as deletion of non-textual content and editing commands through the execCommand command.

The states "events", "caret" and "typing" are defined in this document.

The state "true" is currently not well-defined and its usage is discouraged. An initial attempt has been made to specify the behavior of the "true" state in the contentEditable=True spec.

The state "plaintext-only" is deprecated and its usage is discouraged.

contentEditable states

contentEditable=events state

In a focused editing host that is in the events state, a caret MUST be drawn if the selection is collapsed, and it MUST be possible to place the caret in all of the Legal Caret Positions programmatically.

All user editing intentions initiated while an editing host that is in the events state is focused, MUST trigger a `beforeinput` event.

contentEditable=caret state

A focused editing host that is in the caret state MUST behave like an editing host in the events state. Additionally, the default action of the `beforeSelectionChange` event in such an editing host must be to move the caret in the indicated direction, if movement in that direction seems possible.

Notice the planned beforeSelectionChange event.

contentEditable=typing state

A focused editing host that is in the typing state MUST behave like an editing host in the caret state, and additionally, it MUST handle text insertion by keyboard at the position of the caret if the caret is placed within a text node or it is possible to place a text node at the place of the caret. It must by default also handle composition by IME, both insertion as well as deletion of text input.

Cutting and pasting

Within an editing host that is in the "events", "caret" or "typing" state, cutting and pasting is disabled. However, `cut` and `paste` events are still triggered.

Caret drawing and movement

Caret drawing

A caret is drawn in any editing host that is focused, that does not hold any other selections. Under such conditions, the caret represents a collapsed selection.

Caret positions

It MUST be possible to put the caret in any of the Legal Caret Positions programatically and for the caret to be visible in these in any editing host that is in the "events", "caret" or "typing" state.

Initial caret placement

Carets are initially placed at the first possible position within the editing host.

Caret movement

The specific location that the caret is moved to by default in an editing host in the "caret" and "typing" state, is out of scope for this specification, but later versions of this specification or specifications covering other contentEditable specifications may further specify the movement patterns of the caret.

Replacing text/content

When the user indicates the wish to replace part of the contents of a editing host, by means of a browser-builtin spell checker or alike, a `beforeinput` input with `inputType` set to `replaceText` or `replaceContent` is triggered. No part of the DOM is being changed by default in an editing host that is in the "events", "caret" or "typing" state.

Removal of content

Content is not removed automatically through user input in an editing host that is in the "events" or "caret" state. Instead, Del/Backspace key presses, etc. trigger user `beforeinput` events with `inputType` set to `deleteContentForward` or `deleteContentBackward`. The same is true for any editing host that is in the "typing" state, unless it is currently in the composition mode, in which case it will remove characters from the DOM if they are part of the composition.

Advanced grammar checking

An implementation CAN provide spell check, grammar check and other advanced functionality that are not defined through a specification for any editing host. These features MUST be disabled by default.

Context menu

If the implementation provides a `context menu`, this `context menu` SHOULD contain items for editing operations such as `paste`, `cut`, `copy`, `delete` and CAN contain items for spellchecking for any editing host. Triggering any of `context menu` items MUST NOT by default cause any change to the DOM, `paste`, `cut` and `beforeinput` events SHOULD be triggered. Menu items in a `context menu` that do not cause DOM changes by default SHOULD function as in any other editing context.

Acknowledgements

Thanks to: Michael Aufreiter, Adrian Bateman, Robin Berjon, Oliver Buchtala, Enrica Casucci, Olivier Forget, Aryeh Gregor, Marijn Haverbeke, Yoshifumi Inoue, Koji Ishii, Gary Kacmarcik, Frederico Caldeira Knabben, Takayoshi Kochi, Piotrek Koszuliński, Travis Leithead, Grisha Lyukshin, Chaals McCathie Nevile, Masayuki Nakano, Ryosuke Niwa, Julie Parent, Ben Peters, Florian Rivoal, Hallvord R. M. Steen, Johan Sörlin, Cristian Talau, Ojan Vafai, Xiaoqian Wu, Chong Zhang, Joanmarie, and everyone in the Editing Taskforce for their input and feedback.