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