Angular: What is ngStyle?

Angular: What is ngStyle?

Give me some style, please!

Nowadays, all documents containing HTML elements have a stylesheet (I’m lying, of course, there are some with no HTML at all: see what happens when you don’t have a stylesheet). Regardless of technology, you always have to style elements on your website! (Here I go, lying again!) 

There are many ways to do it. Some of them are more elegant, some of them are more recommended, and there are actually good reasons for the variety. Who would want to maintain one big CSS file with all styles for an app? (Obviously, it would work great as recommended solutions for the final user, but c’mon, think about developers!) 

Angular 2 has a component–based structure so you can put your CSS style into a file associated only with a component (if you’re fancy, you may use compilers as an alternative to CSS like SCSS or LESS. It doesn’t matter here.) Traditionally, you can also hardcode them on the HTML elements (a very bad idea!) or pass them dynamically to the elements using Angular property binding of the style attribute. 

Or you can use something more enjoyable — ngStyle.

ngStyle in action!

Before I explain how it should be used properly, I would like to tell you that what you’re going to do might be wrong and you should definitely check the next section to see why and maybe rethink if you really need to use it. 

Are you still here? Ok, but remember I warned you.  

Using the ngStyle directive is pretty straightforward. First of all, it’s included in CommonModule from @angular/common so don’t forget to import it to your module! It is a directive so it can be applied to any element in the Angular DOM. It takes one argument with JSON containing key-value pairs of CSS properties. The keys are the style properties, and the values are the style values. The directive simply applies the given style property with the calculated value. 

That’s the theory. Let’s look at the example.

<div [ngStyle]="{'background-color':'red'}"></<div> 

It would change the background color to red. Easy, right? But you can achieve the same by simply using: 

<div [style.backgroundColor]="’red’"></<div>

So it doesn’t make sense to change just one CSS property with ngStyle. Use style attribute binding instead! But when you’d like to change multiple CSS styles?

<div [style.backgroundColor]="'red'"
    [style.cursor]="'pointer'"
    [style.padding.px]="'10'"
    [style.fontFamily]="myFontValueVariable"
    [style.display]=" isDataLoaded ? 'block' : 'none'"
></<div>

It doesn’t look so great. Let’s see the same example implemented with ngStyle:

<div [ngStyle]="{'background-color': 'red',
    'cursor': 'pointer',
    'padding.px': '10',
    'font-family': myFontValueVariable,
    'display': isDataLoaded ? 'block' : 'none'}"
></<div>

It’s better, but when you construct the JSON in the component and pass just the reference to the template, it’s the most optimal solution.

Somewhere in the component class:

public styleJson: Object = {
    'background-color': 'red',
    'cursor': 'pointer',
    'padding.px': '10',
    'font-family': myFontValueVariable,
    'display': isDataLoaded ? 'block' : 'none'
}; 

Template:

<div [ngStyle]="divStyle”></<div>

There are three important things to notice. 

First of all, you don’t use units (px, %, em, vw, vh) directly, instead you put them after the dot at the end of CSS property, e.g. padding.px. It’s the same as for style binding. It’s comfortable, but there’s no easy way to switch between different units for the CSS property inside one ngStyle

Secondly, changes in the style based on certain conditions will be detected with the Change Detector. To be even more precise, they are updated in the ngDoCheck. It’s called immediately after ngOnChanges and ngOnit. You can also create it in your component class to add some other checks there. If you’re not sure when it’s executed, you can add a console log there (just for debugging purposes, of course).

Technically, there’s only an issue with using an onPush change detection strategy. Then you need to remember to tell Angular when it should do the detection of changes, otherwise, the corresponding styles won’t change.

Last but not least, in case you use @angular/flex-layout, the ngStyle directive can be enhanced with mediaQuery that updates whenever it’s triggered by activations. It means you can have constructions like this:

<div 
    [ngStyle]="{'background-color':'red'}"
    [ngStyle.xs]="{'font-size.px':'20'}"
    [ngStyle.md]="{'background-color':'blue'}"
    [ngStyle.lg]="{'background-color':'green'}"
    [ngStyle.xl]="{'background': 'none'}"
></<div>

The right entry will be chosen based on the user’s screen resolution. Style without mediaQuery indicator will always be applied but can be overridden by others. It will be overridden for medium and large screen resolutions in the given example. These so–called special responsive features are described in the API. 

Ok, now you know how to use it. Let’s see why you probably shouldn’t.

(Dynamic) inline styles are bad!

You know now how ngStyle is used for inline CSS as well as how to use style attribute binding in Angular. Let’s take a minute to think about why anyone would decide to have inline styles when they can be extracted to external files and just referenced using classes. Developers want to make this one exception (every time!) from the general rules included in CSS files. 

Usually, using inline styles is a reaction to some event like user action, data arrival, or some frontend checks. And that’s fine. Why not highlight the validation error with a red background color when you get information the value is wrong? There’s nothing inherently bad with it, but…

…you lose the split between the structure layer (HTML file) and the presentation layer (CSS file) by mixing up both in one file. In this case, you’d like to change some styles for child elements or repeat the same “only one exception from a general rule” in another place. It’s getting unnecessarily complicated and more difficult to maintain. So is there a better alternative to using style or ngStyle for dynamic manipulation of CSS style? 

Class binding — a better solution!

In general, you shouldn’t have too many inline styles. Otherwise, it’s time to rethink your design. Those that you already have should be analyzed to see what their purpose is. If there’s no dynamic condition, just move them to the style file. Usually, there’s that one event that you expect will change many styles, such as loading data from a remote server or input data by a user. Then you can have a construction like that, somewhere in style:

.context {
    background-color: white;
    color: black;
    padding: 0;
    display: block;
}

.loader-data-context {
    background-color: grey
    color: grey;
    padding: 10px;
}

Template:

<div class=”context” [class.loader-data-context]="!isDataLoaded”></<div>

Here, you see some advantages over using ngStyle. First of all, all styles are in one file dedicated to it so you keep a nice split between layers. Style can also be easily reused in other places in the code. Just add the CSS class over there! It’s a much cleaner solution than using ngStyle. It might look like a bit of overhead if you’d like to change only one or two properties, but it’ll pay off in the future. I promise! This will solve the problem of inline styling when you have a boolean value or an event to react to.

There might be a case when you fetch style values and style dynamically. Then you really don’t have a choice — ngStyle is indeed the best option, but such solutions are used less and less, so please, don’t use it/introduce it (if you’re also doing backend), unless it’s really necessary!

Summary

There are many ways to achieve success with styles. The most important thing is to always think about maintenance and possible extensions in the future. Generally, it’s good to have a split between content and structure (HTML files), presentation (CSS), and behavior (TypeScript) layers. 

I like thinking about each layer as a book. I prefer to read books without the need to cross–check references in other books. 

Nevertheless, as I’ve already mentioned, it may be justified to use an inline style to assign styles dynamically. If that’s the case, feel free to use ngStyle or style attribute binding. You know now how you can do it properly!

Happy styling!

Looking for a reliable software development team?

We use cookies

We use cookies to make sure your website experience is as easy and as personal as possible. By accepting, you’re allowing them to do their job. Change your cookie preferences if you wish to.

Why? To analyze our visitor data, improve our website and show personalized content to our users. We want to give you a better experience of Massive Pixel Creation. Are you fine with this?