by

HTML5 contenteditable and CSS

Reading Time: 2 minutes

My absolute favorite HTML5 attribute is "contenteditable". It makes the contents of the element editable. It’s an incredibly simple feature that has tons of potential for your website.In fact, I’ve already seen it paired with localStorage or Web SQL APIs to capture data and create browser-side interactivity.

Even better, Chris Coyier actually figured out that you could use “contenteditable” to edit your styles in real-time. How’s that for mind-blowing?

So, on the heels of the absolute awesomeness of your ability to edit content and styles on a page, I’m going to give some basic CSS pointers for handling contenteditable and those elements which are ordinarily hidden(e.g.:head, script, style, and even html)

When you’re editing…

When you’re actually editing, a gray border gets drawn around the element in Chrome. I find this annoying.So
the first thing we do is eliminate any browser defaults.

[contenteditable="true"]:active,
[contenteditable="true"]:focus{
  border:none;
  outline:none;
}

I still think it’s polite to tell a user that they’re editing something, though. If you know me, you know I love feedback.

Why not be more direct with using ::before and content? Let’s make sure that a user knows when they’ve hovered or focused something contenteditable.

[contenteditable="true"]:hover::before,
[contenteditable="true"]:focus::before{
content:"Edit Me!";
}

Of course, be sure to set font-sizing, margins, and floats appropriately. The ::before and ::after pseudo-elements are inline with the element. Unless you shift that content out, the user will think the element has added text.

Edit those style blocks

First, I want to state that inline styles and stylesheets are generally bad. An external stylesheet is usually the proper way to style content. But if you’re looking for a cool factor, let’s add this to the CSS so that a user can edit the inline stylesheet — only when they’re actually editing the element. This is also useful for component-based frameworks like React or Vue where you might have styles scoped to a particular component.

[contenteditable="true"]:focus > style {
display:block;
}

After getting our inline style to display, now it’s just a matter of making it look good. So let’s push it off to the right, make the text preformatted and blue (so it looks code-y).

[contenteditable="true"]:focus > style {
display:block; 
position:relative; 
right: -80%; 
top:-2em; 
color: blue; 
font-family: courier, monospace; 
font-size: .75em; 
line-height: 1.5; 
padding: .5em; 
background: #fff; 
border: 1px solid #999; 

}

What else?

That’s it. If it’s an element, you can make it editable with contenteditable="true". If it’s an element which is set to display:none by default, set it to display:block. Now you have a webpage you can edit to your heart’s content, without hitting refresh.

Of course, here’s your demo. If you don’t like it, change it!

Yep, you can edit these words right now. Just go crazy and type whatever you want. The only thing you can’t do is create new HTML elements; everything you type into contenteditable is a text string.

[UPDATE for 3.3.18:]
There’s a sort of followup post to this, where I’ve added additional explanations and included details on the scoped attribute, You may want to read this, instead: