![Thomas Steiner](https://web.dev/images/authors/thomassteiner.jpg) Thomas Steiner [GitHub](https://github.com/tomayac) [LinkedIn](https://www.linkedin.com/in/thomassteinerlinkedin) [Mastodon](https://toot.cafe/@tomayac) [Bluesky](https://bsky.app/profile/tomayac.com) [Homepage](https://blog.tomayac.com/)

<br />


Published: Mar 20, 2025

<br />

> [!TIP]
> **Celebration:** This web feature is now available in all three major browser engines, and becomes **Baseline Newly available** as of March 4, 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](https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/). There's [`field-sizing: content`](https://developer.mozilla.org/docs/Web/CSS/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](https://developer.mozilla.org/docs/Web/API/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.

```html
<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.](https://web.dev/static/blog/contenteditable-plaintext-only-baseline/devtools.png)

Here's a screenshot of the [demo](https://contenteditable-textarea.glitch.me/) 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.](https://web.dev/static/blog/contenteditable-plaintext-only-baseline/demo.png)