Picture this:\n\nA backend dev has been hauled away from their microservices, their exquisitely defined APIs, and their layers of abstraction… and thrown onto a front-end team to help out.\n\nThere’s a crunch on, and deadlines must be met.\n\nOur backend dev, tasked with fixing some styling issues, delves into the CSS, and horror:\n\n
\n\nYes, magic numbers as far as the eye can see, font stacks repeated everywhere, and styles presented in an unstructured and endless parade of CSS selectors.\n\nModern CSS once saved us from inline HTML styles, but now it’s back to eat us alive. Of course, this isn’t the fault of CSS.\n\nSprawling CSS definitions are just a product of complex web applications with large, active teams.\n\nBut there is an excellent solution to such problems: CSS Preprocessors.\n\nIn particular, the Sass CSS preprocessor is a great option for bringing some sanity to undisciplined CSS styles, which would make our backend dev much happier.\n\nIf this sounds good to you, then read on to learn:\n\n
- \n
- How the Sass CSS Preprocessor can simplify your CSS with nesting, variables, mixins, and inheritance.
- How to install Sass and start using it on your own CSS immediately.
- How to set up a Sass to automatically process your Sass-y CSS.
\n
\n
\n
\n\nThis article does assume that you’re at least a little familiar with CSS. If you’re not, check out this article for a beginner-friendly intro to CSS, and then come right back.\n\n
So What’s a CSS Preprocessor?
\n\nA CSS Preprocessor is a development tool that takes something that’s better than regular CSS and spits out normal CSS you can load in a browser.\n\nThere are lots of tools that do this. Some of the most common ones include Less, Sass, Stylus, and PostCSS.\n\nEach of these tools has its own syntax for adding features to CSS, such as:\n\n
- \n
- Nesting (or hierarchy) – structure your styling rules so that the relationship between them becomes obvious.
- Variables – no more magic numbers!
- Mixins – define a set of styles once and use it many times.
- Inheritance – one CSS rule can inherit from and “extend” another.
\n
\n
\n
\n
\n\nThese are great features and they’re offered by nearly all of the CSS preprocessors, but let’s take a closer look at one preprocessor in particular: Sass.\n\n
What Is Sass?
\n\n
\n\nTo begin with, Sass stands for “Syntactically Awesome Style Sheets,” which sounds like a justification for a cool acronym to me, but they do deliver—Sass is syntactically awesome.\n\nIt’s also the most widely used CSS preprocessor. A 2016 survey found that 63 percent of web developers use Sass.\n\nIt was originally implemented in Ruby, a dependency that grated on many developers, but fortunately Sass is now a fully-fledged part of the npm (node package manager) packaging and build system.\n\nThat makes it as easy to install and use as any other npm package.\n\nBesides that, Sass has excellent tooling support and a syntax that strikes a good balance between being concise and readable.\n\nFinally, it’s easy to learn and start using straight away.\n\n
Warning! SCSS vs Sass
\n\nThere’s a very confusing situation with Sass right now—it supports two quite different syntaxes. One of those syntaxes is just called Sass; the other is called SCSS.\n\nThe fact that there’s the tool and a syntax called Sass doesn’t really help either.\n\nSass syntax vs SCSS syntax is one of those things that folks like to engage in holy wars over, but I prefer SCSS because:\n\n
- \n
- SCSS is a superset of CSS3—plain CSS3 is processed successfully by Sass.
- SCSS is a bit easier to pick up if you’re new to SCSS.
- It’s the default syntax used in the official Sass docs, which makes life easier when you’re reading up on Sass.
- It’s way easier to start improving an existing project’s CSS (the normal situation for me) by slowing adding SCSS rules to it. Transforming a large existing set of CSS rules into Sass would be a big job.
\n
\n
\n
\n
\n\nHaving said that, you should check out the Sass syntax as well, especially for new projects. All these concepts apply to it, but it’s a much more terse syntax.\n\nSo when you see some Sass styling here, it’s in the SCSS syntax.\n\n
Sass Features You Can Use Right Now
\n\nRight! It’s time to get our CSS in order. We’re going to look at Sass’s features first, and then get into installing and using it to process some sample Sass styles.\n\nWe’ll start by adding some structure to our CSS:\n\n
Nesting with Sass
\n\nHere’s the thing about CSS: when you’re looking at a CSS file, you have to imagine the structure of the page the style rules will be applied to.\n\nFor example:\n\n\n\nFrom the above, we know that there’s default definition for li elements, and that there’s some kind of side navigation, which is going to have li elements with anchor elements inside them.\n\nThat’s easy to understand, but you need to think about how the elements are structured.\n\nHow about this instead:\n\n\n\nNot only do we have just one entry for #sidenav, but we can see that it is going to have li elements inside it, which in turn contain anchor elements. The nested structure is a lot more intuitive.\n\nWhat about media queries? They’re an incredible source of duplicated CSS selectors. Well, they can be nested as well, which saves us from specifying the same selectors repeatedly:\n\n\n\nSo, no more repeating all your selectors in @media queries—now the media queries can sit right inside the selector.\n\nBut, I can totally hear you saying, what about that media query appearing over and over again, with those hard-coded max-width values?\n\nThat’s going to be a maintenance nightmare.\n\nLuckily, Sass takes care of this too, with the addition of variables.\n\n
How Variables Can Help Sass CSS
\n\nProgrammers have DRY (Don’t Repeat Yourself) drilled into them, and then have to use CSS, which hasn’t even heard of DRY.\n\nThe introduction of variables in Sass allows us to define a value once as a variable we can use throughout our style rules. That’s way more DRY.\n\nWhile it’s possible to redefine Sass variables, it’s better to treat them like a constant, so if you need to change that value, you only need to change it in one place.\n\nLet’s see how that works by expanding on our previous example:\n\n\n\nHere we are repeating that max-width value over and over again in our media queries. What if we want to change the screen width we start adapting our styles to? Then we’d have to change all those @media queries.\n\nInstead of doing that, we could use a variable:\n\n\n\nSetting the $mobile-screen variable and using it in our media queries makes our CSS much more maintainable. A nice bonus is that we also have a meaningful name applied to our max-width.\n\nThe syntax for variables is very similar to that of the normal CSS style rules:\n\n\n\nThe variable is just like a normal style rule except is has a $ at the start, and it doesn’t have to appear inside a CSS selector.\n\nOf course, we’re not restricted to media query values—we can use Sass to assign colors, font-stacks, and measurements of any kind to a variable. Any value that may be repeated throughout your CSS can be replaced by a variable.\n\nBut what if you find yourself repeating groups of CSS style rules?\n\nEnter Mixins:\n\n
Mixins: Getting More DRY with Sass
\n\nWe can think of mixins like a bucket of styles we want to re-use.\n\nLet’s say we have some font and border styling we’d like to apply throughout our CSS:\n\n\n\nSure, we can put that in a class selector and apply that class to HTML. The problem is that some elements can have competing rules that are attached to highly specific selectors, so they beat out our fancy stylings.\n\nHere’s what we can do instead:\n\n\n\nSo that’s nice; our menu items and our buttons can have standardized styling. But what we can also do is parameterize these mixins, so they work like a function:\n\n\n\nWe’ve added a $borderwidth parameter to our callout mixin and given it a default value of 1px.\n\nThis is great. Now we can have the same styling but configure it per selector; this combines excellent consistency of appearance with great flexibility.\n\nNow we’re getting somewhere. We’ve added some structure and taken advantage of variables and mixins to cut down on repetition.\n\nWhat’s next? Let’s see how to take advantage of predefined styles to easily make new ones.\n\n
Inheritance
\n\nInheritance is something normally associated with object-oriented programming (and not positively!), but in Sass CSS, it gives us an opportunity to leverage predefined styles to make new ones with very little effort.\n\nLet’s see how it works. Here’s the sum of our Sass so far:\n\n\n\nNow let’s say we want a new style that combines both our existing navigation styles and the element with the border.\n\nWe can use the extend keyword in a CSS selector to inherit styles from another selector. Let’s take a look:\n\n\n\nThat’s a pretty short definition, but let’s see what it gets us:\n\n
- \n
- The styles from #sidenav, including the li, a, and @media definitions.
- The border styles and font-stack defined in callout.
\n
\n
\n\nThat’s a lot of styling for such a little style definition.\n\n
How You Can Add SASS to Your npm Build
\n\nBut how do we use Sass in an everyday development setup? The best way is to incorporate your Sass into an npm build process.\n\nUsing npm to make CSS conversions automatic will let you see your style changes straight away in a browser and is necessary for automatically deploying changes to staging and production environments.\n\nPlease note: we’re going to be doing most of this from a command line. If you’re not sure how to do that on your computer, now is an excellent time to learn.\n\nIf you’re on Windows, the Command Prompt is an awesome and seriously old-school place to start.\n\nOn macOS and Linux, you’ll want to open a terminal (Terminal application on macOS). Zed Shaw has a great mini-course on how to use a terminal in macOS and Linux right here. (He covers Windows as well, but uses PowerShell instead of cmd.exe. I think cmd.exe is more friendly for beginners.)\n\n
How to Install Node and npm
\n\n
\n\nJoined at the hip, Node.js and npm come together in a package.\n\nIf you’ve been doing some web development already, there’s an excellent chance that you have node and npm installed already.\n\nTo check, open a command prompt (cmd.exe on Windows, Terminal on macOS) and type node -v.\n\nIf you have node installed, it’ll print out the version number. Great! Head straight on to the next section.\n\nIf you don’t have node installed, node -v will make your command prompt complain. Don’t worry, we’re going to fix that now.\n\nFor macOS and Windows, the easiest thing to do is head over to the Node downloads page, download an installer for your system, double-click the installer, and follow the instructions.\n\nIf you’re on Linux, it’ll probably be easier to use your system’s package manager (apt-get, yum etc). You can find instructions on doing this on Node’s package manager installation page.\n\nOnce you’ve done that, go back to your command prompt and type node -v and npm –v for good measure. This is what mine shows:\n\n\n\n
Set up a Test Project, and Install SASS for npm
\n\nNow that you’ve got node and npm installed, let’s set up a test directory to try out some Sass. Note that since I’m on a Mac, I’ll be using commands that apply to Mac and Linux.\n\nMake a new directory called sass-test, and change to that directory:\n\n\n\nNow that you’re in the sass-test directory, let’s initialize npm:\n\n\n\nThis command creates a package.json file, which is used by npm to keep track of what packages you’re using, and what it’s supposed to do with them. The -y flag tells npm not to bother you with lots of questions about the initialization.\n\nNow it’s time to install Sass for npm:\n\n\n\nFirst of all, this produces a lot of output. Don’t worry about that.\n\nThe main thing to note here is that we’re installing the version of Sass that node knows how to run. The —save-dev flag indicates that node-sass should not be included in a production release—it’s just used for development.\n\nNow we’ve got node, npm, and Sass installed. What do we do with them?\n\n
Run Your SASS Preprocessor with npm
\n\nLet’s get some Sass CSS to work with. We’ll use the example Sass CSS from earlier in the article.\n\nUnder your sass-test directory, create a new directory called app, and then a directory under that called scss.\n\nNote: scss is the extension we use for the Sass SCSS syntax. If we were using the SASS syntax, our extension would be .sass.\n\n\n\nSave the following under the app/scss directory as app.scss:\n\n\n\nNow, making sure you’re still in the scss-test directory, run the following:\n\n\n\nHere’s what that means:\n\n
- \n
- This is how we run Sass: node_modules/.bin/node-sass
- This is the file we want to process: app/scss/app.scss
- This is where we want our CSS output to go: dist/css/app.css
- Please format our CSS nicely: –output-style expanded
\n
\n
\n
\n
\n\nSo check out the dist/css/app.css file. You’ll see it has regular old CSS in it that implements our Sass CSS styles.\n\nBut the command we ran to get our CSS is long. Who wants to type that in? Not me, that’s for sure.\n\nTo make life easier, we’ll get npm to run it for us. Edit the package.json file in the sass-test directory. It should look something like this (don’t worry if it has minor differences):\n\n\n\nIn the scripts section, we’ll add a command to run our Sass. Update your file so that it appears as follows (changes highlighted):\n\n\n\n(Note the comma on the end of the first line under scripts.)\n\nOnce you’ve added that and saved package.json, you can now run your Sass build like this:\n\n\n\nThat’s way easier! But doing that every time you make a change to your style gets kind of boring.\n\nHow about doing it automatically?\n\n
Set up a Watch to Automatically Compile Your Sass CSS into CSS
\n\nSass has the awesome ability to automatically watch your Sass CSS files and process them whenever they change.\n\nLet’s add another command to package.json to do that (changes highlighted again):\n\n\n\nThe important changes here involve:\n\n
- \n
- Telling Sass to watch a directory for changes (not just a file): –w app/scss
- Telling Sass where to put CSS output: –o dist/css
\n
\n
\n\nEverything else is the same.\n\nNow, you can execute:\n\n\n\nAnd notice how you don’t get your command prompt back again. Sass is just sitting there, waiting for changes.\n\nAs an experiment, make a change to the app/scss/app.scss file, save it, and see those changes immediately reflected in the dist/css/app.css file!\n\nCool, huh?\n\n
Sass: Making CSS More Powerful and Less Complex
\n\nOk, we’ve covered a lot of ground here, but I hope you’re sold on the benefits of using CSS preprocessors, and Sass in particular.\n\nYou can make CSS more succinct and maintainable with Sass by using:\n\n
- \n
- Nesting to make the structure of CSS rules more apparent.
- Variables to make CSS more maintainable by trapping magic numbers in variables with useful names.
- Mixins to make CSS more succinct, maintainable and readable, and to capture style rules that appear together often.
- Inheritance to reuse existing styles with the @extend keyword to compose new styles based on existing ones.
\n
\n
\n
\n
\n\nRemember that backend dev we mentioned at the start, horrified by the unstructured sprawl of CSS? With Sass, they’ve gained structure, DRY code, and named abstractions. Now our dev will be much happier.