In my relatively short time as a software engineer, I've used many different approaches to writing stylesheets for web applications. My initial naive approach was writing a single CSS stylesheet per application, such as the styles.css file for my SaintsXCTF application that I wrote in college. Although this was a common practice in the early days of web development, lumping an entire website's styles into a single file has many downsides. First, a single stylesheet is difficult to read and gets very long. Second, it doesn't follow programming principles like DRY (Don't Repeat Yourself), abstraction, and encapsulation. Third, CSS lacks many programming language features which enable scalable and reusable code, such as functions, conditional statements, and variables.
June 29th, 2021
While writing this article I learned that CSS recently added variables into its specification1. Variable support is a great new addition (although, unsurprisingly, it is not supported by Internet Explorer). If CSS continues to improve, I may consider its use in certain future applications.
To help bring order to the chaos of CSS stylesheets, different CSS methodologies were introduced. These ensured that CSS code followed certain conventions, thus making it easier to read. One common CSS methodology is BEM, which sets naming conventions for HTML element classes, which are used in CSS code2. I never used these conventions since I believed there was a better alternative: Sass.
Sass is a CSS preprocessor that adds features such as mixins, conditionals, extensions, variables, and more on top of CSS. I've used Sass in both prototype code and production level code. In fact, Sass is the stylesheet language used for this website!
The Sass code for this website (which is written in React) is structured so that each React component has its own stylesheet file. Reusable Sass code is achieved with mixins; mixins are groups of styles that are “mixed in” with other styles. While Sass is nice to work with, it's not without its shortcomings.
For example, in a UI component called
Note with a Note.scss stylesheet, I defined a root level
.jarbek-note CSS selector and two child CSS selectors:
These Sass shortcomings are remedied in JSS, my new favorite stylesheet approach for React applications. Although JSS isn't perfect, it has many great qualities which are worth discussing.
I created an npm project which uses JSS to style some basic HTML elements. The code for this project, located on GitHub, consists of an index.html application entrypoint file, an index.js file which adds additional elements and styles them with JSS, and a server.js file which starts a server with Express to host the webpage.
The JSS application displays a running exercise log, similar to those shown on my SaintsXCTF website. When viewed in the browser, the UI looks like the following screenshot:
Next, I create all the JSS styles.
headerSection are classes that are attached to HTML elements. While most styles created with JSS are written with classes, you can also use CSS at-rules such as media queries (
@media) and keyframes (
@keyframes)5,6. JSS also allows you to nest CSS selectors within classes, enabling more fine-grained control. JSS has some great examples of these approaches on their website.
As I previously mentioned, JSS creates unique class names for its stylesheets. This means that those
As you can see,
page was replaced with
exerciseLog was replaced with
headerSection was replaced with
headerSection-0-0-1. This name mangling prevents naming conflicts when writing multiple classes with the same name in a different JSS style objects.
One thing you may have noticed in the JSS styles was a property called
This property allows you to define styles in the global namespace as you would in traditional CSS code. In other words, it bypasses JSS' unique class naming, instead applying styles to all HTML elements that match certain CSS selectors.
This code applies the styles in
robotoSlabMixin to both the
title classes. In another example, I create an array of hex color codes and a number corresponding to an index in the array. Both the array and index are used in the JSS style object to determine the background color of an element.
In my upcoming article on React JSS, I will show how reusability and dynamic styling can be used in a production application.
flex are built into the language itself. Finally, you need to remember to use camel case instead of dash case for styles. For example,
font-size in CSS and Sass is
fontSize in JSS. Once you get accustomed to JSS that last point isn't much of an issue.
Even with these downsides, JSS is a great library that I highly recommend for new frontend applications, especially those written in React. In my next article, I will discuss React JSS, a library that integrates JSS with React components. I will also showcase how it is used in my SaintsXCTF application. All the code from this article is located on GitHub.