Stylesheet setup - SCSS
I was looking at my todo list and one of the outstanding items under the heading Longer Term was "Make custom css .scss".
I have absolutely no idea what that means. I almost certainly wrote it months ago, and at the time it probably made loads of sense. Given this, I have opted for investigating my usage of SCSS on Running.org more generally and blogging about it.
What is SCSS?
I know what SCSS is, but I never chose to use it. Rather, the initial theme for the project used it and so I stuck with it. I have never had a problem with just using plain old boring CSS.
I've historically had lots of fun with Bootstrap and Semantic UI and have not really had to think about CSS that much. With this project however I wanted to keep things lean.
SCSS is a stylesheet format designed with the intention of providing more power to the designer over standard CSS. That makes it sound like a whole new language. In fact it is a CSS preprocessor - that is to say that SCSS code is converted to CSS. It is just easier to write.
It allows you to write your styling code in the same manner that you think thus producing clear, concise, and readable code. It allows for simple separation of styling concerns, and allows for reuse of code.
Once written it is converted into CSS which is then interpreted by the browser. In my use case this conversion is done as part of the build process. I have a gulp task that watches my .scss files and automagically rebuilds my css when changes are made.
gulp.task('running-sass', function () {
return gulp.src('../public/assets/sass/running.scss')
.pipe(sass().on('error', sass.logError))
.pipe(rename('app.css'))
.pipe(gulp.dest('../public/build/css/running/'));
});
Alternatively you can just run the compiler from the command line.
sass input.scss output.css
And it turns out (I just Googled it) that the SASS compiler itself can watch files/directories. That link is also a great introductory guide to SASS some of which I will discuss below.
Interesting Features
Some interesting features that I have discovered whilst playing around include:
- Variables. You can define variables with preset values that you can use across your styling code. This allows you to change things by changing one line of code rather than in multiple. In practice it means you only have to make sure you don't make a mistake once.
- Mixins. Essentially allows you to reuse blocks of CSS. Allows you to keep your code DRY. Similar in nature (but different) to traits in languages like PHP.
- @import. Allows for the separation of styling concerns. You can have your styling code for different things in different files.
CSS Style Guides
Having clarified my understanding of the tools that I have inherited I wanted to investigate how the code was styled and clean up the custom CSS code that over time I have added.
My approach has always been:
- I need to style something.
- Inline style tags suck. In file
<style></style>
sucks. - Add some CSS to my
_.custom.scss
file (all standard CSS code is compatible with SCSS)
Looking at the inherited code I noticed a large number of classes with double underscores in the name. c-header__inner
for example. I was curious as to why.
Apparently CSS has numerous style guides (who would have thought), and the one used here is called BEM (Block, Element, Modifier). The double underscores indicate that inner
is the nested element of c-header
(the block).
Huh.. you learn something new every day.
Personally I like mega semantically clear class/ID names (even at the expense of file size) so I have always used ID names like #homepage-top-header-nested-div
. OK, thats a slight exaggeration.
Apparently there are lots of CSS style guides. 😳
Definition Separation
Would make a good name for a rock band.
In the theme SCSS codebase that I inherited things are separated to a ridiculous extent. There are nested SCSS files that contain individual classes, mixins, and sets of variable definitions. This level of separation is probably overkill, but it admittedly is very clear. In hindsight I should have taken the time to do this initially and placed my CSS additions in the appropriate places.
There are separate files for CSS setup - things like box-sizing
resets. I remember having issues with box-sizing
many many years ago but I feel as though nowadays themes, and frameworks always include these CSS resets for you. As a result, I had to Google why they are in fact needed - I had forgotten. Here is another great css-tricks read, and here is a succinct StackOverflow answer on why we need reset stylesheets anyway.
Other files include comments to explain why they exist. One file includes a link to this article on single direction margin declarations which I found extremely interesting. My approach to changing margins has always been what I call helper classes aptly named things like margin-top-10
and margin-bottom-30
. I see nothing wrong with this approach (and SCSS makes them easier to define) but I will certainly take on board the insight about single direction margin declarations.
In the process of doing this deepdive I found a number of files containing definitions which we now longer use. For example a file of @font-face definitions, none of which I use on the site anymore. Simply removing these files and cleaning things up a little bit reduced our unminified CSS file from 59kb to 39kb. These are not the kinds of numbers that in practice actually make much difference, but a 34% reduction in size is just a bonus on top of a day of CSS discovery.
Other things..
At this point I may as well note the other areas of the project that pertain to CSS.
- Having converted our SCSS to CSS we run our CSS code through a gulp task to minify its contents. We use gulp-clean-css which is a gulp wrapper around clean-css.
- Lots of aspects of our frontend are written using React. We use various third party libraries to avoid reinventing the wheel. Lots of these libraries have styling requirements. For example react-leaflet.
Previously I was just including these CSS files from a CDN but i stumbled upon browserify-css which is now a part of our build process. It allows you to simply import your required CSS within your javascript like so:
import 'leaflet/dist/leaflet.css';
Behind the scenes it creates javascript which loads the CSS file on the fly and embeds it in a set of <style>
tags created within the <head>
of your page. Its pretty clever stuff, which once I had gotten my head around integrating it with my build process has made working with CSS in such situations a lot simpler/cleaner.
Conclusion
Having written this post, I reread the initial todo item and remembered what it meant. It was directing me to clean up my custom CSS file and integrate it into the SCSS setup (and file structure) present. Thats what I ended up doing anyway. Success !