In this post, we are going to learn the most commonly used options that we have available for styling our Angular components using the ngClass and ngStyle core directives.

This is the first post of a two-part series in Angular Component Styling, if you are looking to learn about Angular style isolation and the Emulated View Encapsulation mode (which Angular uses by default), have a look at part two:

Angular :host, :host-context, ::ng-deep - The Complete Guide.

This post will cover the following topics:

  • Component Styling using ngClass - when to use it and when to use other alternatives?
  • ngClass support for Arrays, strings of classes, configuration objects
  • ngClass support for component functions
  • ngStyle features
  • Summary

In order to cover each feature, we will be adding the multiple examples to this small Angular CLI sample application, that will use as external styles a Bootstrap default theme.

So without further ado, let's get started with ngClass and all the multiple ways that we have for using it!

Component Styling using ngClass - when to use it?

Most of the styles that we need to apply are always present, and can be simply be applied as standard HTML in our templates, like this:

But there are often styles that are applied conditionally to our templates - they are added to an element only if a certain programmatic condition is met.

This is, for example, the case of state styles (if we adopt the SMACSS terminology).

For these cases, is ngClass needed?

Note that many state styles can be natively implemented using browser CSS pseudo-classes, such as for example:

  • styles for identifying an element with the focus, via the :focus pseudo class
  • hover styles and on-click active state styles (using :hover and :active)

For these type of state styles natively supported by the browser, it's better to use the CSS pseudo classes whenever possible. So for these very common cases we won't need ngClass.

Some good examples for the use of ngClass

But there are many other state styles that are not natively supported by the browser. These styles could for example include:

  • styles for identifying the currently selected elements of a list
  • styles for identifying the currently active menu entry in a navigation menu
  • styles to identify a certain feature of a element; for example to identify a new element in an e-commerce site

If the element that we are styling only has one of those state styles, we can even apply it simply by using the plain input property template syntax, without any extra directive:

Notice the syntax [class.btn-primary] that is activating the btn-primary CSS class, effectively adding it to the button.

This expression will add or not the class to the element depending on the truthiness of the expression, which in this case is always true.

But more often than not, an element ends up having multiple state styles, and that is when the ngClass directive comes in handy!

The ngClass directive will take an expression that will be used to determine which state styles to apply at a given time to the styled element.

The expression passed on to ngClass can be:

  • an object
  • an array
  • a string

Let's go over each one of these 3 cases with examples, and then see how we can make sure that we can still keep our templates light and readable.

Passing an Array of CSS classes to ngClass

One way of defining what classes should be active at a given moment is to pass an array of strings to the ngClass directive.

For example, the following expression contains an array of classes:

Angular will then take the array passed to ngClass, and apply the CSS classes that it contains to the HTML button element. This is the resulting HTML:

Notice that the CSS classes don't have to be hard-coded in the template using this syntax (its just an example), more on this later.

Passing a String of CSS classes to ngClass

Its also possible to pass to ngClass a string, that contains all the CSS classes that we want to apply to a given element:

This syntax would give the same results as before, meaning that the two CSS classes btn and btn-primary would still be applied.

Passing a configuration object to ngClass

The last and most commonly used way that we can configure ngClass is by passing it an object:

  • the keys of that object are the names of the CSS classes that we want to apply (or not)
  • and the values of the configuration object should be booleans (or an expression that evaluates to a boolean) that indicate if the CSS class should be applied

Let's have a look at an example of how to use this syntax:

This example would give the same results as before: the two CSS classes would still get applied.

But if for example start using longer expressions to calculate our boolean values, or have several state classes, this syntax could quickly become hard to read, overloading the template and putting too much logic in it.

Let's then see what we can if we run into that case!

Delegating to the component which styles should be applied

One of the roles of the component class is to:

  • coordinate the link between the View definition (the template), and the data passed to the component (the Model)
  • as well as to keep track of any other type of visual component state that is tied uniquely to the component and is transient in nature (like a flag saying if a collapsible panel is open or not)

If our ngClass expressions start to get too cumbersome and hard to read, what we can do is pass to ngClass the output of a component method:

Notice that we could pass parameters to this method if needed. Let's then break down what is going on in this example:

  • The component now has a member variable stateFlag, which will identify if a given component state is active or not.
  • This could also have been an enum, or a calculation derived from the input data
  • The method calculateClasses will now return a configuration object equivalent to the one we just saw above
  • the CSS class btn-extra-class will be added or not to the HTML button depending on the value of the stateFlag variable

But this time around the calculation of the configuration object is done in a component method, and the template becomes a bit more readable.

This function could have also returned an array or string containing multiple CSS classes, and the example would still work!

As we can see, between the native browser functionality and ngClass, we will be able to do most of the styling for our components.

But are there use cases where we would like to apply styles directly to an element?

How to use ngStyle to add embedded styles to our templates

Just like in the case of plain CSS, sometimes there are valid use cases for applying directly styles to an HTML element, although in general this is to be avoided.

This is because this type of embedded styles takes precedence over any CSS styles except styles that are marked with !important.

To give an example of when we would like to use this: Imagine a color picker element, that sets the color of a sample rectangle based on a handle that gets dragged by the user.

The varying color of the element needs an embedded HTML style, as its not known upfront. If we run into such an use case using Angular, we can implement it using the ngStyle built-in core directive:

And this would be the resulting HTML:

Just like the case of ngClass, if our ngStyle expression starts to get too large, we can always call a component method to calculate the configuration object:

And with this, we can now add both CSS classes and embedded styles conditionally to our components!

But another key feature of Angular that we have not covered yet, is the ability to isolate a component style so that it does not interfere with other elements on the page, and that is what we will be covering on part two of this series:

Angular :host, :host-context, ::ng-deep - The Complete Guide.

Summary

There are a ton of options to style our components using ngClass and ngStyle, so it's important to know which one to use when and why. Here is a short summary:

  • most styles can be added simply to the HTML directly, for those we can simply add them to the class property, and no special Angular functionality is needed
  • Many state styles can be used using browser-supported pseudo-class selectors such as :focus, we should prefer those conventional solutions for those cases
  • for state styles that don't have a pseudo-class selector linked to it, its best to go with ngClass
  • if the ngClass expressions get too big, it's a good idea to move the calculation of the styles to the component class
  • only for situations where we have a dynamically calculated embedded style should we use ngStyle, this should be rarely needed

I hope that this post helps in choosing how to style your components if you have some questions please let me know in the comments below and I will get back to you.

To get notified when more posts like this come out, I invite you to subscribe to our newsletter:

And if you would like to know about more Angular Core features, we recommend checking the Angular Core Deep Dive course, where component styling is covered in much more detail.

If you are just getting started learning Angular, have a look at the Angular for Beginners Course:

Have also a look also at other popular posts that you might find interesting: