Drupal 8 is the most advanced Drupal ever built, and it will surely be a game changer among other CMSes out there. Part of its strength comes from adopting the principles from other technologies like Symfony, YAML, Twig, and Backbone.js.
The theming has undergone many changes since Drupal 7, especially the deep integration with Twig – a popular templating engine for PHP, which opens the door to more robust, scalable and secure themes.
Note that since Drupal 8 is still under active development, some of the details below may change prior to its release. Still, since Drupal 8 is now feature-frozen, hopefully, most info should remain relevant.
These are several things to note about the changes for theming in Drupal 8, and we will discuss each of these further in the next section:
Here is a screenshot of the basic folder structure for the theme:
This is the first file that you need to set up for your theme. This file is equivalent to the *.info file in Drupal 7, providing meta-data about your theme.
Consider this yaml code below:
name: YourTheme
description: 'A Cool theme by you.'
type: theme
package: Custom
base theme: classy
core: 8.x
screenshot: yourtheme.png
libraries:
- yourtheme/global-styling
regions:
header: ‘Header’
primary_menu: 'Primary menu'
secondary_menu: 'Secondary menu'
help: Help
page_top: 'Page top'
page_bottom: 'Page bottom'
featured_top: 'Featured top'
breadcrumb: Breadcrumb
content: Content
sidebar_first: 'Sidebar first'
sidebar_second: 'Sidebar second'
featured_bottom_first: 'Featured bottom first'
featured_bottom_second: 'Featured bottom second'
featured_bottom_third: 'Featured bottom third'
footer_first: 'Footer first'
footer_second: 'Footer second'
footer_third: 'Footer third'
footer_fourth: 'Footer fourth'
footer_fifth: 'Footer fifth’
These are the basic *keys *along with values that need to be provided:
name: YourTheme
description: 'A Cool theme by you.'
type: theme
package: Custom
base theme: classy
core: 8.x
screenshot: yourtheme.png
libraries:
libraries:
- yourtheme/global-styling
The libraries key can be used to add asset libraries — which can contain both CSS and JS assets — to all pages where the theme is active. From the example above, yourtheme is the name of the custom theme, followed by / (slash) and global-styling is the name of value to reference the library that we setup in the file of yourtheme.libraries.yml (will discuss further below).
Basically a container for the block that can be added.Above we see some basic key: ’value’ being defined. Taken from the example above: header is the region system name, and ‘Header’ is the name of the region that will display in the admin page.
WARNING: YAML has significant whitespace, so remember to check the INDENTATION. Otherwise, an error will occur.
This file contains references to the assets – notably is the CSS and JavaScript files that need to be loaded from your theme.
This is the basic setup of what could be contained in the *.libraries.yml file.
global-styling:
css:
theme:
css/styles.css: {}
css/layout.css: {}
css/print.css: { media: print }
js:
js/yourtheme.js: {}
js/custom-library.js: {}
dependencies:
- core/jquery
- core/drupal
custom-stuff:
css:
theme:
css/print.css: {}
css/another-style.css: {}
js:
js/yourtheme.js: {}
js/haha.js: {}
The global-styling and custom-stuff here can act as a container for the defined assets. And you’ve noticed that we have 2 containers of libraries here.
When you include the libraries in the *.info.yml (ie: yourtheme.info.yml) file, please note that the naming should be in this format:
libraries:
- yourtheme/global-styling
- yourtheme/custom-stuff
where yourtheme is the name of your custom theme followed by / (slash), and global-styling and custom-stuff is the name of the libraries that you want to include (see a. yourtheme.info.yml section above).
You can define as many containers as you need.
Each library’s container follows a similar pattern, as explained below:
css:
theme:
css/styles.css: {}
css/layout.css: {}
css/print.css: { media: print }
Above is a basic setup where we defined 3 css files, all of them located in the sub-folder called css under the yourtheme (see screenshot below for reference). The last one is set specifically to one type of media which is print.
js:
js/yourtheme.js: {}
js/custom-library.js: {}
JavaScript files are set up similarly to css files. Here we defined 2 javascript files located in the sub-folder of js under yourtheme (see screenshot below for reference).
Breakpoints are basically the point where a website will adjust the theme or layout based on the browser widths by using media query in css.
The purpose of this configuration file is to define the breakpoints for your custom theme, so other (contributed/custom) modules or/and theme that has features and/or functionality related with the breakpoints will be able to access the configuration and use it accordingly.
For example, with the Responsive image module, the module uses the breakpoints that are defined in the custom theme. Below is a screenshot of the admin page of the Responsive image module where you can specify Image styles based on the defined breakpoints in the custom theme.
In order to setup the breakpoints configuration, you need to create a file called yourtheme.breakpoints.yml, with basic code as shown below:
yourtheme.mobile:
label: mobile
mediaQuery: '(min-width: 0px)'
weight: 2
multipliers:
- 1x
yourtheme.narrow:
label: narrow
mediaQuery: 'all and (min-width: 560px) and (max-width: 860px)'
weight: 1
multipliers:
- 1x
yourtheme.wide:
label: wide
mediaQuery: 'all and (min-width: 851px)'
weight: 0
multipliers:
- 1x
Each section represents one breakpoint, which consists of a unique machine name (i.e., yourtheme.mobile,* yourtheme.narrow*,* yourtheme.wide*), with properties explained below:
label
mediaQuery
weight
multipliers
For more info about breakpoints configuration for a custom theme, please refer to this page.
This file contains the hook**preprocess to alter or make a modification to the theme. This file serves the same purpose as *template.php *in Drupal 7.
Below is a simple example of code on how to add custom assets library to our custom theme.
function yourtheme_preprocess_page(&$variables) {
$variables['#attached']['library'] = array('yourtheme/global-styling', 'yourtheme/custom-stuff');
}
As you can see we use hook_preprocess_page(), and we add global-styling and custom-stuff via the #attached library array that comes from $variables.
Another significant change introduced in Drupal 8 is the use of the popular PHP templating engine Twig, to replace the PHPTemplate-based theme system in Drupal 7.
For example, if you used to have page.tpl.php in Drupal 7, it has now been replaced by page.html.twig in Drupal 8.
For the sake of easy management, Twig template files are put under the templates sub-directory from your custom theme.
Here is a list of possible Twig template files that are available in Drupal 8 by default.
HTML (template)
Page template
Regions
Blocks
Nodes
Taxonomy terms
Fields
Comments
Forums
For forum containers:
For forum topics:
Maintenance page
Search result
In terms of coding, Twig template files in Drupal 8 are not much different to PHPTemplate files in Drupal 7. In both cases, you’re essentially writing HTML. The difference is how you define variables and define conditional logic within it.
Here are some examples:
Docblock
PHPTemplate
<?php
/** * @file * File description */
?>
Twig
{#
/** * @file * File description */
#}
Variables
Printing a variable:
PHPTemplate:<div class="content"><?php print $content; ?></div>
Twig:<div class="content">BlogPost 170838076594 Deep Dive into the Anatomy of Drupal 8 Theming</div>
Printing a hash key item:
PHPTemplate:<?php print $item['#item']['alt']; ?>
Twig:
Assigning a variable:
PHPTemplate:<?php $custom_var = $content->comments; ?>
Twig:
Assigning an array:
PHPTemplate:<?php $args = array('!author' => $author, '!date' => $created); ?>
Twig:
Conditionals:
PHPTemplate:<?php if ($content->comments): endif; ?>
Twig:
PHPTemplate:<?php if (!empty($content->comments)): endif; ?>
Twig:
PHPTemplate:<?php if (isset($content->comments)): endif; ?>
Twig:
PHPTemplate:<?php if ($count > 0): endif; ?>
Twig:
Control structures:
PHPTemplate:<?php foreach ($users as $user) {} ?>
Twig:
Filters:
Check_plain:
PHPTemplate:<?php print check_plain($title); ?>
Twig:
Translate:
PHPTemplate:<?php print t('Home'); ?>
Twig:
Translate with substitutions:
PHPTemplate:<?php print t('Welcome, @username', array('@username' => $user->name)); ?>
Twig:
For more examples, please refer to the Twig homepage.
And that wraps it up! That should be enough to know about the basic changes to theming in Drupal 8, and enough to get you started on your own exploration and experimentation.
X-Team is hiring Drupal developers! Click here to learn how to join the league of the extraordinary.
References: