A story about overriding SASS variables and the ‘!default’ keyword
Recently I stumbled upon a problem that took me much more time to solve than I expected. This story is mostly dedicated for the future me, but maybe it’ll be useful for somebody else as well :D
TLDR version
If you want to override a SASS variable defined with !default
keyword located in file a.scss
in a file named b.scss
and then override the one from b.scss
in c.scss
your files should look like this:
// a.scss
$variable: red !default;// b.scss
$variable: green !default;
@import 'a';// c.scss
$variable: blue;
@import 'b';
Long version
Introduction
Let’s start with a few words of introduction — in Leadfeeder we’re sending a variety of emails which initially had been developed using the plain old HTML tables method and, as you probably can guess, weren’t very visually appealing. We decided to pimp up the emails a little bit and start developing our templates using Foundation for Emails. The nice thing about this framework is that Zurb provides a Ruby gem packaged with SASS files that make your templates good looking and responsive out-of-the-box.
We of course needed to give the emails a bit of soul, by changing things like text color which fortunately was pretty easy, because the foundation gem exposes a set of global variables you can override to customize the templates to your needs.
A sample variable definition in the gem looks like this:
/// Primary color for interactive components like links and buttons.
/// @type Color
$primary-color: #2199e8 !default;
Notice that the variable definition includes !default
keyword which, citing this page, means that:
If the variable already has an assignment, it will not be re-assigned
So in order to override the default variables I just needed to create a file called_global-overrides.scss
, redefine the variables there and in my main SASS file import this file before the foundation-emails.scss
file, like this:
@import
'global-overrides',
'foundation-emails'
The thing worked like a charm.
The problem
Later, over the time we developed a base stylesheet for all the emails and called it mailer-common.scss
which looked somewhat like this:
// mailer-common.scss@import
'global-overrides',
'foundation-emails',
'layout',
'header',
'typography';
Now every email stylesheet would have its own file that included the mailer-common
file at the top and selectors specific for given email afterwards, like this:
// weekly-email.scss@import 'mailer-common';.ems-stats {
&__mailchimp-logo {
max-width: 100px;
}
}
The problem appeared when we started converting more emails to the Foundation framework — in one of them we needed to change the value of global-gutter
variable. The variable was already overridden in global-overrides.scss
, so I thought that all I had to do was to redefine it again on the top of the specific email file, like this:
// custom-feed-email.scss$global-gutter: 20px;@import 'mailer-common';
Unfortunately this didn’t change the gutter as I expected - the value was still at 40px defined in global-overrides
.
The solution
The behavior described in the previous part got me a bit confused and wasted a lot of my time, but finally after a few hours of trials and errors I got to the point of understanding that what I needed to do is to override foundation variables in global-overrides.scss
with additional !default
keyword — it still feels pretty weird for me, but that’s how the thing works :D
So the final file structure looked like this:
// _globals.scsc in foundation-emails gem
$global-gutter: 16px !default;// _global-overrides.scss
$global-gutter: 40px !default;// _mailer-common.scss
@import
'global-overrides',
'foundation-emails',
'layout',
'header',
'typography';// custom-feed-email.scss
$global-gutter: 20px;@import 'mailer-common';
Now the gutter in custom feed email had a correct value of 20px and they lived happily ever after.