Updating themes to Drupal 8 #3 – Libraries and assets

Drupal 8’s beta version was released a few month ago and now it is time to start porting themes. In this series we are going to discuss  the most noteworthy changes in Drupal 8 about theming. Quite significant changes were introduced in the theme system between Drupal 8 and 7. This guide contains information that applies to Drupal 8 and refers sometimes to Drupal 7 in order to explain new concepts and approaches.

Adding stylesheets and Javascript

Drupal uses a high-level principle: assets (CSS or JS) are still only loaded if you tell Drupal it should load them. Drupal does not load all assets (CSS/JS) on all pages, because this is bad for front-end performance. This means that only the JavaScript required on a particular page will be added to that page. In particular, by default Drupal doesn’t need JavaScript on most pages that anonymous users can see. This means that jQuery is not automatically loaded on all pages anymore.
So, if your theme requires jQuery or some other JavaScript to be present (which also is defined in an asset library), you need to tell Drupal that this is the case, by declaring a dependency on the needed asset library.

Defining a library

To define one or more libraries, add a *.libraries.yml file to your theme folder. (If your theme is named my_theme, then the file name should be my_theme.libraries.yml). Each “library” in the file is an entry detailing CSS and JS files (assets), like this:

cuddly-slider:
  version: 1.x
  css:
    theme:
      css/cuddly-slider.css: {}
  js:
    js/cuddly-slider.js: {}
  dependencies:
    - core/jquery

Here we are defining a library where assuming that the javascript called cuddly-slider.js is located in the folder js and our stylesheet called cuddly-slider.css is in the folder css. This library requires jQuery and as we mentioned before Drupal doesn’t load libraries itself, so we have to tell Drupal we need jQuery and that is what we defined in dependencies. You can add more css files, javascript files and dependencies just writing them under in the right place. (Note that dependencies need a dash (-) before the library name)

The order in which assets will be loaded depends of the order that we specify them in the library declaration.

In Drupal 7, we used to be able to specify the media property (screen, print, all) as a subkey of the stylesheets property, now we can define it as a value for any given CSS asset. E.g.:

css/print.css: { media: print }

Attaching a library

Depending on which assets we need to have loaded, we’ll want to attach the corresponding asset library in a different way. After all, some asset libraries are needed on all pages, others only very rarely, and yet others on most, but not quite all.

Attaching to all pages

To attach a library to all the pages on the site that use our theme, we need to declare it in our theme’s *.info.yml file, under the libraries key:

name: My Theme
type: theme
core: 8.x
libraries:
  - my_theme/cuddly-slider

We can list as many libraries as we want, all of them will be loaded on every page.

Attaching a library to a subset of pages

In some cases, you do not need your library to be active for all pages, but just a subset of pages. For example, you might need your library to be active only when a certain block is being shown, or when a certain node type is being displayed.

A theme can make this happen by implementing a THEME_preprocess_HOOK() function in the .theme file, replacing “THEME” with the machine name of your theme and “HOOK” by the machine name of the theme hook.
For instance, if you want to attach JavaScript to the maintenance page, the “HOOK” part is “maintenance_page”, and your function would look like this:

<?php
function my_theme_preprocess_maintenance_page(&$variables) {
  $variables['#attached']['library'][] = 'my_theme/cuddly-slider';
}

You can do something similar for other theme hooks, and of course your function can have logic in it — for instance to detect which block is being preprocessed in the “block” hook, which node type for the “node” hook, etc.

Attaching configurable JavaScript

In some cases, you may want to add JavaScript to a page that depends on some computed PHP information.

In this case, create a JavaScript file, define and attach a library just like before, but also attach JavaScript settings and have that JavaScript file read those settings, via drupalSettings (the successor to Drupal 7’s Drupal.settings). However, to make drupalSettings available to our JavaScript file, we have to do the same work as we had to do to make jQuery available: we have to declare a dependency on it.

So that then becomes:

cuddly-slider:
  version: 1.x
  js:
    js/cuddly-slider.js: {}
  dependencies:
    - core/jquery
    - core/drupalSettings

And

<?php
function my_theme_page_attachments_alter(&$page) {
  $page['#attached']['library'][] = 'my_theme/cuddly-slider';
  $page['#attached']['drupalSettings']['my_theme']['cuddlySlider']['foo'] = 'bar';
}

Then cuddly-slider.js will be able to access drupalSettings.my_theme.cuddlySlider.foo(and it will === ‘bar’).

Attaching inline

Inline JavaScript is discouraged. It’s recommended to put the JS you want to use inline in a file instead, because that allows that JavaScript to be cached. However in some cases we can need to use inline.

<?php
function my_theme_page_attachments_alter(&$page) {
  $page['#attached']['css'][] = array( 'data' => $css, 'type' => 'inline');
}

Source: Drupal.org

Conclusion

Drupal doesn’t load assets or libraries itself until you declare that your theme tell it that it will need one, that is done through the declaration of dependencies in the key dependencies of the library declaration.

In the past, if you wanted to add CSS or JS to a particular page, you’d use the drupal_add_css() and drupal_add_js() functions, respectively. Not anymore! You now insert any JS/CSS assets in the #attached property of a render array.

We also make a look at how to attach configurable Javascript and CSS stylesheet inline (the last is more useful in module development).

In the next chapter we’ll talk about the new theme in Drupal 8 named Classy and make a simple post about how to use it as the base theme of our theme.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s