Adding CSS and JavaScript to an Angular CLI Project

Dave Bush
5 min readApr 29, 2018

One of the most popular questions for new Angular developers seems to be “How do I add CSS and JavaScript to an Angular CLI project?”

Often, these programmers are coming from an AngularJS background and their world has changed.

In this article, we explore several “correct” methods of adding CSS and JavaScript into an existing project in a way that will work consistent with the bundling, minifying, and tree shaking that the Angular CLI does for us.

Adding CSS and JavaScript

The temptation is to add the external files directly to your index.html file. But if you do this, the files won’t get bundled. This wouldn’t be horrible, but it isn’t the Angular way. What we ultimately want to end up with is code that we can ship all as one unit.

If you’ve already done a build, you should have a folder named “dist” with all the files you need to run your application. What we want to end up with is ALL of the files we need for our application in that directory all bundled and minified.

As an example of how to do this, we will add Bootstrap 3 to our project. Remember, this is just an example. I’m not saying you should or shouldn’t use Bootstrap in your project. And as Bootstrap 3 uses jQuery, I’m not saying you should use jQuery in your Angular project. Although, sometimes you might be forced to do such a thing and it does happen to work as long as you don’t need to implement server side rendering.

Install

The first step is to add Bootstrap to our project.

npm install bootstrap --save-dev

Bootstrap will also need jQuery installed so we will add that next.

npm install jquery --save-dev

Include

And to tell the CLI that we want these files installed, we will open the .angular-cli.json file and look for the apps.styles and apps.scripts section

"styles": [
"styles.css"
],
"scripts": [],

And you will modify it to look like this:

"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.css",
"styles.css"
],
"scripts": [
"../node_modules/jquery/dist/jquery.js",
"../node_modules/bootstrap/dist/js/bootstrap.js"
],

Notice that we are relative referencing node_modules from the “src” directory, not the directory the .angular-cli.json file is in.

Use

Any CSS files you want to add that you won’t be referencing from your modules directly, and any javascript files that you won’t be importing into your TypeScript files go in this section. When you compile, they become part of the bundles. To prove this, we will modify the app.component.html file located in “src/app”

<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<div class="navbar-brand">
Getting Started With Angular 2 App
</div>
</div>
</div>
</nav>
<div class="container">
<h1>
{{title}}
</h1>
</div>

And now when you build and run the web application, you should see that it is styles using Bootstrap.

Alternate Way

An alternate mechanism you might want to consider using is to place @import statements in your application level CSS file, typically this is styles.css in an Angular CLI project. This works best if you are referencing external files (URLs) or files that you can access from your resources directory.

If it were me, I’d use the .angular-cli.json method and only use @imports when I absolutely have to so that I get the benefit of bundling all of my CSS code together.

Application Level Styles

One of the things you may have noticed in the discussion above is that styles.css was already included in our angular-cli.json file. This is where you add style information that is relevant to the entire application.

And so far, this is what you would expect. But Angular 2 takes styling to the next level.

Component Styles

If you’ve been doing any web development at all for any length of time, you may have noticed that you need to be careful about how you apply styles to components within your application because if you aren’t, the style information will “leak” into other components. Typically, the way I’ve gotten around this is by creating a unique scope around the component so that I can include that scope in my CSS.

Angular does that work for us.

You see, you can also add style information in your components. If you open the existing app/app.component.ts file, you will notice that there is both a templateUrl and a styleUrls attribute in the @Component() metadata section. In the styleUrls property you can specify a list of relative URLs of CSS files to include.

If we include CSS information in the CSS files, you will see that when we render the page, the CSS gets rewritten so that the CSS is scoped to the component. In fact, if you try to style a component that is a child of the component using the parent’s CSS file, it won’t work. This is why we can’t just include the application level CSS in the top level component and instead have to put it in a CSS file that we include in our angular-cli.json file.

Application Level JavaScript

The standard way of including JavaScript as part of your application is by using the import keyword. When the Angular CLI compiles the code, it looks for all the imports and bundles all the JavaScript together. So, you might wonder why we need a scripts block in our angular-cli.json file.

One reason is because when we build the code for production, the CLI removes any code from the bundle that isn’t being used. If you need JavaScript code to be included that the compiler would not be able to tell you are using, you must include it in some other way. In the case above, even if we did an import of the jQuery and bootstrap code, the CLI would never be able to detect that we are actually using it.

It’s All JavaScript

One final note about how Angular works. While you and I are coding CSS and HTML, when these files get compiled into our bundles, they all end up as JavaScript. This might seem inefficient. We’ve been told for years, “Don’t render HTML using JavaScript.” But, the reason we’ve been told that is because most of us render HTML with JavaScript in a very inefficient way.

But, because Angular has implemented smart change detection, it is more efficient to render the HTML using JavaScript. That nice template you created is going to end up as JavaScript. Don’t go looking for it as a separate file that Angular is making an AJAX call to suck into your application. It gets bundled in with all your other JavaScript.

And the same thing happens with all your CSS. Angular 2 renders that all into the HEAD section of your HTML using JavaScript. If you open development tools, you will see several STYLE elements. If you open them up and look, you’ll see renditions of the CSS from all over your application.

--

--

Dave Bush

Dave Bush is an Agile/Scrum/Extreme Architect and Programmer who is currently focused on the world of Angular.