Skip to main content

In our earlier article, we had a solid understanding of Drupal 8 theming. In this post, we're going to dig into the theming fundamentals, files for styles, JS, CSS, library, Twig templates , adding new regions, attach the library to all the pages and working with breakpoints in Drupal 8 development.

Creating a Drupal 8 sub-theme

Sub-themes are just like any other theme, with one difference: they inherit the parent theme's resources. There are no limits on the chaining capabilities connecting sub-themes to their parents. A sub-theme can be a child of another sub-theme, and it can be branched and organized however you see fit. This is what gives sub-themes great potential.

To create a sub-theme you define your theme like any other theme and declare the base theme using the "base theme" key. Note that the key has no underscore.

Create an .info.yml file

To create a Drupal 8 theme you need to first create a file that provides meta-data about your theme to Drupal. This is similar to how modules and installation profiles are being defined, and as such it is important to set the 'type' key in the .info.yml file to 'theme' in order to differentiate it.

If your theme is named “Flower" then the folder is named “flower/" and the .info.yml file is named "flower/"

name: Flower
type: theme
description: 'A flower theme that offers extra fluffiness.'
package: Custom
core: 8.x
  - flower/globalstyling
  - '@classy/css/layout.css'
  - core/assets/vendor/normalize-css/normalize.css
  header: Header
  content: Content
  sidebar_first: 'Sidebar first'
  footer: Footer

Folder Structure

In Drupal 8, we can use the "themes" folder to add a new theme. You should note that Drupal core themes such as Bartik and Seven are located in the core/themes folder of your installation.

The best practice is to place the contributed themes in a sub folder named "contrib" and your own themes in a folder named "custom".

Here are some examples of files and folders that are structured in the new theme folder structure:

 |  |-install
 |  |  |-flower.settings.yml
 |  |-schema
 |  |  |-flower.schema.yml
 |  |-style.css
 |  |-flower.js
 |  |-buttons.png
 |  |-maintenance-page.html.twig
 |  |-node.html.twig

Twig in Drupal 8

Twig is a template engine for PHP and it is part of the Symfony2 framework. One of the results of this change is that all of the theme_* functions and PHPTemplate based *.tpl.php files have been replaced in by *.html.twig template files. Learn how to use the twig template engine in Drupal 8.

Adding Regions to a Theme

Adding region meta-data to your file
- Editing your page.html.twig file and printing the new regions

Declaring any new regions in your file. Regions are declared as children of the regions key like so:

# Regions
  header: 'Header'
  content: 'Content'
  footer: 'Footer'


header: 'Header'
Will become:

{{ page.header }}

In your Twig templates.

Adding (CSS) and JavaScript (JS) to a Drupal 8 theme

In Drupal 8, stylesheets (CSS) and JavaScript (JS) are loaded through the same system for modules (code) and themes.

Defining a library

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

Defining JS files

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

Defining CSS file

Defining CSS file
  version: 1.x
      css/layout.css: {}
      css/style.css: {}
      css/colors.css: {}
      css/print.css: { media: print }

Attaching a library file

  • Attaching a library to All page(s)

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

    name: Flower
    type: theme
    core: 8.x
      - flower/cuddly-slider

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

  • Attaching a library to a subset of pages :

    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:

        function flower_preprocess_maintenance_page(&$variables) {
           $variables['#attached']['library'][] = 'flower/cuddly-slider';

Including Default Image Styles With Your Theme

The process for including an image style in your theme is similar to that of including default configuration in a module.

  • Create the Image Style you wish to include using the UI
  • Export the Image Style as YAML
  • Include the exported YAML in the config/install directory of your theme following the appropriate naming convention.
  • Start by creating an image style using the admin UI at Configuration > Image Styles (admin/config/media/image-styles). Once the image style has been created and saved, the configuration that makes up that image style will be stored in your site's active config.

This configuration can be exported using:

  • Single import/export tool at Configuration > Configuration management > Single Import/Export > Export (admin/config/development/configuration/single/export).
  • From the configuration type select list choose "Image style" then choose your image style from the configuration name select list.

Example: flower/config/install/

langcode: en
status: true
dependencies: {  }
name: black_white
label: 'black & white'
    uuid: 8d4f85cc-9a2d-4a30-af15-21b0833dc06d
    id: image_desaturate
    weight: 1
    data: {  }
third_party_settings: {  }

Working with breakpoints in Drupal 8

Breakpoint's properties

  • label - A human readable label for the breakpoint.
  • mediaQuery - Media query text proper all and (min-width: 851px).
  • weight - Positional weight (order) for the breakpoint.
  • multipliers - Supported pixel resolution multipliers.

Example: flower.breakpoints.yml
label: mobile
mediaQuery: ''
weight: 2
    - 1x
  label: narrow
  mediaQuery: 'all and (min-width: 560px) and (max-width: 850px)'
  weight: 1
    - 1x
  label: wide
  mediaQuery: 'all and (min-width: 851px)'
  weight: 0
    - 1x

I hope this Drupal 8 theming guide illuminates the fundamentals of getting a theme started so that you can use it for Drupal projects.

People are familiar with a Drupal theme and one of the first thing any Drupal developer need to understand how to apply the new tools and techniques to build a Drupal theme from scratch.

Getting started with a Drupal theme

  • Themes allow you to change the look and feel of your Drupal site 
  • Use contributed themes or create a new theme from scratch and share with the community
  • Create a sub-theme of an existing theme. A sub-theme inherits a parent theme's resources

Do more with a Drupal theme

  • Change layouts, regions, images and fonts
  • Hide or display fields dependent on user role
  • Dynamically respond to changes in the content, or to user input
  • Modify or replace text (e.g., labels or attributes) and variables generated by modules
  • Convert any website layout or template into a Drupal theme

Drupal 8 Theming

  • Defining a theme with an .info.yml file
  • Theme folder structure
  • Twig in Drupal 8
  • Adding Regions to a theme
  • Adding stylesheets (CSS) and JavaScript (JS) 
  • Creating a Drupal 8 sub-theme
  • Include default image styles with your theme
  • Use attributes in templates
  • Working with breakpoints in Drupal 8

Theming differences between Drupal 6, 7 & 8

Here are the most noteworthy changes in Drupal 8 that affect theming:

  • Drupal 8 outputs semantic HTML5 markup by default (see Drupal 8 HTML5 Initiative), compared to XHTML in Drupal 6 and 7.
  • Besides jQuery v2.x Drupal 8 now includes more front-end libraries such as  Modernizr, Underscore.js and Backbone.js.
  • Drupal 8's core RDFa  module outputs markup
  • outputs markup
  • Drupal 8 has improved accessibility making extensive use of WAI-ARIA attributes.
  • Drupal 8 introduces Twig, which replaces PHPTemplate as the default theme engine. This means the theme_* functions and PHP-based *.tpl.php files have been replaced by *.html.twig templates ()
  • Drupal 8 enables by default features that improve performance such as CSS and JavaScript aggregation.
  • Drupal 8 ships with new UI elements that you use in your own admin screens, including modal dialogs and drop buttons
  • Drupal 8 ships with responsive features such as responsive themes, toolbar, images, and tables
  • In Drupal 6 and 7 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. This is now replaced byinsert any JS/CSS assets in the #attached property of a render array
  • Drupal 8 drops support for IE 6, 7 and 8, enabling the use of jQuery 2.0 and other code that assumes modern HTML5/CSS3 browser support.
  • Drupal 8 does not support browsers that do not support SVG (including IE8 and Android Browser 2.3)
  • Drupal 8 contains less IDs than Drupal 7's CSS
  • Drupal 8's CSS (file) structure is based on SMACSS & BEM
  • Drupal 8's CSS uses CSS3 pseudo selectors
  • Drupal 8 ships with Classy, a core base theme that injects classes into markup, and includes corresponding CSS. In progress: This will replace many pre-process functions and CSS files which were previously included in core modules
  • Drupal 8 moves CSS classes from pre-process functions to Twig templates
  • Drupal 8 uses breakpoint media queries to control how the site looks on different devices

After you have grasped some basic ideas about your template folder, its files, and the layout of your theme, let's move on to create a Drupal 8 theme in future posts in this series. Join the conversation by commenting below with any questions or feedback on using Drupal 8 theme for your project.

Subscribe to Drupal 8 Responsive Themes