by

Contenteditable, CSS, Scoped, and advanced in-browser editing

I’ve said before and I’ll say again that contenteditable is one of the coolest attributes you can apply to an element. This lil’ gem originates from Microsoft, of all places, and has been there since IE5.5.  Well, the other browsers caught on a while back, and others, including myself, have demonstrated some cool techniques with contenteditable that include editing CSS and JavaScript.

This time, I want to combine what we’ve learned about CSS and contenteditable with another HTML5 attribute called scoped, and show you a fun little jQuery plugin that’s sure to make your day more interesting.

Prerequisites

First let’s get the browser issues out of the way. Contenteditable and scoped may not work in all browsers. Definitely check to see if you can use contenteditable or scoped on caniuse.com. Even if the answer is “yes”, you may still need to enable a flag. Go to Chrome://flags in Google Chrome to flip it on (warning, may require a browser restart).

Fundamentals of contenteditable

You have three values for this attribute: true, false, and inherit.

There’s two ways we make an element’s content editable for the end user, the difference is whether you want to use a value. Therefore, setting either contenteditable or contenteditable="true" on an element will get you the same result. A browser, by default, sets the value to true when the contenteditable attribute is present (but I’ll explicitly set the value because valueless attributes creep me out).

Child elements get a value of inherit unless you explicitly state otherwise.

Once an element is contenteditable, the end user can now change any of that content that’s inside; all descendants of this element will inherit this property. Yes, that means those <p>s, <headers>, and even <style> and <script>.

Fundamentals of scoped

Folks have been talking about scoped for a while (in the web world, a while == a year). It’s another HTML5 property that’s in draft mode, and it hasn’t been advanced too much because it is extremely dangerous… to the design.

The scoped attribute is meant for the <style> element. What it does is tell the browser that these styles apply only to the parent container and its children. The styles that are scoped are isolated to only one small piece of the page; they won’t affect the entire design. So, consider the following HTML:

<style>
.tastyTreats h1{color:green}
</style>
<div class="tastyTreats">
<style scoped>
h1{color:red}
</style>
<h1>Bacon for the Win</h1>
</div>
<div class="tastyTreats">
<h1>There's Celery</h1>
</div>
<div class="tastyTreats">
<h1>Maybe Spinach?</h1>
</div>

If you have scoped enabled in your browser, this HTML will make much more sense to you.

Bacon for the Win

There’s Celery

Maybe Spinach?

And if you didn’t get the joke, here’s a picture of what you should see:

The div with a scoped style is red
The div with a scoped style is red

The default color was supposed to be green for those h1 elements, but in the first one we set a new style, scoped it, and didn’t affect the others. As a result of the scoped style, Bacon is its proper and respectable color.

The dangers of scoped

Ignoring the ever-present issue of browser support, there are other serious dangers with this attribute. The big one is that this is the override that overrides the override. Best practices dictate that we use an external stylesheet. Decent practices dictate that we use an internal stylesheet in the <head>. Bad practices involve style blocks in the body, and worst practices are inline-styles.

There’s two reasons that we don’t like styles on the page itself: manageability and specificity.

External stylesheets make it easy to manage all the styles on a site; internal ones and inline blocks can create the kind of nightmare that front-end guys like me would get from eating a block of Blue Stilton Cheese. At least if a style block is in the head, we can hope that it’s called from some JavaScript API and they’re trying to be really polite about the situation (WordPress is a good example). If it’s an inline style block, I can only imagine that it’s some giant portal application like SharePointe or Portal 7.0 where some poor web developer is given the task of putting lipstick on a pig. Let’s face it, a style block in the body is never one of our first two options.

The specificity is what really gets hairy in the case of scoped styles. Recall that the order of specificity power is this:

inline style / style block > ID > class > element

Your inline style block is already the Obi Wan Kenobe of the specificity wars (I guess that an inline style must be a Yoda / Superman / Chuck Norris combo).

Once you start scoping the styles, it’s almost like there becomes 5 levels of specificity:

inline style / scoped style block > style block > ID > class > element.

You see, an inline style will still trump a scoped style block. But, a scoped style block can beat a non-scoped style block. I wouldn’t venture to say that there is a true fifth level of specificity, though — I imagine the battle for specificity supremacy is why so few browsers have implemented scoped.

So why used scoped at all?

Imagine you’re building a prototype, demo, or wireframe of some sort. You’re showing them a list of articles, and they want to see what it would look like if you changed just the first article. Provided there’s JavaScript that’s setting that article to contenteditable=true, there’s no reason not to sandbox the styles, too. This means you can safely edit styles without disrupting the design of the entire page. Not only that, a scoped style may be very useful if you build inline WYSIWYGs for a page.

Scoped is good for building prototyping tools or developing content design APIS. It’s an absolutely HORRIBLE idea anywhere else.

A Good Protyping Plugin

So, I wrote a jQuery plugin called editable which you can fork on GitHub.

To make an element editable, it’s easy:

$('.someDiv').editable();

And if you want to be able to edit those styles, here’s how.:

$('.someDiv').editable('styles');

Provided your browser supports the scoped attribute, you can edit and style by simply double clicking the element (I’m not doing feature checking yet). Use the up arrow to get to that style block up at the top of the element (I haven’t worked out the events so that it stays there when you move the mouse).

I haven’t buffed out some of the finer points of the user interface, but follow the repo on GitHub and you’ll see it improve.

If you want a live demo, it’s over on JSfiddle.

Comments are closed.