Theming Angular apps with CSS Custom Properties

Theming Angular apps has never been easier using CSS Custom Properties. CSS Custom Properties allow us to define our own custom variables for CSS values that we can share between components and style rules.

A common use case for using Sass or Less variables is to make it easy to change the value in one place and have it propagate to all CSS rules. CSS Custom Properties work the same way but also allow us to change the value at runtime. Updating CSS Custom Properties at runtime open up the opportunity to easily create themes for our Angular application.

In our use case, we will have two themes, first a default light theme and second and optional default theme.

In our Angular app, we have some default global styles as well as component level styles. This app will have two components, a header, and card component. Both of these components will use CSS variables (custom properties) to update their values dynamically. First, let’s take a look at the app component template.

In our component, we have a single FormControl. We subscribe to the value changes when the user selects the checkbox. We have a theme service that will be responsible for toggling between the different CSS themes. Before we jump into our theme service lets take a look at our global.css file.

CSS Custom Properties

In our global.css file we define the CSS Custom Properties we want to share application wide.

In our global.css file we have our CSS custom properties defined in a :root selector. The root selector at the global level will allow us to define the custom properties on the entire document globally. Global variables in CSS will enable us to define theme variables that multiple components can use. To define a CSS custom property, we must prefix the property key with two dashes like the following --primary-color: #fff;. We can now reference the variable we defined in other CSS rules.

To use a custom property, we use the var keyword to pass in a reference to the custom property. In our example above we can set the body background and text colors to our defined custom properties. Next, we will look at our app-card component and how it uses our CSS variables.

Component CSS

Our first Angular component, the card component is relatively simple using ng-content to allow use to pass HTML content into the inner template.

The first style on the app-card component uses the :host selector. The :host selector will style the host element of our component. The host element is the element that is created for the component, so in our use case that will be app-card. We have some basic styles such as display, padding, and border-radius. Our card now uses our CSS Custom Properties we defined with the :root selector.

background-color: var(--primary-color);
color: var(--text-color);

We can see to use our CSS Custom Properties we use the var syntax. Now whenever we change the value of one of these properties in our application the card will reflect those changes. Next, let’s take a look at the header component.

Similar to our app-card component we can see the header references our two properties, --primary-color and --text-color. Now that we see how our Angular components use the CSS Custom Properties how do we update them? Next, we will look at the Theme Service we used earlier to toggle between the light and dark themes.

Theme Service

Our theme service is an Angular service that we have created to abstract out the logic for toggling the CSS Custom Properties. First, how do we set a CSS Custom Property from JavaScript?