Tutorial: Styling Angular CLI Apps with Bootstrap
Tags: angular, bootstrap, tutorial, beginners
Published: 2020-07-07 17:20:22

---
title: 'Tutorial: Styling Angular CLI Apps with Bootstrap'
published: true
description: In this tutorial, you learn how to use Bootstrap to style Angular Apps.
tags: angular, bootstrap, tutorial, beginners
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9hnz0q3oe7a5nnighvq2.png
series: Styling Angular CLI Apps
---

![Example of the pages of the final app](https://dev-to-uploads.s3.amazonaws.com/i/uisbw2k5xdupr3lrtipy.gif)

In this tutorial, you learn how to use Bootstrap to style Angular CLI Apps.

The goal is to build an application layout with a header and footer, a home page, about page, and a login page with form.

Check the [live demo here](https://tutorial-styling-angular-cli-apps-with-bootstrap.netlify.app/) or the [GitHub repo](https://github.com/beeman/tutorial-styling-angular-cli-apps-with-bootstrap).

## Requirements

Make sure you have the following tools installed:

- Node.js and NPM, visit the [homepage](https://nodejs.org) for installation instructions.
  - Run `node -v` to verify you have version 12 or higher.
  - Run `npm -v` to verify you have version 6 or higher.
- Angular CLI (`npm install -g @angular/cli@latest` to install)
  - Run `ng --version` to verify you have version 10 or higher.

If you prefer using `yarn`, first [configure Angular CLI's default package manager](https://beeman.dev/posts/using-yarn-with-angular-cli-1n73/). This makes sure the generated application has a `yarn.lock` file instead of a `package-lock.json`.

## 1. Create a new application

Open a terminal and run the following command:

```
ng new sandbox --routing --style scss --strict
```

The `ng new` command generates a basic Angular application in a directory called `sandbox` and installs the dependencies.

The `--routing` flag instructs Angular CLI to generate a routing module.
The `--style scss` parameter sets SCSS as the style preprocessor.
The `--strict` flag configures the application to run in [strict mode](https://angular.io/guide/strict-mode).

At the end of the setup, the Angular CLI also initializes a git repository and does an initial commit.

## 2. Start the application in development mode

After the installation is finished, run the following command to navigate to the _project directory_.

```bash
cd sandbox
```

In the project directory you can start the development server using `ng serve`:

```
ng serve
```

> ** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **

Navigate to the link displayed by the Dev server and verify that it works. The app is now ready to get some style(s)! 😎

## 3. Install Bootstrap

Run the following command in your project directory to install Bootstrap:

```
npm install bootstrap
```

When the installation is finished we now can tell Angular CLI to use these styles.

Open `src/styles.scss` and add the following lines:

```scss
@import '~bootstrap/scss/bootstrap';
// Set the full page height so we can stick the footer to the bottom
html,
body {
  height: 100%;
}
```

Next, open `src/app/app.component.html` and delete all the content, replace it with the following snippet:

```html
<h1 class="text-center text-primary">Hello Bootstrap!</h1>
```

When you go back to your browser, you should see `Hello Bootstrap` in big blue letters! 🎉

Let's move on to make our app look a little better!

## 4. Configure the application layout

![The basic application layout](https://dev-to-uploads.s3.amazonaws.com/i/890nao89aq581a8xiles.png)

In this step we create a `UiModule` and add three components to it: `LayoutComponent`, `HeaderComponent` and `FooterComponent`.

> 💡 It's a good idea to keep the UI separate from the rest of the app. This 'separation of concerns' also allows you to easily re-use the UI in other projects.

### 4.1 Create the `UiModule`

Run the following command to generate the `UiModule`.

```
ng generate module ui --module app
```

The `--module` parameter imports the `UiModule` in our main `AppModule`:

Next, generate the 3 components inside of this new module:

```
ng generate component ui/layout
ng generate component ui/header
ng generate component ui/footer
```

> 💡 The `ng generate` command supports shortcuts: use `ng g c` to generate a component, `ng g m` to generate a module, etc.

### 4.2 Implement the LayoutComponent

Open `src/app/ui/layout/layout.component.html` replace the content with the following snippet:

```html
<!-- This flex container takes the full height -->
<div class="d-flex flex-column h-100">
  <app-header></app-header>
  <!-- The main area does not shrink, 'pushing down' the footer -->
  <main class="flex-shrink-0">
    <!-- This will render the routes -->
    <router-outlet></router-outlet>
  </main>
  <!-- This keeps the footer down if the main content does not fill up the space -->
  <footer class="mt-auto">
    <app-footer></app-footer>
  </footer>
</div>
```

We use this `LayoutComponent` in the router, and render the _children_ in the location of `router-outlet`.

Before moving on, make sure to import `RouterModule` in `UiModule`.

Open `src/app/ui/ui.module.ts` and add the following code next to the other imports:

```typescript
import { RouterModule } from '@angular/router';
```

Add `RouterModule` to the `imports` array:

```typescript
@NgModule({
  declarations: [LayoutComponent, HeaderComponent, FooterComponent],
  imports: [CommonModule, RouterModule],
})
```

> 💡 If you forget to import the `RouterModule`, the server will tell you:

    ERROR in src/app/ui/layout/layout.component.html:3:3 - error NG8001: 'router-outlet' is not a known element:
      1.  If 'router-outlet' is an Angular component, then verify that it is part of this module.
      2.  If 'router-outlet' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.</pre>

### 4.3 Use the LayoutComponent

Open `src/app/app-routing.module.ts` and replace the line `const routes: Routes = []` with the following snippet:

```typescript
const routes: Routes = [
  {
    path: '',
    component: LayoutComponent,
    children: [
      // Here we will add our application pages
    ],
  },
];
```

Make sure to import `LayoutComponent` in `src/app/app-routing.module.ts`:

```typescript
import { LayoutComponent } from './ui/layout/layout.component';
```

Open `src/app/app.component.html` and replace the content with the following snippet:

```html
<router-outlet></router-outlet>
```

Save all the files and check your browser, you should see the default `HeaderComponent` and `FooterComponent` being rendered. Time to spice them up!

### 4.4 Implement the Header

Open `src/app/ui/header/header.component.html` and replace the content with the following snippet:

```html
<!-- You can change the values `dark` here with any of the following: -->
<!-- dark, light, primary, secondary, success, info, danger, warning -->
<nav class="navbar navbar-dark bg-dark">
  <!-- This is the application title with a link to the root -->
  <a class="navbar-brand" routerLinkActive="active" routerLink="/">Angular & Bootstrap</a>
  <!-- This is a spacer so the links move to the end -->
  <div class="mr-auto"></div>
  <!-- This main navigation links are defined here -->
  <div class="navbar-expand">
    <div class="navbar-nav">
      <!-- Each link has the routerLink property set to a different route -->
      <a class="nav-item nav-link" routerLinkActive="active" routerLink="/home">Home</a>
      <a class="nav-item nav-link" routerLinkActive="active" routerLink="/about">About</a>
      <a class="nav-item nav-link" routerLinkActive="active" routerLink="/login">Login</a>
    </div>
  </div>
</nav>
```

Refer to the [bootstrap documentation of the navbar](https://getbootstrap.com/docs/4.5/components/navbar/) for more details on the syntax of the navbar and how to make it responsive.

### 4.5 Implement the Footer

Open `src/app/ui/footer/footer.component.html` and replace the content with this:

```html
<div class="py-3 bg-dark text-center text-muted">
  <small>Copyright &copy; 2020</small>
</div>
```

## 5. Add application Pages

With the application layout in place, it's time to add a few pages.

The command we use creates a _module_ with a _component_ and [lazy-loads](https://angular.io/guide/lazy-loading-ngmodules) it in the `AppModule`.

> 💡 Lazy loading is the recommended way of routing in an Angular app as it makes sure the users don't download any code they won't run.

### 5.1 Create a Home page

Run the following command to generate the `HomeModule`:

```
ng g module pages/home --route home --module app
```

Open `src/app/pages/home/home.component.html` and replace the content with this:

```html
<div class="container py-5">
  <div class="jumbotron">
    <h1 class="text-secondary">Home</h1>
  </div>
</div>
```

Go to your application in the browser and click the _Home_ link in the header.

You will be taken to the route `/home` with the text 'Home'. However, the layout with the header and footer is gone!

To fix this, open `src/app/app-routing.module.ts` and move the newly created route inside the `children` array:

```typescript
const routes: Routes = [
  {
    path: '',
    component: LayoutComponent,
    children: [
      // Here we will add our application pages
      {
        path: 'home',
        loadChildren: () => import('./pages/home/home.module').then(m => m.HomeModule),
      },
    ],
  },
];
```

After saving this file, the page should render properly.

### 5.2 Create an About page

Run the following command to generate the `AboutModule`:

```
ng g module pages/about --route about --module app
```

Open `src/app/pages/about/about.component.html` and replace the content with this snippet:

```html
<div class="container py-5">
  <div class="jumbotron">
    <h1 class="text-secondary">About</h1>
  </div>
</div>
```

Open `src/app/app-routing.module.ts` and move the about route inside the `children`, so it sits next to the route to the `HomeModule`.

### 5.3 Create a Login page

The login page is a bit more complex because it has a form and uses the router to redirect.

Run the following command to generate the `LoginModule`:

```
ng g module pages/login --route login --module app
```

Open `src/app/pages/login/login.component.ts` and add the following code next to the other imports:

```typescript
import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
```

Change the content of the `LoginComponent` class to this snippet:

```typescript
export class LoginComponent implements OnInit {
  // The form group defines the fields used in the form
  form = new FormGroup({
    email: new FormControl(''),
    password: new FormControl(''),
  });

  // Inject the router so we can navigate after a successful login
  constructor(private readonly router: Router) {}

  ngOnInit(): void {}

  public submit() {
    // Use the form value to do authentication
    console.log(this.form.value);
    // Navigate after successful login
    return this.router.navigate(['/']);
  }
}
```

Open `src/app/pages/login/login.component.html` and replace the content with this snippet:

```html
<!-- This flex container takes the full height and vertically centers the content -->
<div class="d-flex flex-column h-100 justify-content-center">
  <div class="container">
    <div class="row">
      <!-- This is a single column that is responsive -->
      <div class="col-12 col-md-6 offset-md-3">
        <div class="card">
          <div class="card-header">Login</div>
          <div class="card-body">
            <!-- The formGroup 'form' is defined in the component class -->
            <form [formGroup]="form">
              <div class="form-group">
                <label for="email">Email address</label>
                <!-- The formControlName defines the name of the field in the formGroup -->
                <input id="email" formControlName="email" type="email" required class="form-control" />
              </div>
              <div class="form-group">
                <label for="password">Password</label>
                <input id="password" formControlName="password" type="password" required class="form-control" />
              </div>
            </form>
          </div>
          <div class="card-footer">
            <div class="d-flex justify-content-between">
              <a routerLink="/" class="ml-2 btn btn-outline-secondary">
                Home
              </a>
              <!-- The button has a click handler, it will be disabled if the form is not valid -->
              <button (click)="submit()" [disabled]="!form.valid" type="submit" class="btn btn-outline-success">
                Log in
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
```

> 💡 The template of the `LoginComponent` is quite large. When adding more authentication pages, consider creating a separate `AuthLayoutComponent` and use that like `LayoutComponent`, then add `LoginComponent`, `RegisterComponent`, etc as the children of `AuthLayoutComponent`.

Go to your application in the browser and click the _Login_ link in the header.

The login page renders the form in the center of the screen, and we don't need to add the route to the `children` array.

There is one last thing to fix. If you click the _Home_ link in the login page, you will be taken back to the _root_ of the application, which is blank.

Wouldn't it be great if we could go to the Home page instead?

### 5.4 Redirect the root route

Open `src/app/app-routing.module.ts` and add the following object on the top of the `routes` array:

```typescript
const routes: Routes = [
  {
    path: '',
    // If this path is the 'full' match...
    pathMatch: 'full',
    // ...redirect to this route.
    redirectTo: 'home',
  },
  // The other routes go here
];
```

## Where to go from here?

As stated in the introduction, this app is a starting point and should be fairly straight-forward to enhance it to your liking.

### Additional libraries

Use either [ng-bootstrap](https://ng-bootstrap.github.io/) or [ngx-bootstrap](https://valor-software.com/ngx-bootstrap/) if you want to use Angular implementations of Bootstrap components like dropdowns, tabs, collapse, etc. Both libraries are great options, pick the one you like best.

If your apps have a lot of forms, use [formly](https://formly.dev) for a declarative way of defining your forms, without writing any of the form templates.

### Themes and colors

To tweak Bootstrap's appearance, open `src/styles.scss` and set the variables. Make sure to define the variables before importing Bootstrap:

```scss
$dark: hotpink;
$jumbotron-bg: #333;
$secondary: limegreen;
$body-bg: #555;
@import '~bootstrap/scss/bootstrap';
```

Another great option is [Bootswatch](https://bootswatch.com/) which offers more than 20 different Bootstrap based layouts

## Conclusion

In this tutorial, you learned how to create a basic Angular application, and use Bootstrap to create a layout with header and footer.

The app has several pages that are _lazy loaded_. The Login page has a form with basic validation and a redirect back to the Home page.

In case you have any questions, feel free to leave a comment on DEV or send me a message on [Twitter](https://twitter.com/beeman_nl)!

Big thanks to [Jeffrey](https://dev.to/jefiozie) and [Chau](https://twitter.com/nartc1410) for reviewing this post!

Happy coding!

Cheers, beeman 🐝