I'm Tab Atkins, and I work on Chrome and CSS.

Hey! Slide decks aren designed for talks, not for reading like a web page. I wrote a blog post going over the same stuff, just with more talking and better organization.

Quick TOC

  1. Why the CSSOM sucks
  2. How we're fixing it
  3. CSS Variables!
  4. CSS Mixins!
  5. CSS Nesting!
  6. CSS Modules!

CSSOM = num + "px"; = "linear-gradient(" + color1 + "," + color2 + ")";


var w = parseFloat(;

Better hope it's in px, not em or % or something more esoteric like vw!

The browser already knows how to convert between the values; why should you have to do it again (probably with bugs)?

New CSSOM Values API

(Syntax not finalized.)

The browser deals with CSS as concrete values, not strings. We can expose the same thing to you. += 100; = 255;

var emwidth =;

var shadowColors =
    function(s){ return s.color.cssText; }

JS development always features CSS manipulation heavily.

These should make it much easier/faster/less buggy.

CSS Variables!

Variables! In CSS! OMG!

A common request for literally over a decade.

Why so long?

Previously, discussion was paralyzed by indecision and argument.

We're hoping enough agreement has crystalized that a strong experimental implementation can crash through the barriers.

Var Example

@var header-color color #006;
@var main-color color #06c;
@var secondary-color color #c06;
a { color: var(main-color); }
a:visited { color: var(secondary-color); }
h1 { 
  color: var(header-color);
  background: linear-gradient(left,var(main-color), transparent 25%);

Variables are typed. Every primitive value type, every property, and a few extra convenience types exist.

This lets us expose the new CSSOM stuff on them:

document.styleSheets[0].vars['main-color'].alpha = .5;

Variables are global normally - any rule in the document can access it.

Local Variables can scope a var to a single declaration block, for use in simplifying complex expressions:

.foo {
  @local grad background-image radial-gradient(red, blue, green, ...);
  background: url(foo.png), var(grad), blue;

CSS Mixins!

Mixins are blocks of rules that can be "mixed in" with normal blocks of rules.

They promote reusability when it's not appropriate to decorate the HTML with extra classes.

CSS Preprocessors like LESS pioneered here.

Mixin Example

@mixin error {
  background: #fdd;
  color: red;
  font-weight: bold;
div.error {
  border: thick solid red;
  padding: .5em;
  @mixin error;
span.error {
  text-decoration: underline;
  @mixin error;

Mixins can also take parameters, which function like local variables:

@mixin rounded-corners(size length 8px) {
  -moz-border-radius: var(size);
  -webkit-border-radius: var(size);
  border-radius: var(size);
.foo {
  @mixin rounded-corners(1em);

CSS Nesting!

Stylesheets often have tons of repetition in the selectors.

"#main > header > h1", "#main > header > h1 > a", "#main > header > h1 > a:visited", etc.

Verbose, hard to read, prone to hard-to-see errors

Nesting Example

#main > header > h1 {
  font-size: 2em;
  background: blue;
  color: white;
  @this > a {
    color: #ddf;
    @this:visited {
      color: #fdf;

Just syntax sugar for the long-form stuff.

Again, CSS preprocessors led the way.

Shorter stylesheets, better organization mean faster app development.

Explicitly indicates scoping opportunities, which might be useful for browser perf

CSS Modules!

Vars and Mixins are global by default

This is bad for widgets and similar, because they might clobber the author's Vars and Mixins, or be clobbered themselves

Simple namespacing/modules/whatever to fix this

Module Example

@module foo {
  @var bar color red;
  @mixin baz { color: blue; }
.foo {
  color: var(bar); // Doesn't work!
.bar {
  @use foo;
  color: var(bar); // Works!
.baz {
  @mixin foo|baz;  // Works!

Modules can be nested for further namespacing.

A single decl block can @use multiple modules.

So far, only vars, mixins, and more modules can be put in a module.


No, you cannot haz yet.

Only experimental, not in nightlies yet.

Spec will be produced this quarter.

Goal is experimental implementation in other browser before the end of the year.


Questions? Gimme your name and a random number first. I'll give out some books based on them.