Each theme is a collection of files that define a presentation layer for Drupal. While only a THEMENAME.info.yml file is required, most themes will contain other files as well. Some are Drupal-specific, and need to follow a strict naming convention and be placed in the appropriate place for Drupal to find them. Others are standard front-end web assets like CSS, JavaScript, and image files that can be placed anywhere within the theme's code.
In this tutorial we'll learn about:
- The various types of files you can expect to find in a theme directory
- Where in the Drupal code base your theme directory should live
- Keeping the directory and all the files within organized
By the end of this tutorial you should be able to explain where a Drupal theme should be placed in a project's code base, and the types of files one can expect to find in a theme.
Custom themes in Drupal must be configured to inherit settings, templates, and other assets from a parent theme. Which base theme you use is configurable. This allows theme developers to use a different set of markup as the starting point for their theme, organize various theme assets into a more maintainable structure, and more. All of this is made possible because of how Drupal's theme layer uses a chain of inheritance when assembling all the parts of a theme.
Base themes are also a powerful way to encapsulate standards and best practices into a reusable code base. You'll find dozens of contributed base themes on Drupal.org that can serve as a great starting point, especially if you're planning to work with an existing design framework like Bootstrap or Susy Grids. Or if you want to leverage modern JavaScript bundling without setting up Webpack on your own.
In this tutorial we'll:
- Learn what base themes and subthemes are
- Look at a few examples of template inheritance and how that works
- Discuss some use cases for theme inheritance
By the end of this tutorial you'll know how to declare the base theme that your theme builds upon.
One important aspect of theme administration is the configuration of global and theme-specific settings. In this tutorial, you will learn where theme settings are configured in Drupal's administrative interface, the difference between global and theme-specific settings, and what each global setting refers to on a base installation of Drupal with a custom theme installed.
Sometimes your JavaScript needs to insert new strings into the user interface. In order to ensure that those user-facing strings can be translated into other languages, just like the rest of Drupal's user interface, you should make sure and use the Drupal.t
function anytime you output a string of text.
If you want to create a link to an internal page in a Twig template--and there's not already a variable in the template that contains the URL you want to link to--you'll need to determine the route of the thing you want to link to and then use the Twig url()
or path()
functions to generate appropriate URLs. In most cases when you want to create a link to an entity that is being output by the current template there's an existing helper variable to use. For example, in a node.html.twig template file there's a url
variable that points to the current node. For other scenarios, like hard-coding a link to the /about page, you'll need to do a little more work.
In this tutorial, we'll:
- Get the absolute URL value
- Get the relative path value
- Generate HTML for a link
- Get the URI to a file, like an image in the Media library
- Get the active theme path
By the end of this tutorial you should be able to create links to any internal page via Twig.
Twig is the default template engine for Drupal. If you want to make changes to the markup that Drupal outputs you're going to need to know at least some Twig. In this tutorial, we will outline the role that Twig now plays in Drupal, how Twig impacts the theming experience, and where to find additional resources for learning Twig.
At the end of this lesson, you'll be able to:
- Describe the role that Twig plays in creating Drupal themes
- Explain how Twig impacts the theming experience in Drupal
- Locate additional resources for learning Twig
In Twig, you can modify variables using functions or filters. Twig has a bunch of built-in functions and filters. Drupal extends Twig to provide a few handy Drupal-specific functions and filters as well.
In this tutorial, we'll look at:
- What are functions and filters?
- How to use functions and filters in Twig
- Detailed information about the Drupal-specific functions and filters and their use case
To read a Twig template file, you'll need to recognize Twig's syntax delimiters. Twig has three syntax delimiters: one for printing out variables, another for performing actions or logic, and lastly, one for comments, also used for docblocks.
In this tutorial we'll:
- Explore each of Twig's 3 syntax delimiters.
- Show examples of each from Drupal's core template files.
By the end of this tutorial you should be able to recognize each of Twig's syntax delimiters and understand what the engine will do when it encounters them.
More often than not, templates in a theme share common elements: the header, footer, sidebar, or more. In Drupal, themes created with a Twig template can be decorated by another one. This template inheritance allows you to build a base "layout" template that contains all the common elements of your layout defined as blocks. A child template can extend the base layout and override any of its defined blocks. This helps prevent code duplication, and keeps your theme more organized.
This tutorial is for theme developers who want to reduce code duplication in their themes, or anyone seeking to better understand how Twig template inheritance works. We'll cover:
- What the Twig
block
andextends
tags do - An example use-case for template inheritance
- How to extend a Twig template from another theme or module
- How to include other Twig templates
Do you cringe at the sight of untidy whitespace or (gasp) no whitespace at all when you View Source? Learn how to tame whitespace in Twig template files in this tutorial. By the end of this lesson, you will be able to recognize how Twig controls whitespace and how you can do the same in your Drupal template files.
The Drupal core Media Library module provides an enhanced user interface for locating Media entities and attaching them to an article. It's a drop-in replacement for the default entity reference widget which uses a not very intuitive autocomplete field. Using the Drupal core Media Library module requires minimal configuration.
If you want to provide content creators with a gallery-like library of Media entities that they can browse through in order to find the ones they want to add to their content, the Media Library is the easiest way to do it. It can be configured to work with both Media fields and the CKEditor powered WYSIWYG editor commonly used for editing the body field of Drupal nodes. There's really no reason not to use it.
In addition to providing a better UI for locating existing Media entities, the Media Library provides a way to create new Media entities right from the content creation form. This prevents an otherwise confusing requirement where Media entities need to be created, via a different set of forms, before they can be used.
In this tutorial we'll:
- Install and configure the Media Library module to work with Media fields
- Use the user interface provided by the Media Library to improve the experience of finding and selecting Media entities to associate with a piece of content
By the end of this tutorial you'll know how to replace the default entity reference widget used for selecting Media entities with the much improved Media Library UI.
Media entities, like any content entity, work great with all the different features Drupal provides for changing the way things are displayed: view modes, Layout Builder, theme templates, and more. We're big fans of using view modes to create a component-like design system where entity types have view modes representing the different context in which they're displayed. Then we theme the view modes. This works great for displaying Media entities associated with a page and for changing the way that Media assets are displayed within the Media Library browser.
In this tutorial we'll:
- Create Hero and Sidebar view modes for Media entities
- Configure the Image Media type to use the new view modes and style each one differently
- Use the new view modes to render Image Media assets within a Layout
- Update the Media library view mode that's used by the Media Library browser to display additional information alongside the thumbnails used when selecting Media to attach to a page
By the end of this tutorial you should be able to change the way that Media assets are displayed by using view modes and display formatters in a Drupal site.
Render API Overview
FreeThe Render API consists of two parts: structured arrays that provide data and hints about how that data should be rendered, and a rendering pipeline that can be used to render these arrays into various output formats. Understanding at least the basics of how the Render API works, the difference between elements and properties, and the concept of callback functions is an integral part of learning Drupal.
In this tutorial we'll:
- Look at the fundamentals of the Drupal Render API
- Point to additional material to provide more detail about the inner workings of the Render API and how content is output in Drupal
The core structure of Drupal's Render API is the render array, which is a hierarchical associative array containing data to be rendered and properties describing how the data should be rendered. As a module developer you'll use render arrays to describe the content your module controls in order to output it on a page as HTML, or as part of a response in another format like JSON. As a theme developer, you'll manipulate render arrays in order to affect the way content is output on the page.
In this tutorial we'll learn:
- What render arrays are and why they exist
- The basic format of a render array
- What "properties" and "elements" signify in the context of a render array
- Where to find more information about how to create a render array to describe your own content
By the end of this tutorial you should be able to understand when you need to use a render array, recognize one when you see it, and know where to get more detailed information about render array formatting specifics.
One of the central components of Drupal's Render API is render elements. You can think of them as prepackaged render arrays or shortcuts you can use to describe common things, like tables, links, and form elements, in a consistent way. In this tutorial we'll take a more in-depth look at the use of the #type
property in render arrays in order to answer questions like:
- What are render elements, and what is their use case?
- Where can I find more information about available element types?
By the end of this tutorial you should be able to identify individual render element types within a larger render array, find the relevant documentation for specific types of render elements, and explain the use case for render elements.
In this tutorial we'll look at how you can use the #theme
property of a render array to define custom HTML. With this information, module developers can use render arrays to define content, and theme developers can understand how elements in a render array are converted to HTML and which templates they can override to change the output for a specific element.
Learn how to:
- Use
hook_theme()
to define a new theme hook and define default values for variables - Create a corresponding Twig template file that outputs the variables and any custom HTML markup
- Use a preprocess function to add additional variables for the Twig template file you created
- Use the new theme hook in conjunction with a
#theme
property in a render array to link your Twig template file to actual content
By the end of this tutorial you should know how to define new templates to output content as HTML. You should also have a better understanding of how Twig template files are linked to elements in a render array.
Set up a local development environment to practice Drupal theme development. In order to practice theme development, either on your own or following our Hands-On: Theming guide, you'll need a Drupal site up and running on your computer.
By the end of this tutorial, you should be able to:
- Install Drupal on your computer so you can modify files with a code editor of your choice.
- Generate dummy content so that you have different kinds of pages to theme.
It's time to create the bare-bones structure for a new theme on your site. You should try to complete this exercise based on the information you've learned in this chapter. The video included will walk you through the implementation of this exercise if you need some help. In this exercise you will need to:
- Create an info file that describes a custom theme to Drupal with the regions listed below (we're going to name ours "reboot").
- Enable, and view, a bare-bones custom theme.
Regions:
'Header' (header)
'Primary menu' (primary_menu)
'Secondary menu' (secondary_menu)
'Page top' (page_top)
'Page bottom' (page_bottom)
'Highlighted' (highlighted)
'Featured top' (featured_top)
'Breadcrumb' (breadcrumb)
'Content' (content)
'Sidebar first' (sidebar_first)
'Sidebar second' (sidebar_second)
'Footer first' (footer_first)
'Footer second' (footer_second)
Note: At the end of this exercise, you'll find a video walk-through of the solution.
You can accomplish a lot without needing to change any markup by adding CSS and JavaScript files to your theme. In this exercise you'll create 2 asset libraries and add them to your theme. Specifically, we want to pull in the CSS and JavaScript from the popular Bootstrap framework so that we can make use of its layout utility classes later on. We'll also add a custom CSS file that contains global styles for our site, like setting the page background color.
If you want to try and complete this on your own first you'll need to:
- Add the Bootstrap CSS and JavaScript files to your theme.
- Define an asset library using a THEMENAME.libraries.yml file in your theme.
- Tell Drupal to attach your asset library so that the CSS and JavaScript files it represents are included in the page.
Once that's done your site won't look all that different. But if you view the page source, or look closely, you should see that the Bootstrap files are included along with any CSS rules you placed into your custom style sheet.
Note: Since this course if focused on teaching the Drupal aspects of theme development, and not on writing CSS, we use the Bootstrap CSS. If you don't need it for your project though you can skip it, or add the CSS framework that you want to use instead.
You should try to complete the exercise steps on your own and use the video to help guide you if you get stuck.
Note: At the end of this exercise, you'll find a video walk-through of the solution.
Drupal has a few handy settings you can tweak to make developing themes a little more intuitive and a lot more awesome. This includes disabling some of the caching that Drupal does so you don't need to clear the cache as frequently. We'll also turn off CSS and JS aggregation in a settings file (overriding anything set on the Performance configuration form) so you can see your changes to .js and .css files with just a page refresh. Finally, turning on the Twig debug service will give us some additional contextual information about the templates being used when we view the source code of any page on our site. Walk through the exercise steps, and if you get stuck you can watch the video to see how we implemented this.
If you want to try and complete this on your own you'll need to:
- Make changes to your site's settings.php file. Hint: check out the example.settings.local.php file included with core.
- Modify configuration via a services.yml file. Hint: check out the default.services.yml file included with core.
Once this is done, if you view the source of any page on your Drupal site you should see extra HTML comments with helpful information about which template file was used to generate a section of markup.
Example:
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'node' -->
<!-- FILE NAME SUGGESTIONS:
* node--view--frontpage--page-1.html.twig
* node--view--frontpage.html.twig
* node--2--teaser.html.twig
* node--2.html.twig
* node--page--teaser.html.twig
* node--page.html.twig
* node--teaser.html.twig
x node.html.twig
-->
<!-- BEGIN OUTPUT from 'themes/icecream/templates/node.html.twig' -->
Note: At the end of this exercise, you'll find a video walk-through of the solution.