Web Components

And the future of CSS

Philip Walton / @philwalton

Some quick disclaimers

What makes CSS hard?

The usual answers:

But is that stuff really what makes CSS hard?

Solving those problems just requires a little memorization or Googling.
These aren't actually "hard" problems.

What are some of the real hard problems in CSS?

What do all these have in common?

Hint, it's not these…

~~#sidebar ul li a {~~ color: red; display: block; padding: 1em; ~~}~~

…it's these

#sidebar ul li a { ~~color: red; display: block; padding: 1em;~~ }

Your selectors are the biggest determining factor in how scalable your code is.

Selectors are globals. It’s hard to write predictable code when any rule you write could potentially conflict with another rule you didn’t know existed.

Writing bad selectors today will likely cripple your ability to makes changes to the front-end in the future.

What are bad selectors?

Selectors that cast a wide net increase the chances of unintended matches.

And for whatever reason, people who write CSS like to live dangerously!

#main #content div div div { float: left; width: 50%; }

This is not a joke. This actually happened.

Okay, but my selectors aren't that bad.

Yes, they are.

In my experience, any attempt to style markup through selectors alone is inevitably going to fail.

Selectors that target HTML tags will always be vulnerable to future changes. Instead, your selectors should target classes.

But adding classes to your HTML has its own problems

Without thoughtful conventions, you end up with this:

Are all these classes needed? What do they do? If I remove one of them will everything break? WTF is going on? #FML

So what is the answer?
What does good CSS look like?

Good CSS consists of selectors that match exactly the elements you want without accidentally matching the elements you don't. All while not being overly verbose or repetitive, being resilient to change, and adaptable to any and all future design requirements.

In other words, writing good CSS means you need magical powers and the ability to predict the future.

Is all hope lost?

In all seriousness, the people who are good at CSS recognize its shortcomings and approach new problems with those shortcomings in mind.

Methodologies like BEM, SMACSS, and OOCSS are invaluable tools for writing CSS today.

The real question isn't "how do I write good CSS?" its "how should we change CSS to make it harder to screw up?"

What is CSS missing?

If I could change anything about HTML and CSS to make these problems easier to solve, what would it be?

As it turns out, Web Components give us both of these.

Web Components

Specifically, Shadow DOM

Shadow DOM gives us real style scoping and encapsulation. We can add elements to the page that won't be affected by the existing CSS, and we can write style rules that won't affect the rest of the page.

Shadow DOM also allows us hide presentational elements from end users. Effectively creating a private and public API.

What is Shadow DOM?

Shadow DOM is a subtree of DOM nodes that you can create on any HTML element.

The shadow subtree is ultimately rendered onto the page with the main DOM tree, but unlike the main DOM tree, shadow nodes can only be modified or styled from within.

In short, shadow nodes are private.

A simple example:

The main DOM:

Click Me

Click Me

The element's shadow DOM:

<style> button { background: #0af; border: 0; border-radius: .2em; color: #fff; font: inherit; padding: .5em 1em; } </style>

How can I get me some Shadow DOM?

var element = document.getElementById('some-id'); var shadowRoot = element.createShadowRoot(); shadowRoot.innerHTML = 'Some HTML string...';

Let's see some examples

The Media Object

How it's done today (using BEM syntax):



Notice how div.Media-body serves no semantic purpose. It's a container elements that is purely presentational.

How it could be done.

The main DOM:

Shadow DOM:

<style> :host { display: flex } figure { margin: 0 1em 0 0 } div { flex: 1 } </style>

The composed tree

~~<style>…</style>~~ ~~
~~ ~~
~~ ~~

Media object demo  →

The Author Card

The <author-card> imports the <media-object> and composes it within its own shadow DOM.

**<link href="/path/to/media-object.html" rel="import">** Author card demo  →

Layout primitives

The <flex-grid> element:

Flex grid demo  →

The <flex-line> element:

Flex line demo  →

Building layouts from composable primitives.

<flex-line> and <flex-grid> are very presentational, so you might not want to have them appear in your main document source.

Luckily, you don't have to.

The next example uses <flex-line> in its shadow DOM to build the classic "Holy Grail" layout.

The main document:

<body is="holy-grail">
Holy grid demo  →

Composed tree:

<body> ~~~~ ~~
~~ ~~~~ ~~
~~ ~~
~~ ~~
~~ ~~
~~ ~~
~~ ~~
~~ ~~
~~ ~~
~~ ~~
~~ </body>

Keeping hacks in the shadows

Sometimes CSS doesn't do exactly what you want, so you have to resort to hacks.

With shadow DOM, you can keep these hacks out of sight, where they belong.

Flex grid broken  |  Flex grid fixed


When can I use this stuff? Are any sites currently using it?

Check out polymer-project.org as well as chromestatus.com. Both are built entirely with Web Components using Polymer.

What browsers support these technologies?

With the webcomponents.js polyfills you can get most of these features in all modern browsers (IE 10+).

Though some features (like full style encapsulation) cannot be polyfilled, and so keep that in mind.

Is it possible to style content in the shadow DOM from outside?

Yes, the selectors ::shadow and /deep/ allow you to do this.

But as a general rule, you shouldn't ever do this. Well designed elements should make themselves sufficiently extensible.

To quote the open/closed principle:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

How do I know when to put content in the main DOM vs. the shadow DOM?

The shadow DOM is your private API and the main DOM is your public API. Implementation details belong in the shadow DOM.

Also, dynamic content should go in the main DOM whenever possible. As a rule, Web Components should be static, bundleable, and cacheable.

Is content in the shadow DOM accessible to screen readers and search engines?

Yes. Screen readers see the rendered tree in the same way that you see it (visually) when using your browser.

Since Web Components are just HTML, you can use ARIA roles and attributes just as you can today.

As with any emerging technology, test it on the devices you need to support.

Wrapping Up

Revisiting the hard problems in CSS

Key points:

The End