The topic of scoped CSS styles in HTML5 came up twice in the comments of a recent post by Chris Coyier.
The post itself was discussing the contenteditable attribute, but a few users brought up HTML5’s new scoped attribute, used on the <style>
element.
Let’s take a brief look at this future HTML5 feature and see how it might be useful in the ever-changing web development landscape.
Definition and Syntax
This is not a complicated new feature in HTML5. Here’s the definition from WHATWG:
The scoped attribute is a boolean attribute. If set, it indicates that the styles are intended just for the subtree rooted at the style element’s parent element, as opposed to the whole Document.
So if you put a <style>
element anywhere in the document and add the scoped
attribute, the styles contained inside that <style>
element will only apply to that part of the document. Here’s an example, with some surrounding content so you can theoretically (more on that in a minute) see the effects:
<!-- normal css styles declared in the <head> as usual --> <article> <h1>Blah Title Blah</h1> <p>Blah blah article blah blah.</p> </article> <article> <!-- This style block applies to parent article only --> <style scoped> h1 { color: hotpink; } article { border: solid 1px hotpink; } </style> <h1>Blah Title Blah</h1> <p>Blah blah article blah blah.</p> </article> <article> <h1>Blah Title Blah</h1> <p>Blah blah article blah blah.</p> </article>
The example HTML above would naturally exist inside of a regular HTML5 page with a <head>
, <body>
, etc. The styles declared in the customary way (in the document’s <head>
) would apply to the entire document (as usual). But the styles in the <style>
element inside the second <article>
element would apply to that article only.
So the second article would get a hot pink heading with a hot pink border, but the others would get whatever styles had been applied in the document stylesheet. Of course, as would be the case with any sets of styles, customary cascade and specificity rules I assume would apply.
Of course, if the scoped
attribute is removed, then the styles will apply to the entire document. So you can’t just stick a <style>
element inside something, you need the scoped
attribute to enable this feature.
How Would This Be Useful?
Scoped styles have one pretty obvious use: They allow you to syndicate content that carries style information with it. This would work for anything from a syndicated article to an entire Ajax-based widget. When the receiving page, site, or web app receives the chunk of content that contains the scoped styles, the styles will go with it and will give the ported content the same look and branding that it has everywhere else. This makes it easy for third-party services to pull sections of content into a new location without having to worry about styling it.
Of course, the branding and colors may not match that of the receiving site, so that would be a potential drawback. I suppose if the content was styled with neutral grays, then it would be much easier to port.
No Browser Support
Yeah, this is one of those things that makes us sigh in this industry. The scoped
attribute doesn’t work in any browser (it won’t even validate in HTML5), but it seems to be on the horizon for Gecko and WebKit browsers.
So you can’t use it yet. In fact, it’s not really possible to use it until there’s very strong support cross-browser, because it’s not backwards compatible. That is, a non-supporting browser will apply the styles to all elements on the page, regardless of the existence of the scoped
attribute. This would obviously be counterproductive.
This kind of makes me wonder why they didn’t just add a new kind of style element to the HTML5 spec that is only recognized by supporting browsers and ignored by others. Maybe an element called <scopedstyle>
or something, instead of the scoped
attribute. That would seem to be more in line with HTML’s design principles.
A jQuery Plugin as a Polyfill
Scottish web developer Simon Madine has coded a jQuery plugin that enables scoped styles in all browsers except IE6. Thanks to the great collection of HTML5 Polyfills on GitHub that alerted me to this option.
I haven’t examined Simon’s code, but from his explanation on the original blog post it sounds like there’s quite a bit going on behind the scenes, so it might be a slight performance hit to include this. But I guess it’s better than nothing.
What Do You Think?
Are scoped styles part of HTML5’s future? Or is it likely this feature will go unnoticed for a long time due to lack of support and lack of graceful degradation?
Could be useful, but there are many other things on my web designer wish-list before this one :-)
I could see dropping the scoped attribute all together and just allowing the style element to always apply to it’s parent block element as it never lives outside the head element already. I mean is it true now that the style element really only ventures outside the head when carrying with it the scoped attribute? Why not just let it go as is?
I agree, this would be a good solution, but it still doesn’t resolve the problem of how older browsers handle it. Older browsers will still apply the styles to the entire document, so you might as well use the new attribute anyhow to differentiate in some way.
I think my solution to have a completely new element makes more sense than anything, but I’m not a standards body member, nor am I a browser maker, so there might be something I’m overlooking.
I wouldn’t mind seeing the link element allowed outside of the head. If you had
stuff and things
for instance that might be interesting if it could override “inherited” styles you’d get from head declared styles and only modify or apply to the parent elements contents.Another element might also be nice. I’d just hate to have a lot of “inline style” as a result so the potential to use the link element makes sense.
Sorry. Need a preview button as mentioned below. The code idea was to allow for the link element to be within an article tag for example and have it override other “global” styles and only change the parent’s contents.
This seems as dirty as using inline styles if you ask me.
This is the first thing I thought when I read this article.
The first thing I thought was why am I reading this, the next thing I thought was Anthony must like Pop Tarts, the last thing I thought was this code seems to suck like html from the 90’s.
Neat idea, but goes against the “Separate Style From Content” guideline we’ve been following for years now.
For syndicated content, I’d rather see something like:
ugh, entities fail. where’s the Preview button?
I fixed it for you.
I’ve tried looking for a good preview button. I’ve tried the one James Padolsey uses, but it had problems. I can’t remember exactly what issues I had with it, but I believe it had something to do with the code display or the way it does paragraph breaks. Something was wonky about it, so I abandoned it. I think maybe an ‘edit comment’ button might be good, so I’ll look into that.
Sounds like a nice feature to have available (if/when that happens) but I’d never use it.
Content should be separate to style, it’s ingrained into my being :\
My brain can’t compute sticking styles inline on a page, even if it’s under the nice reasoning of HTML5.
I’d prefer something along the lines of what Drudge was suggesting, maybe with a touch of HTML5 elegance?
Without much thought about the whole subject, I think it would be more beneficial to add something to the CSS referencing the scoped usage than inside the HTML.
That defeats the purpose of it. The purpose of scoped styles is to allow the styles to travel wherever the content goes, without having to link to a global stylesheet. Where the markup goes, the styles follow (physically, not just as a link).
The first thought I had regarding actual real-world implementation of scoped styles was in performance critical, lightweight apps where you serve the minimum required CSS, and then any additional document fragments that are served via AJAX would use scoped styles in the form of a link tag.
However, as far as caching and true modularity goes, I think this still falls short.
This is a bad idea, for two reasons –
1. Separation of style from content. We’ve been working on it for HOW long now?
2. As per the cascade, there’d be no way for the destination site to override the source’s styles (well, aside from javascript). Could lead to an ugly mess if the source’s styles don’t gel.
1. For what “purpose” have we been “working on it”, as you say? It’s for the purpose of maintainability. If this helps maintainability, then it’s fine. Don’t get me wrong though: I’m not encouraging people to use this (when it’s supported); I’m saying it can be useful in a very specific situation.
2. All the destination site would have to do is remove the style block, or else filter it out somehow when the chunk of content is being requested. It’s still early and there’s no implementations yet to fully test it, but theoretically it doesn’t seem that difficult to me to somehow negate the styles. Remember, whatever content you receive through an API, you’ll have the ability to filter stuff. I can’t see why the style block would be inaccessible in that regard.
Maintainability, modularity, speed of download (if this is appearing on a site-wide sdebar, for example, cached styles from a global stylesheet would reduce page weight and improve content/code ratio).
Regarding 2, what I mean is, this’ll only really be of use to those who aren’t already savvy enough to pull in someone else’s content from their RSS feed and style that container – if they want to – by copying the source’s styles. I could do that quite easily, so could you. The average WordPress.com user dragging a widget to their sidebar? Not so much.
This just encourages for more inline style code which isn’t a good idea.
Can’t really see any real need for something like this.
This is a really dumb idea. The problem isn’t HTML and its properties; the problem is CSS. We could simply give a strong ID to the containing tag and reference in the CSS, but I think the problem is how verbose that can be. Instead, I should be able to do this
If you’ve used LESS, this should look familiar.
I think that the concept of scoped styles is good one, but I agree that the styles should be separate from the html.
I think a lot of people are misunderstanding the benefits of scoped styles, and also misunderstanding the definition of ‘inline styles’ or ‘mixing content with presentation’.
Putting CSS in a
<style>
block is not the same as ‘inline styles’. Inline styles are created when you actually put the CSS inside of an HTML tag using the “style” attribute.Scoped styles are a standard created for a specific purpose: To easily port or syndicate content with the existing branding in place. So in that case, there’s nothing wrong with having a
<style>
block inside the HTML.I get putting my styles in a
block not being the same thing as using inline styling. What I don’t get is how putting my styles in a
block is not mixing content with presentation. It seems to me like making the dirty stuff look prettier and more readable.
I’m also afraid this might end up being misunderstood by some of us and used for the wrong reasons. I can see people going for “why bother rethinking my stylesheet, when I can fix this thing with a scoped style?”.
Wouldn’t this be the same as prefixing all of your selectors with:
Yes, but then you can’t port the HTML to another document, which is the main benefit of scoped styles.
Defo agree that the concept of scoped styles is new and fresh, but I agree that the styles should be separate from the html. That what I have been used to using and seems the right way to do it. Loving the blog!!
“scoped style” is an ugly patch to css, we need “inherit:no;”, WHATWG and W3C are still on the wrong way.
If you have a crappy site, and you have to include a bunch of crappy content on a page with crappy overlapping style classes and ids, this would be a killer feature.
Yes, it is not as things should be done, but HTML5 is the very much about how things are usually done: crappily, informally – unfortunately.
For reference scoped style sheets were removed in Chrome 35 (but still work in Firefox and will for awhile, since they’re used internally a lot).