Taking SASS to the next level
Last week I started embarking on upgrading my CSS skills by learning SASS. The documentation is relatively extensive and straightforward, and the concepts are largely clear to me — theoretically at least.
But as with most things I’ve found so far with coding, nothing beats building something and seeing how certain principles, methodologies, languages, frameworks, libraries — or whatever — is applied in practice. I took that to intense proportions a couple of months back with vanilla JavaScript, building a new project every day for 30 days. You can read part one, part two, part three and part four of that experience to see what I mean.
Going forward, I want to get in deeper with both front end and back end development, so this involves learning more about a range of things for each (in this case, SASS for front end development purposes), seeing how it applies in practice, building real websites, making choices and modifications — and hopefully arriving at a stage where I can comfortably bring an idea from a concept to a full-functioning site using whatever new technology I have learnt.
I am now in the second phase of that process with SASS. I have learnt the idea of how it works, the syntax is readable and familiar, and I see patterns of common (and I hope — also good) practice. I found a course to build a project with advanced CSS and SASS, and have done so, making my own changes and modifications whilst learning an example of good design principles at the same time.
I have no connection to this course, and note I bought it whilst it was massively discounted, but if you are curious you can find it here.
The project is great in the sense that I am increasingly confident with CSS animations through practical use, such as the below:
@keyframes moveInFromBottom {
0% {
opacity: 0;
transform: translateY(10rem);
}100% {
opacity: 1;
transform: translate(0);
}
}
Or in more obviously SASS (or to be more accurate, SCSS, syntax):
.secondary-heading {
&--green {
font-size: 3.5rem;
text-transform: uppercase;
font-weight: 700;
display: inline-block;
background-clip: text;
-webkit-background-clip: text;
color: transparent;
letter-spacing: .2rem;
transition: all .2s;
background-image: -webkit-linear-gradient(left, $colour-primary-light, $colour-primary-dark);
background-image: -o-linear-gradient(left, $colour-primary-light, $colour-primary-dark);
background-image: linear-gradient(to left top, $colour-primary-light, $colour-primary-dark); &:hover {
transform: skewY(-6deg) skewX(5deg) scale(1.1);
text-shadow: .5rem 1rem 2rem rgba($colour-black, .2);
}
}
This example above also pulls in the use of variables (in this case for hex values for colours), which means colour schemes can be more easily be changed by amending the value in the variables file, rather than searching for each time it is used —a system prone to human error and oversight.
Stepping back a second — a variables file? Well, the SASS code is structured in a sass directory, with a CSS directory and style.css file as I’d been used to before, but with a major difference in that I leave the style.css file empty. I want my compiled, processed SASS to go in there (it’ll look like perfectly readable CSS, but won’t be what I wrote directly).
Adding a script to my package.json file a la below will make sure that my SASS code is compiled and generate that CSS file:
"scripts": {
"compile:sass": "node-sass sass/main.scss css/style.css -w"
}
For that to happen and actually do anything, I need some code in that SASS directory to begin with. In terms of design architecture, I am using the 7in1 pattern. This website goes into it in greater detail (along with a lot of other useful content), but essentially its about creating several SCSS files of partials and putting them into 7 different directories, as well as having one main.scss which imports all of these files.
My main.scss file looks something like this:
@import "abstracts/functions";
@import "abstracts/mixins";
@import "abstracts/variables";@import "base/animations";
@import "base/base";
@import "base/typography";
@import "base/utilities";@import "components/button";
@import "components/composition";
@import "components/theme-box";
@import "components/card";
@import "components/background-video";
@import "components/story";
@import "components/form";@import "layout/grid";
@import "layout/header";
@import "layout/footer";@import "pages/home";
The seven sub-directories within the sass directory are as follows:
- A ‘base’ subdirectory which includes: a ‘_animations.scss’ file with code like the @keyframes moveInFromBottom example above, a ‘_base.scss’ file with SCSS using the universal selector (i.e. to reset browser styles), and for the html and body tags, a ‘_typography.scss’ file for default font styles as well as custom headings and other key font styles, and an ‘_utilities.scss’ file for standard margins, alignments or other spacing to be quickly and easily reused on the page.
2. A ‘components’ subdirectory which includes custom components’ styles. This concept of reusable and separate components is already familiar to me from React, and so it made logical sense to have component files such as a ‘_button.scss’ file, a ‘_form.scss’ file, a ‘_card.scss’ file etc.
3. An ‘abstracts’ subdirectory which includes the aforementioned ‘_variables.scss’ file as well as files for custom mixins and functions. My variables file looks as below, but it would always be possible to add more:
// Colours$colour-primary: #52fde8;
$colour-primary-light: #a4fbed;
$colour-primary-dark: #00ffe2;
$colour-primary-extra-dark: #008080;$colour-secondary-light: #ffb900;
$colour-secondary-dark: #ff7730;$colour-tertiary-light: #bc4e9c;
$colour-tertiary-dark: #f80759;$colour-grey-light: #f7f7f7;
$colour-grey-light-2: #eee;
$colour-grey-dark: #777;
$colour-grey-dark-2: #999;
$colour-white: #fff;
$colour-black: #000;// Grid variables$grid-width: 130rem;
$vertical-margin: 8rem;
$horizontal-margin-large: 6rem;
$horizontal-margin: 1.2rem;// fonts$default-font-size: 1.6rem;// border radius$radius-large: 1rem;
$radius-medium: .5rem;
$radius-small: .4rem;
4. A ‘layout’ directory which includes a ‘_header.scss’ file, a ‘_footer.scss’ file, and specific layout styles such as a ‘_grid.scss’ file, and could also add nav bars or side bars etc.
5. A ‘pages’ directory, which in this case, is a ‘_home.scss’ file only, as this project just includes a home page broken into separate sections.
Two other directories can be added to complete the 7in1, but in this case I didn’t have specific use for them so they were omitted. These are a ‘venders’ directory for external libraries and frameworks (e.g. jQuery, normalize, Bootstrap, Bulma etc.) and a ‘themes’ directory — which is obviously only relevant if an application has different themes.
In addition to the 7in1, another convention I followed in practice was the BEM methodology (that is short for Block, Element, Modifier if you didn’t know already). This site provides a more in-depth explanation but broadly it’s a syntactical pattern which involves splitting your code into the aforementioned blocks, elements and modifiers.
Examples of blocks in my code included:
- Section tags with the classes ‘about-section’, ‘theme-section’, ‘stories-section’, ‘faves-section’ and ‘booking-section’ (all styled within the ‘pages/home.scss’ file)
- Header and footer tags with namesake classes of ‘header’ and ‘footer’ and saved in similarly named files within the layout directory respectively
- A single div with a ‘story’, ‘theme-box’, ‘background-video’ or ‘booking’ class, and divs and buttons with the classes ‘card’, ‘composition’ and ‘button’
- Main heading, secondary heading and tertiary headings (h1, h2 and h3 tags with each of their respective classes)
Within these blocks, there were typically specific elements I defined within the html file with the structure “.blockname__elementname”. Elements included, for example for the footer block (i.e. part of the footer section that don’t make sense independently):
- A div with the class ‘footer__navigation’ a div with the class ‘footer__logo-box’
- An image tag with the class ‘footer__logo’
- An unordered list tag with the class ‘footer__list’
- A list item with the class ‘footer__item’
- An anchor tag with the class ‘footer__link’.
They are nested and styled within the footer element with &__navigation, &__logo-box, &__logo, &__list, &__item and &__link.
Modifiers meanwhile, as the name perhaps indicates, are for changing a style (or a few) for a specific block or element. For example for the button component, I have different modifiers by colour:
&--white {
background-color: $colour-white;
color: $colour-primary-extra-dark;
&::after {
background-color: $colour-white;
}}&--green {
background-color: $colour-primary;
color: $colour-white;
&::after {
background-color: $colour-primary;
}}&--orange {
background-color: $colour-secondary-dark;
color: $colour-white;
&::after {
background-color: $colour-secondary-dark;
}}
For the card element for example, I have a card block, a side element, and modifiers for the styles for the front and back of the card. This can also adapt to fit psuedo-classes such :hover in this case:
.card {
perspective: 150rem;
-moz-perspective: 150rem;
position: relative;
height: 55rem;&__side {
height: 55rem;transition: all .8s ease;
position: absolute;top: 0;
left: 0;
width: 100%;
backface-visibility: hidden;
border-radius: $radius-large;
box-shadow: 0 1.5rem 4rem rgba($colour-black, .15); &--front {
background-color: $colour-white; } &--back {
background-image: linear-gradient(to right bottom, $colour- secondary-light, $colour-secondary-dark);
transform: rotateY(180deg); }
} &:hover &__side--front {
transform: rotateY(-180deg);
} &:hover &__side--back {
transform: rotateY(0);
}}
The practice of using the BEM methodology, the 7in1 pattern, SCSS syntax nesting modifiers within elements and elements within blocks, making use of variables to set colour schemes, standardise margins, font sizes and even border radius length for a real world example has all been extremely useful in embedding these concepts in my brain to an extent where they become second nature.
I definitely will be continuing to put into practice what I am learning about advanced CSS and SASS, and I am confident it will make me a better developer in the long run.