You are here

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

In one of my previous posts 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 .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 scriptsIn 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 coreIn the theme_name.info.yml file:
stylesheets-remove:
- normalize.css

or to override the core's stylesheet:
stylesheets-override:
- normalize.css

Declaring dependenciesBy 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 footerThere 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 typeSimilarly, 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 resourceOften 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 browsersYou 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 pagesIf 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.

SHARE SOCIAL
Senior Front End Developer
Andrei is a Senior Interactive Designer, Frond End Developer and a Drupal Themer with a passion for clean functional design and great code. He has been working with Drupal for over 6 years and has attended 3 North American DrupalCons. With a Bachelor’s degree in Interactive Design & Multimedia...→ More about Andrei
Senior Front End Developer

Andrei is a Senior Interactive Designer, Frond End Developer and a Drupal Themer with a passion for clean functional design and great code. He has been working with Drupal for over 6 years and has attended 3 North American DrupalCons. With a Bachelor’s degree in Interactive Design & Multimedia from Andrews University, USA. Andrei has traveled extensively and has lived in 3 countries prior to settling here in Canada.

Last Place Visited: (besides Vancouver) New York, Paris, Stockholm.

On the Playlist: London Grammar, Austra, The National.

Favorite Books: The Brothers Karamazov, The Meditations by Marcus Aurelius.

Movies: 2001: A Space Odyssey

Bucket list accomplishments: Biked over 7000 kms in the last 2 years. Learned how to make bread from scratch. Planted few trees. Traveled through Europe, visited Africa and lived in a country called USSR. 

 

 
Appnovation Technologies