Adding a Javascript library to Drupal 8

This evening at our local Drupal meetup, in Bellingham, WA,  Trebor and I dug into Javascript in Drupal 8. In Drupal 7 we use drupal_add_js() hooks. Drupal 8 changed this and several other aspects of how one adds JS to a site.

The move away from drupal_add_js() is well documented in the change record, back on December 4th, 2014. Though adding JS now takes a little more work, the pay-off is worth it. As I understand the rendering system, helpfully drawn out in this image, every entity is now cacheable, per entity. This means if one entity changes on a page, the whole page does not need to have the cache flushed, just that one entity will reload.

I messed around with the core Bartik theme to get this working. The end result is having the search box become sticky on very long posts, so as you scroll down, the search box sticks with you in the upper left.

We modify two files and create one brand new one.

Step 1:

Modify bartik.libraries.yml found in /core/themes/bartik/bartik.libraries.yml. Within that file add the following code at the bottom.

  version: 1.0.0
    sticky/bartik.js: {}
    sticky/jquery.sticky.js: {}
    - core/jquery

The first line declares to Drupal how we can access the components using the new attach_library function. You can call it whatever you want, I chose to name it the same as the library I want to add.

I don’t know what the version is for, but it seems to need it. You can put whatever you want where 1.0.0 is. Then you tell Drupal that stickyjs has a few javascript files and a dependency on jquery. What you are adding here to the .yml file is what used to live in the .info file for a module or theme. You can see where this is roughly outlined within the following Defining a Library section on

Step 2:

Modify this file: /core/themes/bartik/templates/block–search-form-block.html.twig

Here we need to actually tell Drupal to load this library, when this block is present on the page being requested.

{% block content %}
  <div{{ content_attributes.addClass('content', 'container-inline') }}>
    {{ parent() }}
{% endblock %}

The file in unmodified form does not include the second line {{attach_library()}}. What attach_library() does is load the file when this search block is present. The argument in the function is the theme or module name, in this case, bartik. Then the / name you used in the yml file to tell Drupal about your javascript. We end up with bartik/stickyjs.

Step 3:

Download the JS library and add in a .js file that we can invoke with Drupal behavior. For this example we used the awesome stickyjs jquery plugin.

We extracted the download to /core/themes/bartik/sticky. We then created a new file in there named bartik.js, which we defined earlier in the .yml file. I dropped in this snippet of code to invoke the sticky js plugin.

(function ($) {
  Drupal.behaviors.bartik = {
    attach: function (context, settings) {

This is a fairly standard Drupal 7 looking behavior, so not much to see here. This will fire when the page with the search block loads.

Step 4:

Clear the cache by going to your website then to admin/config/development/performance and click the big Clear all Caches button. Go to a page that has the search box on it, add some gibberish to the post, so it is lengthy, and then when you save and the page reloads you will see the search box sticking to the top of the page as you scroll down. On my test site it looks like this:

A nearly blank webpage with a search box in the upper left corner.


At first it seems like a lot more work but I can see how this opens up a lot of flexibility for developers. Once you get the hang of .yml files replacing .info files it begins to make a bit more sense. I think this is well worth it for the improved cache capabilities. I look forward to using D8 in production.

Caveat: I know you don’t modify core. I did it this way as I was exploring the D8 core codebase. If you want to do the above in production, do it in your own theme, not core.

Sample code: Replace your core bartik with this to see this completed example in action.


Leave a Reply

Your email address will not be published. Required fields are marked *