Using ngStyle in Angular for dynamic styling blog post

Using ngStyle in Angular for dynamic styling

Ashnita Bali

9 Jul, 2019

Angular

10 minutes read

Styling is a lot of fun. We mostly define CSS classes to make styles reusable and consistent. However, we need to style an element inline sometimes. Additionally, we need to dynamically change inline styles based on the application state.

In this article, we will look at how to style elements inline using the style attribute. Even more excitingly, we will explore how to dynamically change inline styles in Angular using two very stylish tools: binding to the style property, and ngStyle directive. Cool bananas!

You can also check out our other post on using ngClass!

Inline styling using the style attribute

The style attribute is a global attribute that is available to all HTML elements. It lets us provide style information for individual elements, in other words, it lets us style an element inline.

Syntax:

<p style="background-color: mediumpurple; color: wheat; padding: 1em">
  Styled inline.
</p>

The string assigned to the style attribute contains a CSS style declaration block. A declaration block can have one or more declarations. Each declaration is a CSS property and value pair.

CSS style declaration:

selector {
  css-property: value;
  css-property: value;
}

However, when styling inline we do not need to put curly braces to create a block. Also, we would replace ‘css-property’ above with actual CSS property names.

There are many, many CSS properties that we can use. Some common CSS properties are padding, margin and font.

Most importantly, inline styles override the styles in the component and global stylesheets.

Let us have a quick look at stylesheets in Angular.

Stylesheets in Angular

Angular has a modular design for defining styles. Each component has its own stylesheet which styles only that component. Additionally, there is a global stylesheet for styles that apply to the whole application.

Let’s see an example:

@Component({
  selector: 'app-root',
  styles: [`
    p {
      padding: 1em;
      background: black;
      color: snow;
  }
  `],
  template: `
    <p style="background-color:mediumpurple;color:wheat" #pRef>
      Styled inline!
    </p>
  `
})
export class AppComponent implements OnInit {
  @ViewChild('pRef') pRef: ElementRef;

  ngOnInit() {
    console.log(this.pRef);
  }
}

The inline style for the p element replaces the background-color and color styles from the element selector. Only the CSS properties that are overridden are replaced, therefore, the p still inherits the style for padding (and any cascading styles from the global stylesheets).

Attributes vs Properties

Before we look at how to dynamically style elements, it is important to highlight the connection between attributes and properties.

Without getting into too much detail, the gist is, attributes are used in the HTML document, at development time, to configure the HTML elements. However, the attributes only provide the initial values, for example, the initial background colour in our style attribute.

We often need to change these values while the application is running based on some interaction or some logic. For example, highlight products on sale by changing the background colour of the elements that display those products.

Dynamic changes are made with JS/TS code where the HTML elements are represented as objects and the attributes are represented as the properties of these objects. Therefore, to dynamically change the values we need to change the properties. For example, to change the style, we need to change the style property values.

If we inspect the p tag in our example code above, we would see that it has a property called style. The style property is an object as well and has all the CSS properties as its properties. Remember, CSS properties are things like, display, background-color, top and are dash-case. They are camelCased as properties on the style object.

Now, let us look at how to dynamically change inline styles in Angular.

Property binding with “style”

Property binding is the right fit when styling only one CSS property.

Syntax

<some-element [style.css-property.unit]="template expression"></some-element>

Example:

<p [style.background-color]="randomColor">
  Styled with property binding!
</p>

Firstly, the square brackets denote a property binding and contain the property that we want to set and update dynamically.

However, binding to the style property looks slightly different from other property bindings. This is because the style property is an object itself, with the CSS properties as its properties. Therefore, we also need to specify the actual CSS property to style.

You may find it surprising that we can use the dash-case for the CSS property since the JavaScript representation is camelCased. Angular lets us use either, but it is better to use the dash-case since it is consistent with the style attribute, as well as, it is what we’re used to in CSS declarations and also because Angular provides it to us.

<!-- Both works -->
<!-- Prefer dash-case -->
[style.background-color]

[style.backgroundColor]

The second part of the property binding is the template expression. The string assigned to the binding is a template expression which gets evaluated to a value.

In our case, it should evaluate to the CSS property value that we want to assign to the CSS property. For example, for background-color, the template expression could evaluate to the value #dda0dd.

Whenever the template expression evaluates to a different value from before, the change detection system will apply the new style to the view.

Example

It is time to see an example. Since we’re talking about styles, it is “fitting” to imagine a simple application that lets users browse for hair and if they like it they can get it. We want to help the user out by pointing out the hair that is trending and ones that are a good bargain.

OK, yes, this is based on Ariana Grande’s song:

“You like my hair? Gee, thanks, just bought it. I see it, I like it, I want it, I got it (Yeah)”!

It is a catchy song.

@Component({
  selector: 'hair-catalogue',
  template: `
    <hair-item *ngFor="let hair of catalogue" 
      [hair]="hair"
      [style.background-color]="hair.trending ? 'purple': 'turquoise'">
    </hair-item>
  `
})
export class HairCatalogueComponent {
  catalogue = [
    {
      description: 'Body Wave Long',
      trending: true,
      price: 65
    },
    {
      description: 'Curl Bob',
      trending: false,
      price: 40
    },
    {
      description: 'Body Wave Bang',
      trending: true,
      price: 30
    },
  ]
}

Template expression context

The context for template expressions is the component instance. Meaning, the template expression can access the properties and methods of the component class.

To illustrate this, let us implement the logic for figuring out the background colour in a method. We will highlight the hair items in three categories: trending, trending and a bargain price (shoppers would definitely do not want to miss these), and not trending but are a bargain (maybe it is still worth getting it).

  bargainPrice = 30;

  getBackgroundColor(hair) {
    let color = 'orange';
    if (hair.trending) {
      color = 'purple'
      if(hair.price <= bargainPrice) {
        color = 'turquoise';
      }
    } else if (hair.price <= bargainPrice) {
        color = 'gold';
      }
    return color;
  }

We can call the method in the template expression:

<hair-item *ngFor="let hair of catalogue" 
  [hair]="hair"
  [style.background-color]="getBackgroundColor(hair)">
</hair-item>

Now, let us see how Angular makes it easy for us to bind to CSS properties that need a unit extension.

Optional unit property

Some CSS style properties like font-size, margin, padding, width, height, and plenty others need a unit of measurement. The values for these properties are not complete without a unit or the style will not take effect.

<p [style.font-size]="isImportant ? '3em' : '1.5em'"></p>

Angular gives us a more stylish way to provide the unit. We can specify the unit in the property binding using the dot notation:

<p [style.font-size.px]="isImportant ? 48 : 16"></p>
<p [style.font-size.em]="isImportant ? 3 : 1"></p>
<p [style.font-size.rem]="isImportant ? 3 : 1"></p>
<p [style.font-size.%]="isImportant ? 300 : 100"></p>

Other units include vh and vw.

When we don’t want to use property binding for inline styling

There isn’t much value in using property binding to bind to a static string.

<p [style.background-color]="'tomato'"></p>

Use the style attribute if the value is not expected to change. Even better, we can put the styles in the stylesheet instead of inline.

<p style="background-color: tomato"></p>

Styling multiple CSS style properties inline

Property binding lets us bind to one property at a time making it suitable for styling a single property on an element.

If we want to style multiple CSS properties:

<p [style.font-size.em]="2"  
  [style.background-color]="'coral'"  
  [style.color]="'ivory'">
</p>

It is time to use the NgStyle directive!

Angular’s NgStyle Directive

Use NgStyle directive to dynamically style multiple CSS properties of an element.

Syntax:

<some-element [ngStyle]="template expression"></some-element>

ngStyle is applied as an attribute to an element. The square brackets around the directive indicate that the NgStyle directive has an input property also called ngStyle. It is a common pattern to define the directive and bind to its input property at the same time. This is how we can pass our style information to the ngStyle directive.

<!-- This is a neater -->
<p [ngStyle]="myStyles"></p>

<!-- Is the same as -->
<p ngStyle [ngStyle]="myStyles"></p>

To find out what value the input property expects, let us look at how Angular implements it:

@Input('ngStyle')  
set ngStyle(value: {[klass: string]: any}|null) { ... }

As we see ngStyle expects an object with key and value pairs. The keys are CSS property names and the values are expressions that evaluate to CSS property values.

Here are some of the ways we can pass in the styles as input:

  1. As an object literal
<p [ngStyle] = "{
  'font-size.em': getSize(),
  'background-color': 'rebeccapurple',
  'color': 'seashell'
}">
</p>
  1. Define a property in our component class for the styles
<p [ngStyle]="myStyles"></p>
  1. Call a method in our component class that returns an object with the styles
<p [ngStyle]="getStyles()"></p>

As a side note, and just for completion, we could optionally use camelCase for the keys, in which case we do not need to put them in strings:

let myStyles = {
  fontSize: '3em',
  backgroundColor: 'ivory',
  color: 'maroon'
}

However, to use the optional unit property, we have to provide the keys in strings:

let styles = {
  'fontSize.em': 3,
  'backgroundColor': 'mistyrose',
  'color': 'midnightblue'
}

It is important to be consistent.

So, there we have it. Use property binding to style one CSS property of an element and use the ngStyle directive to set multiple CSS properties. Both tools make it super easy to dynamically style elements.

To learn more techniques, best practices and real-world expert knowledge I’d highly recommend checking out my Angular courses – they will guide you through your journey to mastering Angular to the fullest!

About the author

Ashnita is a front-end web developer who loves Angular and JavaScript. She is interested in learning and community and organises meetups for GDG Reading, WTM Reading and study groups for freeCodeCamp Reading. In her spare times she likes to go on nature walks.

Love the post? Share it!

Lots of time and effort go into all our blogs, resources and demos,
we'd love it if you'd spare a moment to share them!

Explore our Angular courses

Get started today and join over 60,000 developers.