What's new in

Sass 3.4

Code examples shamelessly taken from:

http://www.phase2technology.com/blog/everything-you-need-to-know-about-sass-3-4/

Watch Locally: http://slides.com/akoebbe/what-s-new-insass-3-4/live

Install Sass 3.4

$ gem install sass

Via Gem

gem 'sass', '~> 3.4.0'

Via bundler (Gemfile)

Busting the '&' out of jail

We could only do this

ul {
    li {
        background: blue;
        &:hover {
            background: red;
        }
    }
}

Now we can do this...

nav{
    ul {
        li {
            $selector: &;
            foo: $selector; // nav ul li
            bar: length($selector); // 1
        }
    }
}

...and this

nav, header .container{
    ul {
        li {
            $selector: &;
            foo: $selector; // nav ul li, header .container ul li
            bar: length($selector); // 2
            baz: length(nth($selector, 2)); // 4
            qux: nth(nth($selector, 2), 1); // 'header'
        }
    }
}

Shuffle your selector chains

Appending selectors

nav{
    ul {
        li {
            $new-selector: append(nth(&, 1), a);
            @at-root #{$new-selector} {
                color: pink;
            }
        }
    }
}

// Resulting CSS

nav ul li a {
  color: pink;
}

(This is just silly)

selector-append()

#{selector-append(".foo .bar", ":hover")} {
    background: pink;
}

.foo .bar{
    &:hover {
        background: red;
    }
}

// Both result in

.foo .bar:hover {
    background: red;
}

selector-nest()

#{selector-nest(".foo, .bar", ".qux")} {
    background-color: red;
}

.foo, .bar {
    .qux {
        background-color: red;
    }
}

// Both result in

.foo .qux, .bar .qux {
    background-color: red;
}

Mess with your parents

Age old problem

.tabs {
    .tab {
        background: red;
        &:hover {
            background: white;
            .tab-link {
                color: red;
            }
        }
        .tab-link {
            color: white;
        }
    }
}

Meet selector-replace()

.tabs {
    .tab {
        background: red;
        &:hover {
            background: white;
        }
        .tab-link {
            color: white;
            @at-root #{selector-replace(&, '.tab', '.tab:hover')} {
                color: red;
            }
        }
    }
}

But we can do better...

@mixin context($old-context, $new-context) {
    @at-root #{selector-replace(&, $old-context, $new-context)} {
        @content;
    }
}
.tabs {
    .tab {
        background: red;
        &:hover {
            background: white;
        }
        .tab-link {
            color: white;
            @include context('.tab', '.tab:hover') {
                color: red;
            }
        }
    }
}
// Output
.tabs .tab { background: red; }
.tabs .tab:hover { background: white; }
.tabs .tab .tab-link { color: white; }
.tabs .tab:hover .tab-link { color: red; }

But wait, there's more!

More selector functions

selector-extend(".a .b", ".b", ".foo .bar") => .a .b, .a .foo .bar, .foo .a .bar
selector-unify(".a", ".b") => .a.b
selector-unify(".a .b", ".x .y") => .a .x .b.y, .x .a .b.y
selector-unify(".a.b", ".b.c") => .a.b.c
selector-unify("#a", "#b") => null
is-superselector(".foo", ".foo.bar") => true
is-superselector(".foo.bar", ".foo") => false
is-superselector(".bar", ".foo .bar") => true
is-superselector(".foo .bar", ".bar") => false

It's like a frickin cornucopia

  • The selector-parse($selector) function takes a selector in any format accepted by selector functions and returns it in the same format returned by &. It’s useful for getting a selector into a consistent format before manually manipulating its contents.

simple-selectors(".foo.bar") => ".foo", ".bar"
simple-selectors(".foo.bar.baz") => ".foo", ".bar", ".baz"
selector-parse(".foo .bar, .baz .bang") => ('.foo' '.bar', '.baz' '.bang')

Extra Credit

What's new in Sass 3.4

By akoebbe

What's new in Sass 3.4

  • 1,777