How Web Components will change CSS best practices



How Web Components will change CSS best practices

4 42


html5devconf


On Github philipwalton / html5devconf

How Web Components will change CSS best practices

Philip Walton / @philwalton

Disclaimer

I don't really know.  Nobody knows. 

Web Components haven't been around long enough to really get a feel for what works and what doesn't.

All we can do is learn from history and do our best to avoid repeating the mistakes of the past.

What has history taught us?

As it turns out, CSS is harder than it looks.

Why is CSS so hard?

It's not because:

  • vertical-align never works like you expect.
  • you have to use border-color to make a triangle.
  • the position keywords absolute, static and fixed all sound like they should do the exact same thing.

CSS isn't hard because of the tricks and the hacks, or because it doesn't support X or Y.

There are two hard problems in CSS:

  • Getting your rules to match the elements you want without them accidentally matching the elements you don't.
  • Accomplishing the first part without writing too much code.

Hard problem #1

Getting your rules to match the elements you want without them accidentally matching the elements you don't.

Why is this hard?

All CSS rules are global

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

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

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

Hard problem #2

Accomplishing the first part without writing too much code.

Why is this hard?

Implementation details cannot be easily abstracted away

          
  • ~~…~~

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

Current best practices and methodologies:

BEM, SMACSS, OOCSS

All of these attempt to solve CSS's two hard problems:

  • They minimize unpredictability by reducing unwanted selector matches (i.e. false positives).
  • They maximize code reuse by identifying and codifying recurring visual patterns.

My CSS history, in brief

How I wrote CSS in 2007:

            #sidebar ul li ul li a { }
          
            

How I write CSS today:

            .Sidebar-link { }
          
            

How will I write CSS in the future?

          /* CSS not found… */
        
          
          

Web Componentsto the Rescue

Web Components actually solveboth of CSS's hard problems

  • They give us real style scoping and encapsulation. We can add elements to the page that won't be affected by the existing CSS.
  • We can abstract away presentational elements by putting them in the shadow DOM.

New Specs

  • Custom Element: developers can define their own DOM element with custom styling and functionality.
  • Shadow DOM: a subtree of DOM nodes that are rendered to the page but do not appear in the source.
  • HTML Imports: require() for the browser. Package up scripts, styles, and custom elements into a single bundle.

New Elements

  • <template>: DOM nodes that aren't parsed by the browser. They can be cloned and inserted dynamically later on.
  • <content>: an insertion point. Where nodes from the main document get rendered inside the shadow DOM.

A hello world element:

The main document:

            Newman
Newman

The element's shadow DOM:

            

Hello, ****

The rendered (composed) tree:

        
          ~~~~
          ~~

~~ ~~Hello, ~~ Newman ~~~~ ~~

~~

Let's see the code.

        // Create an object that will be the new element's prototype.
        var HelloWorld = Object.create(HTMLElement.prototype);

        // Add a callback to run whenever a new  tag is created.
        HelloWorld.createdCallback = function() {
          this.createShadowRoot().innerHTML =
            '' +
            '

Hello,

'; } // Register the element. document.registerElement('hello-world', { prototype: HelloWorld }); Callbacks reference  →

The Media Object

How it's done today (using BEM):

        
**
**

**
**

Notice how div.Media-body serves no semantic purpose.

How it could be done.

The main DOM:

            

Shadow DOM:

            
              ****
            
****

The composed tree

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

~~
~~ Media object demo  →

Extending elements

What if I don't like how the media object looks. How can I make it better?

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

        
          <style>…</style>
          ****
            
          ****
        
Author card demo  →

Abstract Layout Components

The <flex-line> element:

            
Flex line demo  →

The <flex-grid> element:

            
Flex grid demo  →

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

Building layouts from composable parts.

<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. You can use <flex-line> to compose other layouts.

The main document:

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

Composed tree:

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

FAQs (anticipated)

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

I've also put together a simple toy site that I was using to validate some of these concepts. You can find it on Github.

What browsers support these technologies?

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

Some features (like full style encapsulation) cannot be polyfilled, and so native support is required (Chrome 36+ only at this point).

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

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

But in general you should never use these selectors on your own elements, only on third-party components that aren't sufficiently extensible.

To quote the open/closed principle:

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

When should I put content in the shadow DOM vs the light DOM?

In general, dynamic content should be in the light DOM so your components can 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.

And search engines that can run JavaScript have access to all content, including shadow content.

Summary

Key points:

  • Style scoping via shadow DOM will make your code more resilient. Refactoring CSS is not something that should be feared.
  • CSS modularity will no longer come at the cost of dirty HTML. Implementation details can be abstracted into the shadows.

Questions?

Twitter @philwalton Website philipwalton.com Github github.com/philipwalton