Written by Joe Casabona✏️
In recent years, CSS has transformed from writing simple rulesets to a powerful engine for creating beautiful user experiences. But as projects grow more complicated, as does the CSS that is being written, it gets harder to manage and even harder to make changes. Native CSS has implemented some new tools to help with this, like Grid and variables, but CSS preprocessors take writing and managing CSS to the next level.
Aside from writing flexible, reusable rulesets, CSS preprocessors like Sass bring powerful program logic to CSS. That’s right – using Sass, you can perform arithmetic operations, write functions (@mixins
), and even use control structures like if/else statements and loops. In this article, we’ll take a look at all the ways you can write programmable logic in CSS. The syntax being used is SCSS.
TIP: If you’ve never used SCSS before, I recommend checking out this guide to get started. But fret not! If you just want to see what SCSS has to offer as far a program logic goes, you can do so in CodePen.io
Low hanging fruit: arithmetic operators
The easiest way to get started with programming in SCSS is by doing math. There are five arithmetic operations you can perform:
- Addition with
+
- Subtraction with
-
- Multiplication with
*
- Division with
/
- Get the remainder with
%
This allows you to use math in your font sizing, or even create nice gradients in styles. Here’s an example:
$scale: 1.5;
$heading-base: 65px;
h1 {
font-size: $heading-base;
}
h2 {
font-size: $heading-base / $scale;
}
Thanks to a simple divisor, your heading font sizes are now scaled, relative to each other. And later, you’ll see how to make that even better.
One thing to note if you can only use these operators on similar units. So you can’t multiply px
and em
for example. You can use operators on hex colors though to make some interesting colors! As a general rule, I try to use only numbers, without units, for math in SCSS when I can.
But using math in CSS is only the start. Let’s take a look at even more powerful programming features of SCSS.
@mixins: The functions of SCSS
Repeatable code is an important aspect of any programming language, and SCSS is no different. Using @mixin
, you can create a set of code that’s reusable. Here’s a simple example:
@mixin button() {
background: #880000;
color: #FFFFFF;
border-radius: 10px;
padding: 15px;
text-align: center;
}
a.button {
@include button;
}
In this mixin, we have a set of common rules for all buttons. Then, as we declare something that should have those rules, we can use the @include
directive to import that ruleset. But it gets better. You can pass variables to mixins as well. Let’s say, for example, you want to control the color of the button:
@mixin button($color) {
background: $color;
color: #FFFFFF;
border-radius: 10px;
padding: 15px;
text-align: center;
}
a.button {
@include button(#008800);
}
Finally, if you want a default changeable color, you can set an optional variable:
@mixin button($color: #880000) {...}
Then if you send a color, that’s used. And if not, the default, #880000
is used.
You can imagine this is pretty powerful for having, controlling, and modifying a set of common styles. If the general style for all buttons ever changes, you’d only need to change it in the @mixin
.
With the ability to generalize code and make it repeatable, there’s another thing you might want to add to your toolset: decision making.
Controlling flow: using if statements for your CSS
Some would argue that programming is pretty much making specific decisions based on some condition. And while I’ll save the philosophical discussion for a different article, it is true that decision making unlocks a lot of power in code to control the flow of a program.
In SCSS, this is less about reacting to real-time interactions (that’s what media queries are for), and more about being able to consolidate and better manage large blocks of rulesets. Let’s look at an example:
@mixin shape($w, $h, $circle: false) {
width: $w;
height: $h;
background: #FF0000;
@if $circle {
border-radius: 50%;
}
}
.square {
@include shape(100px, 100px);
}
.circle {
@include shape(100px, 100px, true);
}
In this mixin, we create a general shape (well, really a square) but thanks to the @if
, we can use the same mixin to create a circle as well. In a more practical example, and one that uses @else
to, you might have a mixin to manage the base styles for a “dark mode”:
@mixin theme-styles($dark-mode: false) {
@if $dark-mode {
//Set styles based on dark mode variables
} @else {
//Set styles based on light mode variables
}
}
So math lets us make better calculations for our measurements, mixins let us generalize rulesets to make them easier to manage from a high level, and if/else statements let us take that management one step further by conditionally adding rulesets and properties as needed.
But perhaps the biggest time saver in SCSS program logic is loops.
Repetition: create beautiful styles with loops
Loops let you repeat a task as long as some condition is true. There are three types of loops in SCSS:
@for
@while
@each
For loops
The @for
loop is a simple counting loop. You can perform a task a specific amount of times. A great example of this is easily creating those scaled heading sizes we looked at earlier:
$heading-size: 65px;
@for $i from 1 through 6 {
h#{$i} {
font-size: $base-size;
}
$heading-size: $heading-size / 1.25;
}
Here, we have a variable we’ve defined as $i
(commonly used in loops; you can think of it as “index” or “interator”), which starts at 1 and increments up to 6. Then we have a little bit of clever syntax in SCSS that lets us use variable names in selectors. First, we use the hash sign (#
) to indicate we’re starting a variable name, then we wrap the variable in curly braces ({ }
).
So here we’re using $i
to define each of the 6 heading tags. Then we’re setting a font size based on the $heading-size
variable. At the end of the loop, we divide that variable by 1.25, making it smaller, then doing the same thing for the next heading tag. So the rendered CSS looks like this:
h1 { font-size: 65px; }
h2 { font-size: 52px; }
h3 { font-size: 41.6px; }
h4 { font-size: 33.28px; }
h5 { font-size: 26.624px; }
h6 { font-size: 21.2992px; }
Nice, mathematically scaled heading sizes!
While loops
@while
loops are similar, but we’re not relegated to a single incrementor. We can do something like create a scaled gradient, based on some multiplier:
$gradient: 1;
$i: 1;
@while $gradient >= 0.1 {
main p:nth-child(#{$i}) {
background: rgba(0,0,240, $gradient);
min-height: 20px;
margin: 0;
}
$gradient: $gradient - 0.1;
$i: $i + 1;
}
In this example, we’re targeting <p>
inside a <main>
element, and stepping down a blue gradient for each child. We have 2 counters here: the $gradient
, which controls the opacity, and $i
, which is counting for nth-child
.
This can also be used to create a set of gradient classes, or create a nice visual effect for long content.
Each loops
Perhaps the most interesting loop in SCSS is the @each
loop. This let’s you step through variable lists(SCSS’s version of arrays). You can do some pretty nifty stuff with the right combination of info. Let’s say you want a series of alerts. You can loop through an array of colors like this:
$alerts: red, blue, green, yellow;
@each $alert in $alerts {
.alert-#{$alert} {
background: $alert;
color: #FFFFFF;
padding: 10px;
text-align: center;
}
}
This says, for each entry in the $alerts
list, create a class with the entry’s name and set the entry as the background color.
You can take this one step further with maps – key → value pairs in lists. If you wanted more descriptive names, you could do this:
$alerts: ("error" : red,
"neutral" : blue,
"good" : green,
"warning" : yellow
);
@each $name, $color in $alerts {
.alert-#{$name} {
background: $color;
color: #FFFFFF;
padding: 10px;
text-align: center;
}
}
This is an effective away to quickly work through large sets of repetitive CSS. You can imagine a custom icon font you want to use, where you have a map of the icon name, and the unicode value for the glyph.
Go forth and program CSS!
With that, you’re ready to start coding your own SCSS. You now have the syntax you need to do math, if statements, and loops for your styles. What are you going to use this new-found power for? Let us know in the comments!
Is your frontend hogging your users' CPU?
As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
LogRocket is like a DVR for web apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Modernize how you debug web apps — Start monitoring for free.
The post A beginner’s guide to programming for CSS with Sass appeared first on LogRocket Blog.
Top comments (2)
Absolute first class advice and post, over the time I have been using Sass I have come to appreciate just how well thought out and useful it is.
Anyone working with CSS should at least try one of the pre-processor languages to see if it can help reduce their maintenance load on both new and existing sites.
Thank you
The most clear and consise explanation in the internet. Thanks, man!