Looking Into the Future of Sass
Sass is a CSS preprocessor. This is now common knowledge. First commit in 2007 by Hampton Catlin. Now the most used CSS preprocessor. Sass has come a long way since its beginning.
In case you are not very familiar with this stuff, I highly recommend you this article on topic by the David Walsh and this one by the Chris Coyier.
In any case, I'll assume you are pretty comfortable with Sass basics. Some of you may even be hardcore Sass hackers! Okay, what if we took a blog post to look forward into the future of Sass?
Version 3.3 incoming
It's been a while Nathan Weizenbaum and Chris Eppstein are working on version 3.3. As of today, the alpha version is already available (with its bugs of course) and I'm pretty confident saying the official version will be released anytime soon (no date announced).
So what's new in this brand new version of Sass? Well, quite a number of things. Most of them aren't officially announced as part of the v3.3 so I only have to guess:
- Sourcemaps (tagged 3.3)
- Improved
&
selector (tagged 3.3) - Improved
if()
function (tagged 3.3) - Advanced operations for lists (tagged 3.3)
- A new
list-separator()
function (guessed) - Maps support (planned)
- Improved
@for
loop (maybe) @at-root
rule (maybe)- New string manipulation functions (sniffed)
- Brand new
@import
(planned for 4.0)
On a side note, if you have the opportunity to be at CSS Summit 2013, don't miss it. Especially since Chris Eppstein will talk about Sass 3.3 with a lot of awesome people as well.
Sourcemaps
I think the greatest feature shipping in this version 3.3 has to be sourcemaps. Actually, sourcemaps aren't specific to Sass at all. It is a language-agnostic way to map production code to original code that was authored even after compilation and minification. Here is an introduction.
Ever inspected an element in the DevTools, wanted to edit its styles just before you realize the pointed source is something like styles.css:1
(first line of your CSS file)? Yes, that sucks because you don't edit CSS files but Sass files. Plus, everything is on line 1 in your CSS file (if everything's has been done properly).
Well, that's basically where Sass sourcemaps come in handy. Instead of having styles.css:1
, you may now have component.scss:42
. Isn't it better?
Five steps to be able to use Sass sourcemaps in your workflow:
- Make sure you use Chrome 28+
- Make sure you use Sass 3.3 Alpha (
gem install sass --pre
) - Go to chrome://flags and enable Developer Tools Experiments
- Open DevTools, go to General tab and check Enable source maps
- Open DevTools, go to Experiments tab and check Support for Sass
- Compile your stylesheets using
sass watch --sourcemap
Done. You have now told Chrome DevTools to use your freshly generated Sass sourcemaps (.map
files) to map your development code with your production code. You can now click (file names and properties) and access your Sass files.
Important! As of today, Sass 3.3 Alpha presents some serious issues when used along with Compass 0.13. You can't use compass watch
for now and have to use sass --compass --sourcemap --watch style.scss:style.css
. More informations on this issue.
Improved &
selector
You probably already know the reference selector (&
). It is a reference to the current selector when used in nested rules and can't be used at root level (throws a Sass error). The simplest use case is the following:
a { color: tomato; &:hover { color: deepskyblue; } }
This is the very basics. They have made a ton of improvements to this reference selector! Let's see a couple of them.
Using &
in selectors
Among several bug fixes, I believe they want to make possible to use the reference selector in more complicated selectors. Please consider the following example:
$base: ".module"; #{$base} { &#{$base}-something { /* ... */ } }
In this case, you define some kind of base selector for your module. Then want to apply styles to an element who would have the base selector class and a derived from the based selector class (.module
and .module-something
). This throws a Sass error (Invalid CSS after " &#{$base}": expected "{", was "-something {" "-something" may only be used at the beginning of a compound selector.).
In the next version of Sass, we will be able to do so by interpolating the reference selector in the selector like this (reference issue):
$base: ".module"; #{$base} { #{&}#{$base}-something { /* ... */ } }
Currently, the only workaround is to remove the dot from the base variable and explicitly use it in the selector like this:
$base: "module"; #{$base} { &.#{$base}-something { /* ... */ } }
This isn't great since it forces the pattern to use a class name since the .
is hard-coded in the nested selector. Still better than nothing while we wait for the new &
, right?
BEM-like syntax
One thing I'm really looking forward to is the expansion of the reference selector to allow a better BEM-like syntax. If you're not very familiar with the Block-Element-Modifier syntax, I highly recommend you these posts: MindBEMding - getting your head 'round BEM syntax.
The problem -if a problem it is- when writing BEM with Sass is you can nest anymore. Let's take a real dumb example:
.block { /* Base stuff */ } .block__child { /* Sub-element of block */ } .block--modifier { /* Variation of block */ }
This is what you want. Right? Unfortunately, you can't nest things here (there is nothing to nest whatsoever). What if we could right something like this...
.block { /* Base stuff */ &__child { /* Sub-element of block */ } &--modifier { /* Variation of block */ } }
This would be awesome. Syntactic sugar at its best. As of today, this throws a Sass error (Invalid CSS after " &": expected "{", was "__ child {" "__ child" may only be used at the beginning of a compound selector).
Thankfully, they will improve the reference selector in a way we can use this kind of syntax (reference issue). Quick note though, we will have to interpolate the reference selector as so: #{&}__child
. No big deal.
Prevent &
from bugging at root level
This case has been reported by Ericam from the Susy framework (reference issue). He made a mixin that uses the reference selector to draw a fallback for @media
rules for Internet Explore Here is is:
@mixin respond-to($media, $ie-class:'ie') { @media (#{$media}) { @content; } // We need the parent selector here in order to mimic the @media bubbling. .#{$ie-class} & { @content; } }
The idea is simple: he calls the mixin passing it a valid value for @media
, open braces and writes everything he wants inside. This will be displayed in a @media
block. Moreover, he wants another block to be created using the reference to the parent selector for Internet Explorer.
// This works already. .container { @include respond-to('min-width: 30em') { color: red; } } // This doesn't work. @include respond-to('min-width: 30em') { .container { color: red; } }
Calling the mixin from within a selector works like a charm. However calling the mixin from the root level throws a Sass error (Base-level rules cannot contain the parent-selector-referencing character '&'). This is because the &
selector can't be used at root level yet.
Understandable. Yet it should be usable while referencing nothing. This would make no arm and prevent Sass errors in cases like this. Hopefully this is likely they fix this problem in a future Sass release (reference issue).
Improved if()
function
Have you ever heard of the if()
function? It is an approximative equivalent to the well known notation variable = condition ? true : false
(JavaScript, PHP...). It works the same:
$a: 10; $b: if($a > 5, blue, red); // blue
Except one tiny problem... The function doesn't have conditional evaluation. To put it simple, the function works this way:
- Check condition
- Evaluate true result
- Evaluate false result
- Assign according result
When it should work like this:
- Check condition
- Evaluate according result
- Assign according result
This looks like I'm nitpicking but it makes a big difference in situations where one of the results shouldn't be parsed. Take the following example:
@function dosomething($argument) { $second-item: if( type-of($argument) == list, nth($argument, 2), $argument ); @return $second-item; } // This works like a charm dosomething( (item-1, item-2) ); // This throws an error dosomething( only-item );
This function returns the second element of the list if the given parameter is a list or the given parameter if it isn't. At least, that's its purpose. Unfortunately, this outputs: List index is 2 but list is only 1 item long for `nth' when passing it a single value or a 1 item long list.
This shouldn't fail. The normal behavior would be to check the condition, realize it is false in the current case, so jump to the 3rd argument without even trying to parse the 2nd one. Sadly, the if()
parses everything.
So they decided to fix this by making the if()
a parser built-in (reference issue).
Advanced operations for lists
Sass provides a decent number of functions to manipulate lists. They are all great especially the join()
function to append a list to another one. They are thinking of adding the +
operator for lists (reference issue).
$a: item-1, item-2, item-3; $b: item-4, item-5, item-6; /* Same as * $c: join($a, $b); */ $c: $a + $b; // item-1, item-2, item-3, item-4, item-5, item-6
This is really just syntactic sugar but still, I think this is nice. Now, Chris even proposed to implement the -
operator for lists!
$a: item-1, item-2, item-3; $b: item-3, item-4, item-1; $c: $a - $b; // item-1, item-2, item-3, item-4
The -
operator should remove from the first list all the values found in the second one. This could be a great feature when you want to remove -let's say- all false
and `null values from a list.
$a: item-1, false, item-2, null, item-3; /* Same as * $a: reject($a, false); * $a: reject($a, null); */ $a: $a - (false, null); // item-1, item-2, item-3
Even if this would be awesome, Nathan doesn't seem very interested in implementing the -
operator since the only language where things behave like this is Ruby. But not everybody's familiar with Ruby.
To end with lists, I heard the nth()
function you use to get the nth child of a list will now accept negative indexes to count from the end of the list instead of the start (reference issue). To get the last item, you will be able to do this:
$list: a b c d e; $last-item: nth($list, length($list)); // Old way $last-item: nth($list, -1); // New way
A new list-separator()
function
This one is a pretty small leap forward but I think this is the nice addition to all the kind of things we can do with Sass lists.
They plan to add a native list-separator()
function to determiner whether a list is separated by commas or spaces (reference issue). The usage is pretty straight forward:
$a: item-1, item-2, item-3; $b: item-1 item-2 item-3; list-separator($a) -> comma list-separator($b) -> space
The function returns either comma or space. Since every value in Sass is treated as a list, passing a single-element value will return space.
Maps support
It took me some time to hear about this one. It seems they want to add maps support to Sass 3.3 (reference issue). Maps are like associative arrays. Like a list of pairs where element A goes along element B.
map = { A: B, C: D }
This is a map. In a JSON-like language. As of today, I'm not sure I see the benefit of a map over a two-levels deep list. This is how you emulate a map in Sass with nested lists:
$map: ( A B, C D ); @each $pair in $map { $first-item : nth($pair, 1); $second-item : nth($pair, 2); }
It works great. It makes sense. That's why I don't really understand why they want to bring the map syntactic the language. Actually I can see one (good) reason: making the syntax more structured and less hacky.
In any case, this what I could find regarding the incoming syntax:
$map: ( a: b, c: d ); @for $key, $value in $map { /** * $key is what we called $first-item * $value is what we called $second-item */ }
And that's it for now. They couldn't settle things down regarding other features like map-creations, keyword arguments and such. From what I heard, only the basics will land in 3.3; remainder will come later. For more informations on Sass maps, follow this issue.
Improved @for
loop
We love loops. Loops are awesome! They are a great way to reduce the amount of code required for some tasks. Sass provides the usual 3 different types of loops:
@for
: let a variable i from m through n@while
: while a condition is true@each
: for each element in the array
They are all great. However the @for
loop has a tiny issue. Have you ever tried initializing a @for
loop going backward (i.e. decrementing)? Something like:
@for $i from 5 through 1 { /* Do something with $i */ }
Well don't bother, this will output nothing. Not even a Sass error. Currently, the only workaround for this stuff is doing so:
@for $i from -5 through -1 { /* Do something with abs($i) */ }
Basically, you turn both values negative, making the loop incrementing again, then you deal with abs($i)
instead of $i
to access the value you wanted in the first place.
Anyway, they plan on fixing this bug for the 3.3 (reference issue). Chris Eppstein would also like to add a feature to increment/decrement the value by another value from 1. It should look like this:
@for $i from 1 through 10 by 2 { /* Do something with $i */ }
However Nathan Weizenbaum doesn't seem very in agreement with complicating the @for
syntax for such a borderline thing that can easily be reproduced by hand.
@for $i from 1 through 10 { @if $i % 2 != 0 { /* Do something with $i */ } }
@at-root
rule
Okay, I'll be perfectly honest with you: this one is a mystery to me. The @at-root
directive takes a nested chunk and move it to the root level. Fine, this is nice. But why? Why couldn't you just write it at root level in the first place?
I couldn't find much information regarding the @at-root
rule except for the syntax. Here are a couple of usecases:
/* Example 1 - Sass */ .foo { @at-root .bar { color: gray; } } /* Example 1 - CSS */ .bar { color: gray; } /* Example 2 - Sass */ .foo { @at-root .bar & { color: gray; } } /* Example 2 - CSS */ .bar .foo { color: gray; } /* Example 3 - Sass */ .foo { @at-root { .bar { color: gray; } } } /* Example 3 - CSS */ .bar { color: gray; }
You know what? I won't go any further on this @at-root
thingie. They seem to be pretty confident regarding the way they'll implement this feature but I don't see much use cases for this. More informations on this issue.
New string manipulation functions
While sniffing into unmerged branches of Sass code, I realized they were planning on adding quite a few functions to ease string manipulation along with the already existing quote(string)
and unquote(string)
(reference file). I found 5 of them:
str_length(string)
: returns the length of$string
str_insert(string, insert, index)
: insert$insert
into$string
at$index
str_index(string, substring)
: returns index of first occurrence of$substring
in$string
str_slice(string, start_at, end_at = nil)
: returns a substring from$string
starting at index$start-at
and ening at index$end-at
to_upper_case(string)
: returns$string
to upper caseto_lower_case(string)
: returns$string
to lower case
Brand new @import
Last but not least, they plan on redoing the whole @import
function from scratch to replace it with a more powerful, module-aware import mechanism. However this will definitely not land in 3.3; according to Chris, this will be the main feature of Sass 4.0. Among other things, the new version would allow:
@import-once
- importing regular CSS files
- namespacing
- auto-looking for
index.scss
orindex.sass
when importing a folder - importing all files from a folder (maybe?)
Please note this is really just speculating. I've gathered this list from opened issues related to @import
. By the way, I've got rid of proposals that didn't please either Nathan or Chris.
Import once
If you're familiar with PHP or other programming languages, you'll probably know the include_once
directive (with a quite similar syntax). The idea is to import a file once and only once.
In the current state of things, if you import twice the same file the compiler outputs twice the content of the imported file. Not great!
A workaround proposed by Seanofw is to use a little function appending filenames into a list, then checking filenames to make sure the files are only included once.
$imported-once-files: (); @function import-once($name) { @if index($imported-once-files, $name) { @return false; } $imported-once-files: append($imported-once-files, $name); @return true; } @if import-once("_SharedBaseStuff.scss") { /* ...declare stuff that will only be imported once... */ }
Thankfully, the new @import
will be simpler to use than this function (reference issue)!
Importing regular CSS Files
One thing that can be annoying when you move a CSS project to a Sass/SCSS one is you can't import regular CSS files in a Sass stylesheet. It makes sense since it will completely crash the whole thing if you use the Sass syntax.
I think Normalize.css is the perfect example. When doing @import "normalize"
, the compiler will do nothing if the only matching file is a regular .css
file. So you have to convert the CSS file to a Sass/SCSS file; this sucks.
It should be possible with the new @import
(reference issue).
Importing index as default
Depending on your architecture, you may manage your files in folders. Like a folder helpers containing a folder per mixin, with a single file within each. It has been proposed to implement the basic behavior of looking for a file called index
when importing a folder.
So you can have something like this:
/* Current way of doing */ @import "helpers/clearfix/index"; /* New way of doing */ @import "helpers/clearfix";
Definitely not a major feature; plus I don't see the point of managing files in folders instead of direct files but still... Should be possible (reference issue).
Import all files from a folder
Same idea, pushing things further would be to be able to import all files from a folder at once. This is also called "Sass globbing" and currently exists as a Sass plugin by Chris Eppstein himself (I think this will be merged with Sass in 4.0).
This allows you to do things like this:
/* Import all files from folder helpers */ @import "library/helpers/*"; /* Import all folders from folder library */ @import "library/**/*";
However please note files are being imported in alphabetical order. This may or may not break things in your implementation.
Namespacing
One big thing missing to CSS (and in a lesser extend, Sass) is namespacing. Everything is in a the global scope. On-topic, I highly recommend you Please respect CSS global namespace by Kaelig.
Anyway, they are thinking of adding a namespace to imports (reference issue) so you can have a finer control over your files and your project.
Since this is a big feature under discussion, there is no decided syntax for namespacing files. I guess this could look like this:
@import "file"; @import "file-2" as "Module"; .element { @extend file%placeholder; @include Module.mixin(); }
This is just my idea, don't take this seriously please. If you want to contribute to this issue, please refer to this GitHub issue.
Miscellaneous
Hey, don't leave yet! Little gift, just for you. I crawled into unmerged branches of Sass code to find other pieces of cool stuff!
Unique ID
It turns out there is unique-id()
function returning a unique random identifier (scoped into a Sass run) as an unquoted string. Based on what I can understand from the Ruby code, it returns a 9-characters long alphanumeric string starting with a u
. Probably like u214ab34e
.
I'm not quite sure what's the main purpose of such a thing in itself. However, this could be a way to get a random number in Sass I guess. Let me try...
@function parse-unique-id($value) { $letters: a b c d e f g h i j k l m n o p q r s t u v w x y z; $value: unquote(""); @for $i from 1 through str-length($value) { $letter: str-slice($value, $i, $i + 1); @if index($letter, $letters) == false { $value: str-insert($value, $letter, str-length($value) + 1); } } @return $value; } $number: parse-unique-id(unique-id());
This code snippet won't compile if you test it yet, even with the latest build since it relies on incoming features. Basically, it checks each character of the value of unique-id()
: if it is a letter, it removes it.
It will give you a random number between 0 and 9999999. Do whatever you want with it. :D
Existence checks
I found a couple of functions which I believe are mostly made for internal gearing or Sass libraries (reference issue). Basically they allow you to test whether a variable, function or whatever exists in the current state.
variable_exists(named)
global_variable_exists(named)
function_exists(named)
mixin_exists(named)
There also seems to be a feature_exists(named)
function which is meant to check if a feature exists in the current Sass runtime. I guess it will be used in future versions to check whether a given feature exists or not.
Final words
Okay, I guess it will be all. Please, keep in mind most of this stuff is the result of code sniffing and GitHub issue spying; no date or guarantee announced for any version/feature.
If you're interested in incoming features of Sass, I recommend you have a glance at the official repo.
Thanks for reading anyway! See you!
About Kitty Giraudel
Front-developer from France. Author at Codrops, helper at CSS-Tricks, curator of Browserhacks. CSS Goblin, Sass hacker, margin psycho. You can catch me on HugoGiraudel.com or Twitter.
Excellent article, thank you for that. I‘m already using Sass 3.3 because of sourcemaps. This feature is just indispensable.
There‘s just one thing that‘s bugging me: people use the term Sass, when they actually mean SCSS. Everytime someone writes “Sass” and I see some curly brackets, I get goose bumps. IDK, maybe it‘s just the Monk in me.
@Lars the `SASS` you are referring to is the 1.X syntax while `SCSS` is the syntax of 2.X+. The `SASS` term the others are using is the CSS preprocessor as a whole (no matter which syntax the user prefers).
I’m definitely most excited about source maps. Had no idea you could use them now. I’m not sure how useful it would be to anyone whose workflow is entirely different from mine, but I came up with a methodology for writing BEM-style Sass that kind of reflects the improved syntax Hugo was talking about. I’m trying to get some feedback on it. https://github.com/chatrjr/single-responsibility-bem
Hell! I did not know Sass is going to be that much of a deal especially with source maps. The possibilities seems a lot and I should better start getting on this before I miss the train of next big thing in web development. Thanks for sharing was quite insightful
I think it would be great for SASS to group
@media
query contents.For example if i have multiple places where elements are styled in a media query, SASS could concatenate all other styles that are under the same media query.
If i have modular structure i have multiple small sass files, where with in each if needed have
@media
query to style module in some conditions. In other file i have styled other module, but under the same conditions.So on compiling sass could put them together :)
Well, it isn’t *that* simple.
First of all, merging all equivalent
@media
rules isn’t without risks: reording is the most important I could think about. What if the compiler mess with the order of your styles and break something? Nested @media rules could be another issue I guess, even if it’s probably less frequent.Secondly (and most importantly), there would be little if not any performance impact with such a feature. Yes, the CSS code would probably feel more right (but we shouldn’t care much about the look of the output) but the performance impact would be essentially null since Gzip is amazingly efficient when it comes to compress repeated strings.
Someone asked me about this at the end of my last talk. Here is the article that cover my entire talk (see Q&A section): http://hugogiraudel.com/2013/07/08/digging-into-my-slides-sass/#QA.
Tl;dr is: merged media queries wouldn’t bring much as long as you GZip your stylesheets.
When I was reading about BEM CSS syntax, I was hoping that SASS might have implemented a feature that automatically “transforms” your selectors to BEM from normal CSS… but we got something just as good. And if no one does make the “converter”, I’m sure someone can come along and make one. Great tutorial.
Great article, I fall in love with SASS as soon as I started using it.
Another question for using SASS together with compass, I hope it is related: when I include the imported sprites in the
@media
queries, like@include
icons-sprite(twitter); I get the DEPRECATED warning:… (accedently hit enter).
Here is the warning:
DEPRECATION WARNING on line 337 of icons/*.png:
@extend
ing an outer selector from within@media
is deprecated.You may only
@extend
selectors within the same directive.This will be an error in Sass 3.3.
It can only work once @extend is supported natively in the browser.
What to do about this issue? Will this more a problem of the Compass?
You cannot use
@extend
inside a@media
block.For those having troubles installing Sass using
(reported here
Try adding the version flag like:
get sass latest version: http://rubygems.org/gems/sass
Hi Hugo, I’m on the core team for Less.js although I use SASS from time to time as well.
Great write-up in general, but you made this statement, asserted as fact: “Now the most used CSS preprocessor. Sass has come a long way since its beginning.” Indeed, SASS — and preprocessors in general, have come a very long way. But I’m curious, do you have any kind of research or data to back up that statement that SASS is the most used processor? I ask because all available research indicates otherwise. For instance, here is a survey conducted by CSS Tricks where Chris Coyier describes the results: http://css-tricks.com/poll-results-popularity-of-css-preprocessors/
Conducted about a year ago, the survey had 13,000 responses and showed that of the ~54% of people who used preprocessors:
* ~51% preferred LESS
* The other ~49% was split across all other processors, including SASS, SCSS and Stylus.
Also about a year ago, at the time of the survey, LESS had approximately twice the community of SASS on GitHub, which is a different source of data that is consistent with the survey’s results. However, today the LESS GitHub community is just shy of 4 times the size of SASS (5 times if you measure forks instead of stars):
* SASS – 2,263 stars, 359 forks
* Less.js – 8,860 stars, 1,760 forks
Obviously GitHub is just one slice of data, but the stats on GitHub are pretty consistent with data we’ve accumulated from other sources (including publicly available data and paid).
In fact, our own research indicates that, demographics-wise, the majority of the LESS user base is designers and that the majority of those designers do not even use GitHub. On the other hand, our research also shows that the vast majority of the SASS user base is developers. Infer from that what you will, but it seems reasonable to assume that _in general_ developers are more likely to have an account on GitHub than designers. So the divide might be much larger than what is supported by the real data we have access to.
In any case, I’m just curious if there have been other publicly available surveys or studies since the one I linked to that indicate a material shift in user base from LESS to SASS? If so, since you made the claim I think it would be great if you could post links to whatever you have to back it up. We (the Less.js team) would appreciate it, it would also help us to know what’s important to our users and can do what’s necessary to shift focus. If you don’t have any data to back it up, then perhaps you should consider amending the statement?
Thanks for taking the time to comment Jon.
While I respect your position on the LESS team, I have to defend Hugo here. A few thoughts:
1. Sass’ reputation is one of progress and forward-thinking, while LESS has the reputation of being negelected and slow to release. This isn’t just my opinion, but that of many of my developer friends I asked.
2. Measuring popularity is largely irrelevant, so I don’t think it weighs much on this post.
I will simply add what you asked from me, data: http://blog.codepen.io/2013/04/08/statistics-on-preprocessor-usage/.
CSS-Tricks poll is from 06/2012. CodePen data gathering is from 04/2013.
Unfortunately, when Googling for data around CSS preprocessors usage, it is the CSS-Tricks article that comes up. :(
The @at-root thing sounds very useful for dealing with state. Imagine using Modernizr; according to your example, you’d be able to do this:
Right?
It already works without @at-root. :)
Do you know of any way to test Sass 3.3 online, similar to http://sassmeister.com/ or http://sass-lang.com/try.html ?
As I don’t have a machine with Ruby installed, I’m currently using http://sassmeister.com/ to experiment with building a Sass-based metaframework around Cascade Framework ( http://cascade-framework.com/ ).
As I need string manipulation functions to replace certain characters in a string before using that string to generate dynamic placeholders, I literally can’t wait until Sass 3.3 is finished.
Do you know of any place where I can test Sass 3.3 online? That way, I can continue development without being forced to install Ruby.
Hi John!
Even with Ruby, you cannot try all these 3.3 features yet. As far as I know, the only one available on the alpha build is Sourcemaps.
You’ll have to wait. ;)
For me selector inheritance is a deal breaker… but maybe I’m not understanding it correctly.
In LESS the following:
Produces:
But in SASS it produces:
Am I wrong in saying that LESS does not support selector inheritance as efficiently as SASS?
I think that’s right. Sass creates more efficient CSS in this example.
The following examples should give you a good idea of how to use Sass and what it can do…
Including one selector into another selector allows you to create create eg. child or descentant selectors
Example 1 :
————-
.class1 {
font-weight: bold;
.class2 {
color: red;
}
.class3 & > .class4 {
font-size: 13px;
}
.class5 > }
Result 1 :
————-
.class1 {
font-weight: bold;
}
.class1 .class2 {
color: red;
}
.class3 .class1 {
color: green;
}
.class1 > .class4 {
font-size: 13px;
}
.class5 > .class1 {
font-size: 16px;
}
———————
Using “mixins” allows you to include styling rules into selectors or other styling rules :
Example 2 :
————-
$default-font-size : 13px;
@mixin font-size($value) {
font-size: $value;
}
@mixin font-size-default {
@include font-size($default-font-size);
}
.class1 {
@include font-size-default;
}
.class2 {
@include font-size-default;
color: red;
}
Result 2 :
————-
.class1 {
font-size: 13px;
}
.class2 {
font-size: 13px;
color: red;
}
———————
Using “Extend” allows you to extend an existing selector :
Example 3 :
————-
.class1 {
font-size: 13px;
}
.class2 {
@extend .class1;
color: red;
}
.class3 {
@extend .class2;
font-weight: bold;
}
Result 3 :
————-
.class1, .class2, .class3 {
font-size: 13px;
}
.class2, .class3 {
color: red;
}
.class3 {
font-weight: bold;
}
———————
Placeholders act as a virtual selector. When you do not extend them, they generate no output. When you do extend them, they behave pretty much like a normal selector :
Example 4 :
————-
%font-size-10 {
font-size: 10px;
}
%font-size-11 {
font-size: 11px;
}
%font-size-12 {
font-size: 12px;
}
%font-size-13 {
font-size: 13px;
}
%font-size-14 {
font-size: 14px;
}
%color-blue {
color: blue;
}
%color-green {
color: green;
}
%color-yellow {
color: yellow;
}
%color-red {
color: red;
}
.class1 {
@extend %font-size-13;
@extend %color-red;
}
.class2 {
@extend %font-size-11;
@extend %color-yellow;
}
.class3 {
@extend %font-size-12;
@extend %color-blue;
}
.class4 {
@extend %font-size-13;
@extend %color-green;
}
.class5 {
@extend %font-size-12;
@extend %color-green;
}
.class6 {
@extend %font-size-11;
@extend %color-red;
}
.class7 {
%color-red {
font-weight: bold;
}
%font-size-10 {
margin: 10px;
}
%font-size-11 {
text-decoration: underline;
}
}
Result 4 :
————-
.class2, .class6 {
font-size: 11px;
}
.class3, .class5 {
font-size: 12px;
}
.class1, .class4 {
font-size: 13px;
}
.class3 {
color: blue;
}
.class4, .class5 {
color: green;
}
.class2 {
color: yellow;
}
.class1, .class6 {
color: red;
}
.class7 .class1, .class7 .class6 {
font-weight: bold;
}
.class7 .class2, .class7 .class6 {
text-decoration: underline;
}
———————
Finally, control directives like @if / @else, @for or @each allow you to use Sass as a programming language :
Example 5 :
————-
@for $i from 1 to 30 {
%font-size-#{$i} {
font-size: #{$i}px;
}
}
@each $color in (black, blue, green, yellow, red, purple) {
%color-#{$color} {
color: $color;
}
}
@mixin generate($classname, $font-size, $color) {
.#{$classname} {
@if $font-size != ” {
@extend %font-size-#{$font-size};
}
@if $color != ” {
@extend %color-#{$color};
}
}
}
@include generate(class1, 13, red);
@include generate(class2, 11, yellow);
@include generate(class3, 12, blue);
@include generate(class4, 13, green);
@include generate(class5, 12, green);
@include generate(class6, 11, red);
@include generate(class7, ”, yellow);
@include generate(class8, ”, blue);
@include generate(class9, 25, ”);
Result 5 :
————-
.class2, .class6 {
font-size: 11px;
}
.class3, .class5 {
font-size: 12px;
}
.class1, .class4 {
font-size: 13px;
}
.class9 {
font-size: 25px;
}
.class3, .class8 {
color: blue;
}
.class4, .class5 {
color: green;
}
.class2, .class7 {
color: yellow;
}
.class1, .class6 {
color: red;
}
If you want to try playing around with the possibilities of Sass without installing Sass on your own system, I highly recommend http://sassmeister.com/ . Just write your Sass-code on the left and you’ll see the CSS output immediately on the right.
Looks like something went wrong with my layout… and of course I can’t edit my post :-s
Just try copy-pasting my code examples to http://sassmeister.com/ and try for yourself how much more powerful Sass really is than LESS…
Isn’t nesting contrary to BEM principles? I hope the output from the example above to be 1 level deep.
Great round up.
I like the idea of namespacing imports, it could be a good addition when using multiple frameworks / plugins.
PS: Thanks for referencing my article on the global CSS namespace.
@at-root is good for concatenation of classes. See https://github.com/nex3/sass/issues/286#issuecomment-18437694 for more details.
Quote: “So you’d write ‘foo { @at-root .bar#{&} { … } }’, which would yield ‘.barfoo { … }’.”
http://422LP9R.TK cheap 422LP9R electronic components cheap electronics components for sale , most style electronics components can be find on our web , even many hard to find components , buy electronics components at our web is best choose . go to our web find what you need and ask for a quote now .
I had the same reaction to @at-root, but see a couple of use cases:
1) refactoring existing, bloated sass with very deep nests, to create leaner compiled css. The nesting is useful also as a code organization. @at-root can abstract out the code organization from the css depth.
@at-root .slider could keep the slider contextualized in a certain page region but the compiled css lean.
Not everyone gets the option to build from scratch using the best practices of right now.