Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does sass harm performance?

I've been educating myself. Reading this:

The engine evaluates each rule from right to left, starting from the rightmost selector (called the "key") and moving through each selector until it finds a match or discards the rule. (The "selector" is the document element to which the rule should apply.)

For example:

ul li a {...}
#footer h3 {...}
* html #atticPromo ul li a {...]

Now, some example code SASS outputs for me:

#content #blog {
  /* ... */
}
/* line 85, ../sass/screen.scss */
#content #flickr {
  /* ... */
}

#content #flickr div p {
  /* ... */
}

This seems a bit awkward.. am I doing something wrong? Is this a communication problem between me and Sass? Are we losing it?

Edit: Some SCSS code:

#flickr {
    @include columns(5,8);
    background: url('../img/ipadbg.png') no-repeat;

    #ipod-gloss {
        z-index: 999;
        position: relative;
    }

    div {
        margin-top: -80px;
        margin-right: 20px;

        h2 {
            color: $white;
            font-size: 24px;
        }

        p {
            margin-top: 40px;
        }
    }
}

Side Bonus!: The article says browsers (or at least Firefox) search the selectors from right to left. I couldn't understand why this is a more efficient why. Any clues?

like image 359
CamelCamelCamel Avatar asked Jul 26 '11 05:07

CamelCamelCamel


2 Answers

You have to find your compromise between maintainability (nesting makes it easier to find your way around in the stylesheet) and rendering performance.

A rule of thumb says you should try to restrict yourself to a three-level nesting and you should avoid to nest IDs if it's not necessary.

However, I think nesting too much is not the biggest issue. As soon as I became aware of the power of mixins, I used them a lot.

For example, this is my often used button mixin:

@mixin small-button($active-color: $active-color, $hover-color: $button-hover-color, $shadow: true)
  display: inline-block
  padding: 4px 10px
  margin:
    right: 10px
    bottom: 10px
  border: none
  background-color: $button-color
  color: $font-color-inv
  +sans-serif-font(9px, 700)
  text-align: center
  text-transform: uppercase
  cursor: pointer
  @if $shadow
    +light-shadow
  &:hover
    text-decoration: none
    background-color: $hover-color
  &:last-child
    margin-right: 0
  a
    color: $font-color-inv
    &, &:hover
      text-decoration: none
  &.disabled
    +opacity(0.75)
    &:hover
      background-color: $button-color
  &.active
    background-color: $active-color
    &.disabled:hover
      background-color: $active-color

You see, quite a bit code. Applying such mixins to many elements on your page will result in a big CSS file which takes longer to be interpreted.

In the old fashioned CSS-way you would give each button element e.g. the class .small-button. But this method pollutes your markup with unsemantic classes.

Sass provides a solution though: selector inheritance via the @extend directive.

If you set defaults for your parameter of the mixin, you can also provide a simple class, which uses the mixins with your default:

// Use this mixin via @extend if you are fine with the parameter defaults
.small-button
  +small-button

And then you can just inherit from this class in various contexts:

#admin-interface
  input[type=submit]
    @extend .small-button

The resulting CSS statement aggregates all usages of .small button into one rule with comma-separated selectors:

.small-button, #admin-interface input[type=submit] {
  display: inline-block;
  ...
}

Concluding, a naive usage of Sass can effect your CSS performance. Used wisely, however, it is maintainable thanks to well-structured and DRY code, it leads to proper separation of markup and styling (semantic classes only) and allows for smart and performant CSS code.

like image 150
crispy Avatar answered Oct 23 '22 00:10

crispy


SASS is only a language that compiles down to CSS. If you're concerned with SASS' performance in terms of how it runs in the browser, then SASS doesn't enter the equation -- it'll be compiled and served to the browser as regular CSS.


From what I can see of your usage of SASS, there's a couple of things I could suggest:

  1. You don't have to nest everything.

The ability to nest rules inside each-other in SASS is a language feature, but you don't have to do it if it doesn't make sense to do so.


In terms of your general CSS usage:

  1. If the nesting gets too severe/unwieldly, consider using classes where it makes sense.
  2. When it's necessary to use the hierarchy of DOM elements, consider using the [child combinator]: .foo > .bar.

IDs are meant to be unique, thus should always only reference a single element. Most of the time, they can be CSS rules unto themselves -- #content #flickr would become just #flickr, for instance -- and browsers will optimise the lookup for a single ID. The only time you would need something like #id1 #id2 is if #id2 needs to appear in different contexts on different pages.

If your selector contains things like #id div p, that div is either superfluous or serving a specific purpose.

  • If it's superfluous, change the rule to #id p, which selects any <p> that occurs as a descendant of #id.
  • If it serves a specific purpose, consider classing the <div> with a class name that describes its purpose -- perhaps <div class="photos-list">. Then your CSS could become .photos-list p, which is far more maintainable and reusable.

like image 28
Chris Avatar answered Oct 22 '22 23:10

Chris