CSS in JavaScript with Angular

SCSS styling allowed us to write better stylesheets code

For many years the frontend css styling world saw new features added. Most were to fix the underlying issues with the browser layouts such as grid systems, web fonts and vector shapes. Most developers still didn’t have DRY (don’t repeat yourself) ways of coding stylesheets, resorting to copy/paste or abstracting classes, creating hierarchies and applying them to every DOM element. These approaches usually come at a cost of readability for developers who need to pick up the code and make changes.

Then along came compile-to-css frameworks such as SCSS, allowing new patterns such as variables, mixins and more. Gradually we will see these new functionality added to browsers out-of-the-box, so less compiling will be needed.

However, when writing single-page apps, most code is written and compiled down to production code anyway, allowing us more flexibility in source formats. We have seen TypeScript become the language of choice, compiling down JavaScript, and now another option for CSS, as JavaScript!

cssinjs is interesting!

For those who want to stick to browser standards, using cssnext to polyfill features until they arrive seems the most logical solution. But for those writing single-page apps who want ease and functionality over standards, cssinjs is an interesting approach to assess for projects.

Some immediate advantages I see to writing css as JavaScript:
* Write just one language (JavaScript or TypeScript)
* Allows auto-suggestions while you type
* Proper type-checking for properties
* Faster compiling and live-reload for single-page apps
* Easier testing by checking values from JavaScript.

There are quite a few CSS-in-JS projects out there, and currently no definitive winner, so I picked JSS which I was familiar with. I wanted to see how easy it was to use JSS in an Angular project (It was easy!).

First start a new Angular app using the ng-cli:

ng new angular-jss

Add the JSS library:

cd angular-jss
npm install jss jss-preset-default

In your angular.json remove any default stylesheets from styles:

"styles": []

In src/app/app.module.ts import the library and run the setup() function:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import jss from 'jss';
import preset from 'jss-preset-default';
jss.setup(preset());
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Create your styles file e.g. src/app/app.component.styles.ts. This will contain your variables, styles etc. In this example we are using different approaches in the same file to show off JSS functionality (variables, functions):

export const red: string = '#F44336'
export const green: string = '#4CAF50'
export const blue: string = '#2196F3'
export const styles: Object = {
title: {
textAlign: 'center',
backgroundColor: '#E0E0E0',
'&:hover': {
backgroundColor: '#BDBDBD'
}
},
area: {
width: '100%',
height: '10rem',
color: 'white',
backgroundColor: data => data.area.backgroundColor
}
}

You can now start using the JSS in src/app/app.component.ts. Here we import the styles and variables we want to use, and can dynamically switch them afterwards using JavaScript:

import { Component, OnInit } from '@angular/core';
import jss from 'jss';
import { styles, red, green, blue } from './app.component.styles';
interface sheet {
readonly classes: Object
readonly update: Function
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
public classes: Object
public ngOnInit(): void {
const sheet: sheet = jss.createStyleSheet(styles, { link: true }).attach()
this.classes = sheet.classes
sheet.update({
area: { backgroundColor: red }
})
}
}

Finally our app.component.html maps the classes to the DOM elements. As you see here, you reference the variable name, instead of classnames. I find this clearer and it’s easy for error checking than using a string:

<h1 [class]="classes.title">Angular JSS example</h1>
<input [class]="classes.area" type="textarea">

When run in the browser the styles are compiled to css, with auto-generated classnames, and injected into the page!

JSS compiled to CSS

You can view a full working example here:
https://kmturley.github.io/angular-jss

And grab the full source code here:
https://github.com/kmturley/angular-jss