CSS Tutorial with Angular 7/8: ngClass, ngStyle & ViewEncapsulation

In this tutorial, we'll learn about CSS and how to use it in Angular apps. We'll see by example how an Angular 8 application generated by Angular CLI is styled.

We'll also see how to use ngClass and ngStyle built-in directives for applying styles dynamically

We'll also see the various APIs and configurations related to CSS in Angular.

In a nutshell, we'll learn:

  • The basics of CSS for Angular developers,
  • How to use CSS styles in components,
  • Global CSS styles,
  • CSS and View encapsulation in Angular,
  • Component selector,
  • How to import CSS and how to use a CSS framework like Bootstrap or Tailwind with Angular 8,
  • The :host pseudo-class selector
  • How to style parent and child components,
  • How to share CSS between components, and much more.

You can either use Angular CLI as the tool for initializing and working with your Angular 8 project or Stackblitz, the online IDE for front-end development.

What is CSS?

So, what is CSS?

Let's refer to Wikipedia for the definition of CSS.

Cascading Style Sheets (CSS) is a style sheet language used for describing the presentation of a document written in a markup language like HTML. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.

CSS allows developers to separate the presentation from the content. This has many benefits such as enabling multiple web pages to share formatting by specifying the relevant CSS in a separate .css file, reduce complexity and repetition in the structural content.

Thus we can see that CSS tries to solve the common problems in general software and web development such as reusability and separation of concerns.

If you know that HTML is the very first language that you need to learn as a web (frontend or backend) developer then you'll also want to know that CSS is the second language that you should know. In most cases, you don't have to be a CSS expert but you should at least have the basics!

How Does CSS Relate to HTML?

HTML is a markup language that is used to create the structure of web pages by allowing you to add headlines, paragraphs, forms, and tables and embed images, videos and other types of media. CSS is on the other hand concerned with styling the web pages such as layouts, colors and fonts, and much more.

How Is CSS Used?

CSS is deeply related to HTML as it's applied to HTML element tags using various ways such as external CSS files, internal CSS styles or inline styles.

For instance, let's take the <body> element tag in HTML which defines the main content of the HTML document that will be directly visible on your web page.

If you want to make the background of the web page appear black and the color of any text within the body appear white, you’ll need to use CSS styles as follows:

body  {  color: white;  background-color:black;  }

In this example, body is the CSS selector which defines the HTML element tag to which the CSS styles will be applied.

In CSS, you need to place the element selector on the left and the CSS properties like the color and background-color and their values between curly brackets in the right. The right part is called a CSS declaration.

Note: In our example, color and background-color are CSS properties while white and black are values. A CSS property can have more than one accepted value in most cases.

In our example, we used a simple CSS selector for selecting the HTML body in a document but CSS provides complex and powerful selectors that can select multiple HTML elements based on various rules.

How Is CSS Applied to HTML Elements?

Now that you have seen a simple example of a CSS selector and declaration, how do we apply the defined CSS code to an actual HTML document?

As we said previously, CSS is deeply related to HTML. As such, HTML does provide more than one way for attaching CSS styles to HTML documents.

HTML provides three ways that you can use to attach CSS styles to your HTML pages, such as:

  • Using external CSS stylesheets (simple text files with the .css extension),
  • Using internal CSS styles via the HTML <style> tag element,
  • Using inline CSS styles via the style attribute suported by HTML element tags.

External stylesheets can be attached to an entire website, while internal styles can be attached to individual pages and finally inline styles can be only attached to individual HTML element tags. The two latter methods should only be used for small use cases.

In most cases, all the previous are combined to style websites.

Now, how to attach an external stylesheet file to an HTML file? You simply need to use the <link> tag in the <head> section of the document and point the href tag to the URI of the CSS file:

<head>
<link rel=”stylesheet”  type=”text/css”  href="styles.css”>
</head>

Internal styles are CSS instructions which are added in the <head> of an HTML document via the <style> tag:

<head>
<style>
body {  color: white; background-color: blue;  }
</style>
</head>

Inline styles are CSS code that's added directly into the HTML element, and applicable only to that element. For example:

<h1  style=”color: white;”>CSS Tutorial</h1>

Note: Angular adds more ways to attach CSS to HTML templates and provides more features for working with CSS.

Styling Angular Components with CSS

https://angular.io/guide/component-styles

Angular applications are simply styled with the standard CSS that you already know.

You can use external CSS stylesheets via the <link> tag, internal CSS via the <style> tag and inline styles via the style attribute. And you can apply standard selectors, rules, and media queries to your Angular components.

Let's get started by initializing a brand new Angular 8 project using the Angular CLI. Open a command-line interface and run the following command:

$ npx -p @angular/cli ng new angular-css-demo

The npx is installed when you installed npm.

We have used Angular CLI 8 locally without installing it globally on our system thanks to npx.

Next, navigate to your project's folder and start the local development server using the following commands:

$ cd angular-css-demo
$ npx ng serve

You'll be prompted if you Would you like to add Angular routing? Type y for Yes and Which stylesheet format would you like to use? Choose CSS.

Note: If you already have Angular CLI installed on your system, you don't need to use the npx command.

Angular CLI allows you to use various stylesheet formats such as CSS, SCSS, Sass , Less, and Stylus.

Sass, SCSS, Less, and Stylus are called CSS preprocessors. A CSS preprocessor is a program that lets you generate CSS from the preprocessor's unique syntax. There are many CSS preprocessors to choose from, however, most CSS preprocessors will add some features that don't exist in pure CSS, such as mixin, nesting selector, inheritance selector, and so on.

Browsers can only understand CSS so these other formats are precompiled by the CLI using an appropriate preprocessor at the build time.

You can go to the http://localhost:4200/ address to see your app up and running:

As you see, we already have a beautifully-CSS-styled interface with some placeholder content. Of course in a real-world situation, you would remove this content and add your own but in our tutorial, let's take this as our example and learn how CSS is attached and applied to the various Angular components.

Let's get started by investigating the index.html file, the entry point of our Angular application. Open the src/index.html file, you'll find the following content:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularCssDemo</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

This is a typical HTML file with standard HTML element tags except for <app-root> which refers to the App component of our Angular 8 application.

In the <head> section, we can use <link> tags to attach global CSS files to our app. We'll see an example in the next section.

Now, inside the src/ folder of your project, you'll find a styles.css file. If you open it, you'll find out that it's empty with only the following CSS comment:

/* You can add global styles to this file, and also import other style files */

This file can be used for adding global styles and import other style files. Add the following CSS code:

body{
    background-color: #b1cbe4;
}

Go back to your app in the web browser, you should see that our CSS background color is applied to the <body> element:

But since the global src/styles.css file is not linked from the src/index.html file via a <link> element tag, how the style is applied?

Angular CLI makes use of an angular.json configuration file which contains a styles array that can be used for adding any global stylesheets. By default, the styles.css file is present in this array.

  "projects": {
    "angulardemo": {
      /* [...] */    
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            /* [...] */
            "styles": [             
              "src/styles.css"
            ],
            "scripts": []
          },

Angular CLI injects any global styles via a <style> tag in the <head> section of the index.html file. You can confirm that by inspecting your web page in the web browser (Ctrl + Shift + I in Chrome). This is a screenshot of the Elements panel in our case:

The CSS comment that starts with sourceMappingURL allows the browser to know where the source map is.

Source maps are used for debugging purposes as they provide mapping information between symbols in the original source files and the final built bundles. For example, thanks to source maps, the browser has the required information to let us know that our previous CSS rule applied to the <body> element from the global src/styles.css file at line 3 even if the Angular CLI inlined the content of the file:

You can instantly agree with how useful source files are in development.

Check out Use a source map.

We can also ourselves use the <style> element to include global styles in the <head> section of the index.html file.

These are the points that you need to remember about global styles:

  • You can add global styles using the default styles.css file or your own stylesheets in the styles array in the angular.json file,
  • You can cause the @import statement in the styles.css file to include global stylesheets to your Angular project,
  • Global styles are not scoped by any custom HTML attributes,

- Component styles override global styles.

Applying CSS Styles to Angular Components

We have seen that we can use global CSS files to apply styles to our application just like a typical HTML document but Angular provides more options for including styles with more features like CSS isolation.

Open the src/app/app.component.html file which contains the HTML template for the root and the only component in our application at this stage. This is a portion of the file content truncated:

<style>
  :host {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    font-size: 14px;
    color: #333;
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  .toolbar {
    height: 60px;
    margin: -8px;
    display: flex;
    align-items: center;
    background-color: #1976d2;
    color: white;
    font-weight: 600;
  }
  /* [...] */
</style>

<!-- Toolbar -->
<div class="toolbar" role="banner"></div>

  <!-- Resources -->

  <!-- Next Steps -->
  <!-- Terminal -->

  <!-- Links -->

  </div>

  <!-- Footer -->
  <footer>
  </footer>


</div>

<router-outlet></router-outlet>

Angular allows us to include inline CSS styles in components using the standard <style> tag just like typical HTML documents.

These styles are only applied to the template where they are included i.e in our case to the template of the App component.

Another better way is to use an external CSS file or multiple files for styling the component. We can already find an empty src/app/app.component.css file in our project which has the same name as the template of the App component. This should give us a hint that any styles that are added in this file are applied to the src/app/app.component.html template and that's correct by they are not linked by convention because they have the same name but through an explicit meta property called styleUrls in the component. Open the src/app/app.component.ts file:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'angular-css-demo';
}

The styleUrls property, that can be added via the component decorator, takes an array of files paths relative to the component file and allows you to attach one or multiple CSS files to a component.

Let's take the inline styles of the app template and add them in the src/app/app.component.css file without the <style> tag.

If you save the changes and go back to your web app, you should see that our interface looks in the same way as before.

The :root pseudo-class

In our app component styles, we have a special CSS selector called :root:

:host {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    font-size: 14px;
    color: #333;
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

If you need to style the component custom HTML element itself, and not an element inside its template, you can use the :root pseudo-class selector.

In this case, we need to style the app-root component itself and can't do that using the styles inside the related src/app.component.css file because the CSS styles inside that file will be scoped to the HTML element tags of the src/app.component.html template.

The :root selector enables you to apply CSS styles to the app-root element only.

Now, let's see how Angular implements this. Go back to your web app and open the Elements panel in DevTools by inspecting the page or pressing Ctrl+Shift+I in Chrome,

If you look in one of the <style> elements in the <head> section, you'll find our app component CSS styles inlined by Angular CLI:

They are the same styles in the src/app/app.component.css file except that they have now some weird names as part of their selectors. These names are unique and custom attributes added to the HTML elements of our component by Angular at runtime. If you look below inside the <body> element, you'll see:

Angular 8 added a custom _nghost-dsy-c0 attribute to the <app-root> element and a _ngcontent-dsy-c0 atribute to each HTML child of <app-root>.

The custom attributes are used to create CSS selectors with much higher specificity (and much harder to override) so the component styles will be isolated and only applied to the elements of the component.

Note: If you reload your application, new unique custom attributes will be used in the HTML elements and CSS styles.

This is not a perfect CSS isolation technique. If someone wants to override those styles, they will be able to do it, since it's not enforced by the web browser but only emulated by Angular using CSS rules and custom HTML attributes to scope the styles to individual components.

Note: You can structure your CSS code using methodologies such as SMACSS.

You can also use a CSS pre-processor for adding programming-like features to your styles like CSS variables and inheritance, etc.

Angular supports other mechanisms for CSS isolation which are supported by modern browsers such as Shadow DOM

Note: Native Shadow DOM is currently implemented by Chrome and Opera so we can't rely on it at the moment.

Angular can bundle component styles with components, enabling you to write a more modular code than regular stylesheets.

How Angular View Encapsulation Works?

By default, Angular uses an emulated View Encapsulation to encapsulate CSS styles within their components so they can be isolated and only applied to the HTML elements within these components.

There are three modes of Angular View encapsulation:

  • ViewEncapsulation.Emulated: Emulates CSS scoping and isolation by adding an attribute containing surrogate id to the Host Element and pre-processing the style rules provided via the styles property of the component decorator or styleUrls, and adding the new Host Element attribute to all selectors. This is the default option.
  • ViewEncapsulation.Native
  • None: Don't provide any template or style encapsulation.
  • ViewEncapsulation.ShadowDom: Use Shadow DOM to encapsulate styles. For the DOM this means using modern Shadow DOM and creating a ShadowRoot for Component's Host Element.

You can change the default view encapsulation of a component via a decorator property called encapsulation.

Open the src/app/app.component.ts file and change the View Encapsulation mode to None:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class AppComponent {
  title = 'angular-css-demo';
}

We first import ViewEncapsulation from the @angular/core package. Next, we add the encapsulation property to the component decorator and set its value to ViewEncapsulation.None. This will change the encapsulation mode of the App component.

If you head back to your running web application, you'll see that nothing has changed in the appearance of the UI but if you inspect the page, you'll see that no CSS scoping is applied with custom HTML attributes and CSS attribute selectors.

This is a screenshot of the Elements panel:

This is a screenshot of the CSS styles:

The styles are inlined but no isolation or scoping techniques are applied.

Next, let's change the view encapsulation to ShadowDom:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  encapsulation: ViewEncapsulation.ShadowDom
})
export class AppComponent {
  title = 'angular-css-demo';
}

If you inspect the DOM of your app, you should see that both the HTML template and CSS styles of the App component are encapsulated using ShadowDom:

Why Would You Need to Isolate CSS Per Components

Angular provides emulated techniques for isolating and encapsulating CSS styles and also adopts the native modern techniques like Shadow DOM but why CSS isolation is such an important feature?

There are many reasons for that. For example, one important reason is maintainability which is a crucial phase in ay serious software or web development project.

Component-based architectures, adopted by Angular and most modern frameworks nowadays including React and Vue, are about creating apps with isolated and decoupled components. In web apps, CSS and styling are an essential part which means isolation and decoupling should also include CSS to prevent the styles from one feature, implemented as a module or component, to interfere with the styles of another feature.

Also, how about components from third-party libraries? If CSS styles are bleeding in or out this will lead to a broken component simply because of styles.

If you are a library developer, CSS styles isolation would allow you to ship highly decoupled and reusable components that have higher chances to be used inside other projects without any issues.

Using the ngClass and ngStyle directives

Angular provides builtin directives for dynamically applying CSS styles to components such as the ngClass and ngStyle directives. For example

<p ngClass="selected"></p>  
<p [ngClass]="'selected'"></p>     
<p [ngClass]="['selected']"></p>   
<p [ngClass]="{'selected': true}"></p>

Note: The ngClass directive can be used with the other class attributes.

The ngStyle directive takes pairs of CSS properties and values. For example:

<p [ngStyle]="{'color': 'white'}" style="margin: 5px;"><song-track [ngStyle]="{'font-size.px': '12'}">  
<p [ngStyle]="{'font-size': '12px'}"></p>
<p [ngStyle]="{'color': 'white', 'font-size': '12px'}">

Conclusion

As a recap of our CSS tutorial, we have seen what CSS is and what is used for. We have seen how CSS is used in Angular and created a simple Angular 8 app with the CLI to demonstrate various concepts such as global styles, component styles and the :root pseudo-class.

We have learned about global styles in Angular and how the frameworks add additional features for CSS isolation and scoping such as View encapsulation using Emulated or ShadowDom modes.

We finally seen how to use the ngClass and ngStyle directives for dynamic styling in Angular components.

Note: We also publish our tutorials on Medium and DEV.to. If you prefer reading in these platforms, you can follow us there to get our newest articles.

You can reach the author via Twitter:

About the author

Ahmed Bouchefra
is a web developer with 5+ years of experience and technical author with an engineering degree on software development. You can hire him with a click on the link above or contact him via his LinkedIn account. He authored technical content for the industry-leading websites such as SitePoint, Smashing, DigitalOcean, RealPython, freeCodeCamp, JScrambler, Pusher, and Auth0. He also co-authored various books about modern web development that you can find from Amazon or Leanpub


Get our Learn Angular 8 in 15 Easy Steps ebook in pdf, epub and mobi formats, plus a new Angular 8 tutorial every 3 days.


Online Courses (Affiliate)

If you prefer learning with videos. Check out one of the best Angular courses online
Angular 8 - The Complete Guide (2019+ Edition)

Angular Crash Course for Busy Developers

comments powered by Disqus
DMCA.com Protection Status