Working with Sass Stylesheets in ASP.NET MVC Applications and Visual Studio
For the last couple of years, I used Less to pre-process my stylesheets, but recently made the switch to Sass, which is even more powerful than Less. Here's how I organize and compile my Sass stylesheets in ASP.NET MVC applications with Visual Studio.
#Approaches to Pre-Process CSS Files
When you're using a CSS pre-processor to write your stylesheets, you need to compile those files at some point of time. After all, browsers only understand plain CSS and know nothing about Less or Sass. There are three conceptually different approaches for compiling a stylesheet with a CSS pre-processor:
- Dynamically compile the stylesheet on the server when the file is requested.
- Deliver raw stylesheets to the browser and compile those using JavaScript.
- Compile the stylesheets to static CSS files right after updating and saving them.
I've chosen option #3 for my Sass stylesheets because this approach works nicely with bundling and minification and doesn't require any JavaScript execution in the browser.
#Compiling Sass Stylesheets
While Visual Studio 2013 ships with an editor that provides syntax-highlighting, IntelliSense, formatting, outlining, and more, it doesn't include a Sass compiler. This means that you can create new *.scss
files and edit them with nice tooling support, but Visual Studio won't generate the compiled CSS files for you.
There's a great Visual Studio extension, though, the Mindscape Web Workbench, which does exactly that (and a lot more). It splits your Sass editor into two panes and directly shows you the resulting CSS on the right-hand side:
When you save a *.scss
file, the Web Workbench will automatically compile it and create a CSS file for you that's nested underneath the Sass file:
Let's now take a look at how to organize our stylesheets.
#Organizing Sass Stylesheets
When you have even a medium amount of Sass rules, you want to split them up into separate files. Each of those should only contain styles for one particular piece of functionality. Thanks to the @import
directive that comes with Sass, it's almost trivial to import rules from other referenced stylesheets:
Note that the imported _Mixins.scss
stylesheet has a leading underscore in the file name. That causes the the Web Workbench (and the Sass compiler in general) not to generate a standalone Mixins.css
file. This is desired behavior as _Mixins.scss
only contains a collection of mixins which are inlined into the Sass rules that include them.
I usually create the above mixins file and a _Settings.scss
which defines variables for accent colors, font families, etc. that are used in various places of my stylesheets. If the website uses custom web fonts, those are defined in a _Fonts.scss
file. Here's how a simplified Styles
folder could look like:
#Setting Up Bundling and Minification
Because we want to create web applications with great performance, our stylesheets should be bundled and minified in order to minimize HTTP requests and bytes sent over the wire. Using the @import
approach described above, the bundling part is a piece of cake: Just create one main Sass file and import all required stylesheets. I like to name it Bundled.scss
:
It's very convenient that the Web Workbench understands Sass dependencies, which means that the Bundled.scss
file is recompiled automatically whenever one of its imported stylesheets changes. There's no need to invoke the compilation manually, so you can simply make a change to one of the dependent stylesheets, save it, and be done.
The Bundled.scss
file is the only stylesheet whose name doesn't start with an underscore, so the Sass compiler will create a CSS file for it. That resulting CSS file with all the required rules can then easily be used in conjunction with a style bundle from the System.Web.Optimization
bundling and minification framework:
var styleBundle = new StyleBundle("~/Client/Styles/Bundled")
.Include("~/Client/Styles/Bundled.css");
BundleTable.Bundles.Add(styleBundle);
Finally, the bundle needs to be rendered in the Razor layout view:
<head>
<!-- ... -->
@Styles.Render("~/Client/Styles/Bundled")
</head>
When running in debug mode, the stylesheet will be rendered without being minified, which facilitates diving into the CSS rules when debugging. In production, however, minification CSS is desired and will be performed.
And there you go! That's how I work with Sass in my ASP.NET MVC applications.