The use of Sass on compiled themes is being deprecated, and stylesheets should migrate to native CSS features. For more information on this change and how to use Sass locally in your theme development workflow, please read our announcement blog post on deprecating Sass.
In part one of this series, I introduced you to Sass in Shopify themes, explained variables and nesting, and discussed the limitations of the online store editor with Sass.
This article will focus on some of the more creative parts of Sass development — the things that can make your stylesheets smarter. We’ll take a look at using some of the operators built into Sass, as well as using some native Sass functions. We’ll also look at creating Sass mixins and extends.
This is part two in a three part beginner’s guide to Sass with Shopify.
Check out part one of this series, a beginner’s guide to Sass and Shopify themes.
Arithmetic operators
Sass has standard arithmetic operators baked in. These can be super helpful when trying to do calculations in your stylesheets, and have to support older browsers (IE8/IE9 reliably or Opera Mini) that don’t play nicely with the CSS calc()
function. The calculations are done on compilation, and rendered as a specific value.
In Sass, we have access to the +
, -
, *
, /
, and %
math operators.
For example:
.page-wrapper {
width: 100%;
}
.site-content {
float: left;
width: 600px / 960px * 100%;
}
.site-sidebar {
float: right;
width: 300px / 960px * 100%;
}
Compiles to:
.page-wrapper {
width: 100%;
}
.site-content {
float: left;
width: 62.5%;
}
.site-sidebar {
float: right;
width: 31.25%;
}
When Sass gets compiled, the evaluation of the math we’ve done outputs to the final values in our stylesheet. This means that these values will work in browsers that don’t support the calc()
CSS function.
Note that when Sass interpolation #{}
is used near operators like /
, those operators are treated as plain CSS rather than math operators.
For example:
p {
$font-size: 100%;
$line-height: 1.5;
font: #{$font-size}/#{$line-height} Arial, Helvetica, sans-serif;
}
Compiles to:
p {
font: 100%/1.5 Arial, Helvetica, sans-serif;
}
Where #{$font-size}
and #{$line-height}
resolve to 100%/1.5
, instead of Sass trying to divide those two values by one another.
Mixins
Sometimes it can be tedious to write in CSS over and over. Mixins differ from functions in that a function’s main objective is to return a value, whereas a mixin enables the creation of a reusable chunk of CSS. Think of a @mixin
like an include or snippet.
To create a mixin use the @mixin
directive, and give it a name. Mixins can take multiple arguments in the form of variables, which are comma separated.
A simple example of this is to create a reusable button style. This mixin also includes a Sass function, which you can read more about in the next section of this article.
For example:
@mixin link($color-link) {
text-decoration: none;
color: $color-link;
}
Usage:
.link {
@include link(#2980b9)
}
Output:
.link {
text-decoration: none;
color: #2980b9;
}
In the example above, @mixin link()
is passed an argument of $color-link
. Then, the $color-link
argument is used throughout the mixin property values. To use the mixin you would use the @include
directive, followed by the mixin name, and pass it the appropriate argument. In the case of this mixin, it’s a color value.
Below is a mixin I use to visually hide an element when I build themes, but still allows for that element to be read aloud by screen readers. Using a mixin for this makes it clear that the element is visually hidden in the styling. As a mixin, it then can be used multiple times throughout your styles, all while keeping accessibility in mind.
For example:
@mixin visually-hidden() {
position: absolute !important;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
}
Usage:
.logo {
background-image: url(logo.png);
}
.logo span {
@include visually-hidden();
}
Output:
.logo {
background-image: url(logo.png);
}
.logo span {
position: absolute !important;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
}
You may also like: Developing Shopify Themes with Accessibility in Mind.
Functions
In Sass, you’ll hear about two types of functions, functions which you write yourself using the @function
directive, and functions which are shipped with Sass.
Creating custom Sass functions
There are some pretty useful functions that you can create yourself. A function you create yourself uses the @function
directive, followed by the name of the function. It must be declared first, and once declared, can be used later on in your stylesheet by calling on the name of your function.
The output of a function is a single value. This value can be any Sass data type, which includes: numbers, strings, colors, booleans, or lists. Functions can accept multiple arguments in the form of variables, which are comma separated.
I usually put custom Sass functions at the top of my stylesheet, just after variables, or in a separate file that’s imported after variables, but before all my other styles. We’ll talk more about file structure and workflow in part three of this series.
I often use an em()
function. The function converts px
values into em
values ✨ auto-magically ✨ for you, based on a set base font size.
For example:
$browser-context: 16; // default
@function em($pixels, $context: $browser-context) {
@return #{$pixels/$context}em
}
Usage:
h1 {
font-size: em(72);
}
Output:
h1 {
font-size: 4.5em;
}
This simple function converts to em
values for you, which makes things much simpler than calculating them for yourself. Using em values for all sizing is especially helpful. If a user increases or decreases the size of their text, and you’ve used em
sizing for layouts as well, things will automatically scale and flow appropriately.
Using native Sass functions
There are also a huge list of functions that ship with Sass, which come in handy when theming. These native Sass functions are super helpful when creating consistent variations for a specific color within your theme. For example, you might want to create a button, that uses your primary color as a background, but darkens that background when it’s hovered or active.
We’re going to use the Sass darken()
function in the example below, to darken the $color-primary
for our hover states.
The darken()
function takes two parameters, a color (which can be of any format), and an amount to decrease the lightness by, which is a percentage from 0%
- 100%
.
darken($color, $amount)
In this example, we set the $color-primary
as the background-color
of the button. Using the Sass function darken()
, we set the :hover
and :focus
state for the button to a darker background-color
based on the $color-primary
.
For example:
$color-primary: #2980b9;
$color-button-text: #ffffff;
.button {
color: $color-button-text;
background-color: $color-primary;
font-weight: bold;
padding: 1em 1.5em;
display: inline-block;
text-decoration:none;
border-radius: 3px;
&:hover,
&:focus {
background-color: darken($color-primary, 15%);
}
}
Compiles to:
.button {
background-color: #2980b9;
color: #ffffff;
font-weight: bold;
padding: 1em 1.5em;
display: inline-block;
text-decoration:none;
border-radius: 3px;
}
.button:hover,
.button:focus {
background-color: #1b557a;
}
There are a ton of other built-in Sass functions that you can access. You can check them out in the official Sass documentation, and try experimenting with different ones! Follow this tutorial to create dynamic color schemes using Sass functions and theme options.
You may also like: An Introduction to Theme Options.
Extend
The @extend
directive lets you share a set of CSS properties from one selector to another. This can be incredibly useful if you don’t have access to update or change markup, but need to style an element. Note that when one uses the @extend
selector, it extends all nested selectors as well.
For example:
.box {
background-color: #f5f5f5;
h2 {
color: red;
}
}
.block {
@extend .box;
}
Compiles to:
.box, .block {
background-color: #f5f5f5;
}
.box h2, .block h2 {
color: red;
}
Notice that Sass doesn't "go get" the styles from .box
, inserting them below into .block
, then duplicating the styles. Instead, when Sass compiles it, the comma separates both selectors, applying the styles more efficiently.
Be careful not to abuse @extend
. When you want to use @extend
ask yourself if creating another class and adding it to your Liquid template might be more appropriate. There are some other gotchas that arise when you use @extend
that you should be aware of, these include lengthy output, and selector order issues.
You’re on your way to making your theme smarter!
By using Sass operators, mixins, and functions, you can begin thinking about how you can make your styles more efficient. Already, you can start to see how much less typing you’ll have to do when styling.
Stay tuned for part three of this beginner’s guide to Sass with Shopify!
Read more
- Introducing Online Store 2.0: What it Means For Developers
- An Overview of Liquid: Shopify's Templating Language
- Deprecating Sass for Shopify Themes
- How to Use Product Media on Your Custom Shopify Themes
- How to Display Price Ranges on Shopify Collection Pages
- How the Routes and Page_Image Liquid Objects Can Help You Build More Robust Themes
- How to Get the Most out of the Timber Theme Framework
- How to Test your Theme Before Submitting to the Shopify Theme Store
- How to Personalize Shopify Themes with the customer Object
- How to Work With Shopify Theme Blocks
Do you know any helpful mixins or functions for Shopify Themes? Tell us about your favorite ones, and why you love using Sass in the comments below!