---
title: "How to add JS and CSS assets to a Drupal 8 theme · Appnovation"
url: "https://www.appnovation.com/insights/how-add-js-and-css-assets-drupal-8-theme"
description: "How to declare and attach JavaScript and CSS assets in a Drupal 8 theme or module using libraries.yml, with examples."
---

Article

# How to add JS and CSS assets to a Drupal 8 theme

[![](https://cdn.sanity.io/images/ey850001/production/d554cb30b50f2e0f5ec2f886c627b6f37dd65b94-68x68.png?w=68&auto=format) azvonkov azvonkov Senior Front End Developer](/people/azvonkov-azvonkov.md) Jan 08, 2015  
 7 min read 

![How to add JS and CSS assets to a Drupal 8 theme](https://cdn.sanity.io/images/ey850001/production/3d1332e7390d8870419959782c95c9787ced57a8-680x200.png?w=1400&auto=format) 

On this page

## On this page

In one of my previous [posts](/insights/creating-drupal-8-theme-sasssingularity-breakpoint.md) I wrote about creating a Drupal 8 theme and declaring assets (JS and CSS) associated with it. Recently there were a few changes in Drupal 8's core and the way these assets are served to a theme or a module. Drupal 8 introduces a concept of asset libraries for JS and CSS in themes and modules. One of the recent core updates was about changing the way[these assets are attached to the theme (opens in new window)](https://www.drupal.org/node/2379475).

In this post I wanted to go over a few practical examples of how these assets can be added and customized. Here are some scenarios:

*   Through a global library
*   Deleting or overriding existing styles served by core
*   Declaring various dependencies that are provided by Drupal 8's core
*   Specifying assets scope or sending JS to the footer
*   Specifying media type
*   Adding external CSS or JS library, e.g: Google Fonts
*   Adding conditional CSS or JS for older IE browsers
*   Adding custom libraries to specific pages, e.g: front page

## Global styles and scripts

In the example below `global-styling` is a name of a library (a file or collection of files) that is used for global styles. It is declared in a `theme_name.libraries.yml` and then also added to the `theme_name.info.yml` file. This specific library will now be available across the whole site.

Here is how it will look in the`theme_name.libraries.yml` file.

global-styling: version: VERSION css: theme: css/style.css: {} 

Then it's declared in the `theme_name.info.yml` file.

name: Example type: theme core: 8.x libraries: - theme\_name/global-styling 

Declaring scripts would be very similar. In the `theme_name.libraries.yml`

global-scripts: version: VERSION js: js/script.js: {} 

Then in the `theme_name.info.yml` file, we add these libraries.

name: Example type: theme core: 8.x libraries: - theme\_name/global-styling - theme\_name/global-scripts 

Now these two libraries or collections of JS and CSS files are available across the whole site. These two separate sets of CSS and JS can also be combined into one library.

global-styles-and-scripts: version: VERSION css: theme: css/style.css: {} js: js/script.js: {} 

## Deleting or overriding existing styles served by core

In the `theme_name.info.yml` file:

stylesheets-remove: - normalize.css 

or to override the core's stylesheet:

stylesheets-override: - normalize.css 

## Declaring dependencies

By default Drupal 8 doesn't load any additional scripts. For example jQuery is not loaded, but it can be declared as a dependency. For all core assets look into /core/assets/vendor. You will find modernizr, jQuery and other useful things in there.

Example of declaring a dependency.

global-scripts: version: VERSION js: js/script.js: {} dependencies: - core/jquery - core/jquery.once - core/modernizr 

## Specifying scope of a JS file or sending it to the footer

There are many cases when it would be best to have a JS asset at the footer of the page. By default they will be included in the header but you can easily send them to the footer by specifying the scope in the `theme_name.libraries.yml` file.

js/script.js: { scope: footer } 

## Specifying media type

Similarly, if there is a need for a print stylesheet in your theme it can also be easily specified with a media parameter in the `theme_name.libraries.yml` file.

css/print.css: { media: print } 

## Bringing in an external JS or CSS resource

Often you would want to include an external library in your theme, here is how it can be added in `theme_name.libraries.yml` file.

remote-custom: remote: https://github.com/yui/yui3 license: name: BSD url: https://github.com/yui/yui3/blob/master/LICENSE.md gpl-compatible: true version: VERSION js: http://yui.yahooapis.com/3.18.1/build/yui/yui-min.js: { type: external, browsers: { IE: 'lte IE 8', '!IE': false } } 

You can also specify additional parameters in the `theme_name.theme file` with a preprocess hook:

function theme\_name\_css\_alter(&$css) { $theme\_path = drupal\_get\_path('theme', 'theme\_name'); // Add googlefonts. $googlefonts = '//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700|Source+Serif+Pro:700,400'; $css\[$googlefonts\] = array( 'data' => $googlefonts, 'type' => 'external', 'every\_page' => TRUE, 'media' => 'all', 'preprocess' => FALSE, 'group' => CSS\_AGGREGATE\_THEME, 'browsers' => array('IE' => TRUE, '!IE' => TRUE), 'weight' => -1, ); } 

## Conditional CSS or JS for older IE browsers

You can specify IE conditionals through the parameters in the `theme_name.libraries.yml` file.

http://yui.yahooapis.com/3.18.1/build/yui/yui-min.js: { type: external, browsers: { IE: 'lte IE 8', '!IE': false } } 

## Adding or limiting a library to specific pages

If you only need to load a specific library onto a specific page, e.g maintenance page, you will need to add a hook in your `theme_name.theme` file. Here is an example:

function theme\_name\_preprocess\_maintenance\_page(&$variables) { $variables\['#attached'\]\['library'\]\[\] = 'theme\_name/custom-library'; } 

This can be useful when you only need certain styles on certain node types. You just need to create a hook for that specific node type to load your custom library. Often you will need additional JS for a custom home page banner or a slider. Here is an example of how a `custom-library` can be loaded only on a front page:

function theme\_name\_preprocess\_page(&$variables) { if($variables\['is\_front'\]){ $variables\['#attached'\]\['library'\]\[\] = 'theme\_name/custom-library'; } } 

Remember to always clear your caches when you are adding libraries or creating new hooks. An easy way to do that automatically is to set the `debug: true` in your Drupal 8 `services.yaml` file in `sites/default/` while developing.

[![](https://cdn.sanity.io/images/ey850001/production/d554cb30b50f2e0f5ec2f886c627b6f37dd65b94-68x68.png?w=68&auto=format) azvonkov azvonkov Senior Front End Developer · Appnovation](/people/azvonkov-azvonkov.md) 

## Keep reading

[![What is Sovereign AI](https://cdn.sanity.io/images/ey850001/production/a5889abdd5e80376912546622e046e3fbef234b4-2496x1664.png?w=640&auto=format)](/insights/what-is-open-source-sovereign-ai.md)

 Article · 7 min AI 

### [What Is Open Source, Sovereign AI?](/insights/what-is-open-source-sovereign-ai.md)

Every company is encouraging more AI, and almost every AI bill is climbing. Sovereign AI is about two kinds of control: over your data and over your costs. Here's why open source sits at its foundation.

[Iain MacNeil](/people/iain-macneil.md) Article 

[![AI-first experience design](https://cdn.sanity.io/images/ey850001/production/8bbc2418e87924ef10f36115478a2e10d5bed95e-1584x624.jpg?w=640&auto=format)](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

 Article · 6 min AI Sep 10, 2026 

### [How to Build an AI-First Experience Without Throwing Out Everything You've Already Built](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

Users now expect a direct answer, not a list of links to click through. Here's how organizations can layer an AI-First experience onto their existing website or app, in weeks rather than years.

[Andrew Douglas](/people/andrew-douglas.md) Article 

[![What Becomes Possible When AI Can Read All the Data](https://cdn.sanity.io/images/ey850001/production/c28ab0bd26753421ee42937e13adc7a7f19b47f0-1296x510.jpg?w=640&auto=format)](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

 Article · 4 min AI Sep 09, 2026 

### [What Becomes Possible When AI Can Read All the Data](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

Most of the world's data has never been analyzed, only sampled. AI changes that. How AI-ready data platforms unlock questions no one could ask before.

[Appnovation](/people/appnovation.md) Article 

## Get the thinking,  
*before everyone else.*

One considered email a month. New essays, field notes from live engagements, and the occasional strong opinion. No noise.
