The contenteditable "plaintext-only" attribute value combination is now Baseline Newly available

Published: Mar 20, 2025

When you want to allow the user to enter plaintext information, your first instinct might be to reach for a <textarea>. This works for many cases and requires no special effort to make it work with forms, but also has limitations.

One example is growing the <textarea> dynamically with the content without resolving to hacks. There's field-sizing: content, but it has limited browser support. This is where the contenteditable="plaintext-only" attribute value combination comes in. You can add it to generic elements like <div>, and have the element automatically take care of resizing.

Another limitation is styling. The CSS Custom Highlight API provides a mechanism for styling arbitrary text ranges on a document by using JavaScript to create the ranges, and CSS to style them. A <textarea> internally uses a <div> in the user agent shadow root, which is why styling the text with the CSS Custom Highlight API doesn't work. If used on an element like a <div> directly that you have made contenteditable, the CSS Custom Highlight API works just fine.

<style>
  ::highlight(highlight) {
    background-color: yellow;
    color: black;
  }
</style>

<div contenteditable="plaintext-only">Edit me</div>

<script>
  const parentNode = document.querySelector('div').firstChild;
  const range = new Range();
  range.setStart(parentNode, 0);
  range.setEnd(parentNode, 3);
  const highlight = new Highlight(range);
  CSS.highlights.set('highlight', highlight);
</script>

Chrome DevTools Elements panel inspecting a textarea showing that it's using a div in a user-agent shadow root.

Here's a screenshot of the demo that shows this limitation. Note how the text in the <textarea> isn't styled, but the text in the two contenteditable generic <div> elements is.

Demo showing how the CSS Custom Highlight API only works with the contenteditable div elements, but not the textarea.