SlideShare a Scribd company logo
8 Things to Know About
Theming in Drupal 8
Or, “Lessons I Learned when Building a D8 Subtheme”
Logan Farr || LoganFarr.com || @logan_farr || @loganfarr
Site building
Object oriented programming
Module building
Hooks and API functions not
normally in theming.
JavaScript frameworks
Things we will not
be covering.
Constructing a Drupal 8 (sub)theme
How a Drupal 8 theme works
Templating and Twig*
Template preprocessing and theme functions
What the (theme) differences are between D7 and D8
Tools to debug a theme
Things we will be covering
1.File structures have changed
D8 Base Path
D8 Theme
2. File types have changed
THEME_NAME.info -> THEME_NAME.info.yml
template.php -> THEME_NAME.theme
hook_template.tpl.php -> hook_template.html.twig
dcu.info
name = DCU
description = An example theme for Drupal Camp Utah
base theme = Omega
screenshot = screenshot.png
engine = phptemplate
core = 7.x
stylesheets[all][] = css/dcu.styles.css
scripts[] = js/dcu.behaviors.js
regions[content] = Content
...
dcu.info.yml
name: DCU
type: theme
description: An example theme for Drupal Camp Utah
base theme: Omega
engine = phptemplate
screenshot: screenshot.png
core: 8.x
libraries:
- dcu/global-styling
#Regions
regions:
navigation: Navigation
header: Header
content: Content
machine_readable: Human Readable
stylesheets-remove:
- core/assets/vendor/normalize-css/normalize.css
3. stylesheets-remove
You can prevent stylesheets from rendering on your page!
In THEME_NAME.info.yml:
stylesheets-remove:
- (path to stylesheet here)
- core/assets/.../normalize.css
Note: You need the FULL path of the CSS stylesheet (from the root directory).
Especially useful if:
● Trying to remove default module
styling
● Trying to remove unnecessary
system stylesheets
● Trying to remove a base theme
stylesheet
4. Libraries
Probably the most notable change in Drupal 8.
Define library:
A collection of CSS stylesheets and JS scripts
Can be used globally, or just as needed.
Library Naming (NOT file naming):
THEME_NAME/LIB_NAME
dcu/global-styling
dcu.libraries.yml - Overview
global-styling: #LIBRARY_NAME
version: 1.x
css:
theme:
styles/css/style.css {}
styles/css/print.css { media: print }
js:
js/script.js {}
header:
js/header.js {}
dependencies:
core/jquery
sessions: #LIBRARY_NAME
...
(Yes, jQuery is now included in Core!)
dcu.libraries.yml - CSS
D8 dcu.info.yml:
global-styling:
version: 1.x
css:
theme:
styles/css/style.css {}
styles/css/print.css { media: print }
D7 dcu.info:
stylesheets[all][] = css/global.styles.css
stylesheets[all][] = css/responsive.styles.css
stylesheets[all][] = css/print.css
dcu.libraries.yml - JS
D8 dcu.info.yml:
global-styling:
...
# By default, all JS is loaded in the footer
js:
js/script.js: {}
# But it can be overridden!
js-header:
header: true
js:
js/header.js: {}
js-footer:
js:
js/footer.js: {}
D7 dcu.info:
scripts[] = js/script.js
Attaching a Library to a Page
Options for loading a library:
● Every page
● A subset of pages
● Individual templates
(Remember, THEME_NAME/LIBRARY_NAME is how you reference a library)
To load a library on every page, place in your THEME_NAME.info.yml file.
To load a library on a subset of pages:
<?php
function dcu_preprocess_maintenance_page(&$variables) {
$variables['#attached']['library'][] = dcu/sessions';
}
?>
To load on a Twig template:
{{ attach_library('dcu/sessions') }}
You can override a library and remove a library with the commands
library-override
library-remove
Another note about libraries...
5. Don’t mess up your YML.
If you are developing a theme and you get a WSOD or a 500 error, it’s because you have messed up
YML code.
Use spaces, not tabs
Don’t forget your colons (also forget your semi-colons)
Use colons not equal signs
Follow indentation
6. The Themer’s Best Friend
Twig debugging!
To turn on, edit settings.php and services.yml
sites/default/settings.php
$settings['twig_debug'] = TRUE;
$settings['container_yamls'][] = __DIR__ . '/services.yml';
sites/default/services.yml
parameters:
twig.config:
debug: true
Thanks to Derek Walker (@derekawalker) for helping me out with this.
Also Devel - although a note: the
dpm() function is now kint()
Twig Debug, Turned OFF
Twig Debug, Turned ON
<!-- THEME DEBUG -->
<!-- THEME HOOK: ‘page’ →
<!-- FILE NAME SUGGESTIONS:
x page--page.html.twig
* page--front.html.twig
* page.html.twig
-->
<!-- BEGIN OUTPUT FROM
‘themes/dcu/templates/page--page.html.twig’ -->
(HTML HERE)
Functions now done in THEME_NAME.theme!
Some functions are different though.
For example, to add template suggestions to a page, use
hook_theme_suggestions_HOOK_alter().
Preprocess functions, like in D7, are used to pass variables to the page (Twig) templates.
7. Preprocess Functions are still a thing
Example Functions in dcu.theme
/**
* Implements hook_preprocess_HOOK().
*/
function dcu_preprocess_page(&$variables) {
$variables[‘title’] = ‘Come to the dark side.’;
$variables[‘page_class’] = ‘page-dark-side’;
kint();
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function dcu_theme_suggestions_page_alter(array &$suggestions, array $variables) {
if ($node = Drupal::routeMatch()->getParameter('node')) {
$suggestions[] = 'page__' . $node->getType();
}
return $suggestions;
}
8. Templates are now done in Twig (not PHP)
<section id="content-outer-wrapper" class="outer-wrapper clearfix">
<div id="main-layout" class="{{ region_classes.main }}
inner-wrapper clearfix">
{% if page.content %}
{{ page.content }}
{% endif %}
{% if page.sidebar_first %}
{{ page.sidebar_first }}
{% endif %}
{% if page.sidebar_second %}
{{ page.sidebar_second }}
{% endif %}
</div><!-- /#main -->
</section><!-- /#main-outer-wrapper -->
<div class="l-main-wrapper">
<div class="l-main">
<div class="l-content" role="main">
<a id="main-content"></a>
<?php print render($tabs); ?>
<?php print render($page['help']); ?>
<?php if ($action_links): ?>
<ul class="action-links">
<?php print render($action_links); ?>
</ul>
<?php endif; ?>
<?php print render($page['content']); ?>
</div>
<?php print render($page['sidebar_first']); ?>
<?php print render($page['sidebar_second']); ?>
</div>
</div>
Twig Reference & PHP Equivalent
{{ twig_variable }}
{% if twig_variable %}
{% elseif twig_variable %}
{% else %}
{% endif %}
{% for i in 0..10 %}
{{ i }}
{% endfor %}
echo $php_variable;
if($boolean)
else if($boolean)
else
for($i = 0; $i < 10; $i++) {
echo $i;
}
Twig reference to come soon…
Twig Variables & Preprocess Functions
<body class=”{{ page_class }} main”>
<h1>{{ title }} It’s awesome.</h1>
...
</body>
<body class=”page_dark_side main”>
<h1>Come to the dark side. It’s
awesome.</h1>
...
</body>
Twig Loops and PHP Arrays
<?php
function dcu_preprocess_page(&$variables) {
$variables[‘sessions’] = array(
‘auditorium’ => array(
‘title’ => ‘Drupal 8 Theming’,
‘time => ‘11:15 AM’,
),
‘room_b’ => array(
‘title’ => ‘Drulenium’,
‘time’ => ‘11:15 AM’,
),
);
}
?>
{% for session in sessions %}
{{ session.title }} at {{ session.time }}
{% endfor %}
Helpful note: {{ variable_name.key }} for array
elements
Drupal 8 Theming Fundamentals, Part 1
https://www.lullabot.com/articles/drupal-8-theming-fundamentals-part-1
Drupal 8 Assets Theming Guide
https://www.drupal.org/theme-guide/8/assets
Classy Theming by Morten DK
https://drupalwatchdog.com/volume-5/issue-1/classy-theming
My Drupal 8 Omega Subtheme “Resistor” (as reference material)
https://github.com/loganfarr/Resistor
Barcelona DrupalCon - Drupal 8 Theming
https://events.drupal.org/barcelona2015/sessions/drupal-8-theming-0
MortenDK’s Los Angeles DrupalCon Session - Drupal 8 Theming with <3
https://events.drupal.org/losangeles2015/sessions/drupal-8-theming
Twig Reference (Coming Soon)
https://loganfarr.com/twig
This presentation + extended examples (Also coming soon)
https://loganfarr.com/d8-theming
Additional Reading Material
Now go build a
Drupal 8 theme.

More Related Content

PDF
Building a Custom Theme in Drupal 8
PDF
Drupal 8: Theming
PDF
Drupal 8 theming deep dive
PPTX
Converting (X)HTML/CSS template to Drupal 7 Theme
PDF
Drupal 8 templating with twig
PPT
PSD to a Drupal Theme (using a base theme)
PDF
Absolute Beginners Guide to Drupal
PPTX
One-hour Drupal 8 Theming
Building a Custom Theme in Drupal 8
Drupal 8: Theming
Drupal 8 theming deep dive
Converting (X)HTML/CSS template to Drupal 7 Theme
Drupal 8 templating with twig
PSD to a Drupal Theme (using a base theme)
Absolute Beginners Guide to Drupal
One-hour Drupal 8 Theming

What's hot (19)

PDF
Drupal 8 - Corso frontend development
KEY
Grok Drupal (7) Theming (presented at DrupalCon San Francisco)
PDF
Drupal theming - a practical approach (European Drupal Days 2015)
PDF
Design to Theme @ CMSExpo
PPTX
Getting started with drupal 8 code
PDF
Introduction to Drupal (7) Theming
PDF
Grok Drupal (7) Theming
PDF
Drupal 7 Theme System
PDF
Intro to Theming Drupal, FOSSLC Summer Camp 2010
PPTX
A look at Drupal 7 Theming
PDF
Grok Drupal (7) Theming - 2011 Feb update
PDF
Drupal 8: Entities
PDF
Learning PHP for Drupal Theming, DC Chicago 2009
PDF
Drupal 8 Theme System: The Backend of Frontend
PPTX
The Way to Theme Enlightenment 2017
PDF
Drupal 8: Routing & More
PDF
Performance on a budget (European Drupal Days 2015)
PDF
Drupal 8: Forms
PDF
D7 theming what's new - London
Drupal 8 - Corso frontend development
Grok Drupal (7) Theming (presented at DrupalCon San Francisco)
Drupal theming - a practical approach (European Drupal Days 2015)
Design to Theme @ CMSExpo
Getting started with drupal 8 code
Introduction to Drupal (7) Theming
Grok Drupal (7) Theming
Drupal 7 Theme System
Intro to Theming Drupal, FOSSLC Summer Camp 2010
A look at Drupal 7 Theming
Grok Drupal (7) Theming - 2011 Feb update
Drupal 8: Entities
Learning PHP for Drupal Theming, DC Chicago 2009
Drupal 8 Theme System: The Backend of Frontend
The Way to Theme Enlightenment 2017
Drupal 8: Routing & More
Performance on a budget (European Drupal Days 2015)
Drupal 8: Forms
D7 theming what's new - London
Ad

Similar to 8 things to know about theming in drupal 8 (20)

PDF
Drupal 8: frontend development
PDF
Designing with Drupal 8
PDF
PPTX
Theming in Drupal 8 (everything)
PDF
Twig & D8 - DrupalCamp Baltics 2013 - Tallinn
PDF
Drupal 8: Theming. Lviv Drupal Cafe #4
PDF
Drupal 8 what to wait from
PDF
Building your first d8 theme
PDF
Drupal8 themingdeepdive drupaldevdays-montpellier17042015
ODP
Drupal Theme Development - DrupalCon Chicago 2011
PDF
Drupal 8 - Core and API Changes
PDF
Twig for Drupal 8 and PHP | Presented at OC Drupal
PDF
Terrific Composer Workshop
PDF
Drupal 8 deeper dive
KEY
Twig for Drupal @ Frontendunited Amsterdam 2012
PPTX
Drupal Camp Porto - Developing with Drupal: First Steps
PDF
Default theme implementations: a guide for module developers that want sweet ...
PPT
SynapseIndia drupal presentation on drupal best practices
PDF
What's new in D7 Theming?
PPTX
Top 8 Improvements in Drupal 8
Drupal 8: frontend development
Designing with Drupal 8
Theming in Drupal 8 (everything)
Twig & D8 - DrupalCamp Baltics 2013 - Tallinn
Drupal 8: Theming. Lviv Drupal Cafe #4
Drupal 8 what to wait from
Building your first d8 theme
Drupal8 themingdeepdive drupaldevdays-montpellier17042015
Drupal Theme Development - DrupalCon Chicago 2011
Drupal 8 - Core and API Changes
Twig for Drupal 8 and PHP | Presented at OC Drupal
Terrific Composer Workshop
Drupal 8 deeper dive
Twig for Drupal @ Frontendunited Amsterdam 2012
Drupal Camp Porto - Developing with Drupal: First Steps
Default theme implementations: a guide for module developers that want sweet ...
SynapseIndia drupal presentation on drupal best practices
What's new in D7 Theming?
Top 8 Improvements in Drupal 8
Ad

Recently uploaded (20)

PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Big Data Technologies - Introduction.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Encapsulation theory and applications.pdf
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
cuic standard and advanced reporting.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPT
Teaching material agriculture food technology
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Empathic Computing: Creating Shared Understanding
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Per capita expenditure prediction using model stacking based on satellite ima...
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Big Data Technologies - Introduction.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
Encapsulation theory and applications.pdf
The Rise and Fall of 3GPP – Time for a Sabbatical?
Diabetes mellitus diagnosis method based random forest with bat algorithm
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
cuic standard and advanced reporting.pdf
20250228 LYD VKU AI Blended-Learning.pptx
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Teaching material agriculture food technology
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Understanding_Digital_Forensics_Presentation.pptx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Empathic Computing: Creating Shared Understanding
Unlocking AI with Model Context Protocol (MCP)
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication

8 things to know about theming in drupal 8

  • 1. 8 Things to Know About Theming in Drupal 8 Or, “Lessons I Learned when Building a D8 Subtheme” Logan Farr || LoganFarr.com || @logan_farr || @loganfarr
  • 2. Site building Object oriented programming Module building Hooks and API functions not normally in theming. JavaScript frameworks Things we will not be covering. Constructing a Drupal 8 (sub)theme How a Drupal 8 theme works Templating and Twig* Template preprocessing and theme functions What the (theme) differences are between D7 and D8 Tools to debug a theme Things we will be covering
  • 3. 1.File structures have changed D8 Base Path D8 Theme
  • 4. 2. File types have changed THEME_NAME.info -> THEME_NAME.info.yml template.php -> THEME_NAME.theme hook_template.tpl.php -> hook_template.html.twig
  • 5. dcu.info name = DCU description = An example theme for Drupal Camp Utah base theme = Omega screenshot = screenshot.png engine = phptemplate core = 7.x stylesheets[all][] = css/dcu.styles.css scripts[] = js/dcu.behaviors.js regions[content] = Content ...
  • 6. dcu.info.yml name: DCU type: theme description: An example theme for Drupal Camp Utah base theme: Omega engine = phptemplate screenshot: screenshot.png core: 8.x libraries: - dcu/global-styling #Regions regions: navigation: Navigation header: Header content: Content machine_readable: Human Readable stylesheets-remove: - core/assets/vendor/normalize-css/normalize.css
  • 7. 3. stylesheets-remove You can prevent stylesheets from rendering on your page! In THEME_NAME.info.yml: stylesheets-remove: - (path to stylesheet here) - core/assets/.../normalize.css Note: You need the FULL path of the CSS stylesheet (from the root directory). Especially useful if: ● Trying to remove default module styling ● Trying to remove unnecessary system stylesheets ● Trying to remove a base theme stylesheet
  • 8. 4. Libraries Probably the most notable change in Drupal 8. Define library: A collection of CSS stylesheets and JS scripts Can be used globally, or just as needed. Library Naming (NOT file naming): THEME_NAME/LIB_NAME dcu/global-styling
  • 9. dcu.libraries.yml - Overview global-styling: #LIBRARY_NAME version: 1.x css: theme: styles/css/style.css {} styles/css/print.css { media: print } js: js/script.js {} header: js/header.js {} dependencies: core/jquery sessions: #LIBRARY_NAME ... (Yes, jQuery is now included in Core!)
  • 10. dcu.libraries.yml - CSS D8 dcu.info.yml: global-styling: version: 1.x css: theme: styles/css/style.css {} styles/css/print.css { media: print } D7 dcu.info: stylesheets[all][] = css/global.styles.css stylesheets[all][] = css/responsive.styles.css stylesheets[all][] = css/print.css
  • 11. dcu.libraries.yml - JS D8 dcu.info.yml: global-styling: ... # By default, all JS is loaded in the footer js: js/script.js: {} # But it can be overridden! js-header: header: true js: js/header.js: {} js-footer: js: js/footer.js: {} D7 dcu.info: scripts[] = js/script.js
  • 12. Attaching a Library to a Page Options for loading a library: ● Every page ● A subset of pages ● Individual templates (Remember, THEME_NAME/LIBRARY_NAME is how you reference a library) To load a library on every page, place in your THEME_NAME.info.yml file. To load a library on a subset of pages: <?php function dcu_preprocess_maintenance_page(&$variables) { $variables['#attached']['library'][] = dcu/sessions'; } ?> To load on a Twig template: {{ attach_library('dcu/sessions') }}
  • 13. You can override a library and remove a library with the commands library-override library-remove Another note about libraries...
  • 14. 5. Don’t mess up your YML. If you are developing a theme and you get a WSOD or a 500 error, it’s because you have messed up YML code. Use spaces, not tabs Don’t forget your colons (also forget your semi-colons) Use colons not equal signs Follow indentation
  • 15. 6. The Themer’s Best Friend Twig debugging! To turn on, edit settings.php and services.yml sites/default/settings.php $settings['twig_debug'] = TRUE; $settings['container_yamls'][] = __DIR__ . '/services.yml'; sites/default/services.yml parameters: twig.config: debug: true Thanks to Derek Walker (@derekawalker) for helping me out with this. Also Devel - although a note: the dpm() function is now kint()
  • 17. Twig Debug, Turned ON <!-- THEME DEBUG --> <!-- THEME HOOK: ‘page’ → <!-- FILE NAME SUGGESTIONS: x page--page.html.twig * page--front.html.twig * page.html.twig --> <!-- BEGIN OUTPUT FROM ‘themes/dcu/templates/page--page.html.twig’ --> (HTML HERE)
  • 18. Functions now done in THEME_NAME.theme! Some functions are different though. For example, to add template suggestions to a page, use hook_theme_suggestions_HOOK_alter(). Preprocess functions, like in D7, are used to pass variables to the page (Twig) templates. 7. Preprocess Functions are still a thing
  • 19. Example Functions in dcu.theme /** * Implements hook_preprocess_HOOK(). */ function dcu_preprocess_page(&$variables) { $variables[‘title’] = ‘Come to the dark side.’; $variables[‘page_class’] = ‘page-dark-side’; kint(); } /** * Implements hook_theme_suggestions_HOOK_alter(). */ function dcu_theme_suggestions_page_alter(array &$suggestions, array $variables) { if ($node = Drupal::routeMatch()->getParameter('node')) { $suggestions[] = 'page__' . $node->getType(); } return $suggestions; }
  • 20. 8. Templates are now done in Twig (not PHP) <section id="content-outer-wrapper" class="outer-wrapper clearfix"> <div id="main-layout" class="{{ region_classes.main }} inner-wrapper clearfix"> {% if page.content %} {{ page.content }} {% endif %} {% if page.sidebar_first %} {{ page.sidebar_first }} {% endif %} {% if page.sidebar_second %} {{ page.sidebar_second }} {% endif %} </div><!-- /#main --> </section><!-- /#main-outer-wrapper --> <div class="l-main-wrapper"> <div class="l-main"> <div class="l-content" role="main"> <a id="main-content"></a> <?php print render($tabs); ?> <?php print render($page['help']); ?> <?php if ($action_links): ?> <ul class="action-links"> <?php print render($action_links); ?> </ul> <?php endif; ?> <?php print render($page['content']); ?> </div> <?php print render($page['sidebar_first']); ?> <?php print render($page['sidebar_second']); ?> </div> </div>
  • 21. Twig Reference & PHP Equivalent {{ twig_variable }} {% if twig_variable %} {% elseif twig_variable %} {% else %} {% endif %} {% for i in 0..10 %} {{ i }} {% endfor %} echo $php_variable; if($boolean) else if($boolean) else for($i = 0; $i < 10; $i++) { echo $i; } Twig reference to come soon…
  • 22. Twig Variables & Preprocess Functions <body class=”{{ page_class }} main”> <h1>{{ title }} It’s awesome.</h1> ... </body> <body class=”page_dark_side main”> <h1>Come to the dark side. It’s awesome.</h1> ... </body>
  • 23. Twig Loops and PHP Arrays <?php function dcu_preprocess_page(&$variables) { $variables[‘sessions’] = array( ‘auditorium’ => array( ‘title’ => ‘Drupal 8 Theming’, ‘time => ‘11:15 AM’, ), ‘room_b’ => array( ‘title’ => ‘Drulenium’, ‘time’ => ‘11:15 AM’, ), ); } ?> {% for session in sessions %} {{ session.title }} at {{ session.time }} {% endfor %} Helpful note: {{ variable_name.key }} for array elements
  • 24. Drupal 8 Theming Fundamentals, Part 1 https://www.lullabot.com/articles/drupal-8-theming-fundamentals-part-1 Drupal 8 Assets Theming Guide https://www.drupal.org/theme-guide/8/assets Classy Theming by Morten DK https://drupalwatchdog.com/volume-5/issue-1/classy-theming My Drupal 8 Omega Subtheme “Resistor” (as reference material) https://github.com/loganfarr/Resistor Barcelona DrupalCon - Drupal 8 Theming https://events.drupal.org/barcelona2015/sessions/drupal-8-theming-0 MortenDK’s Los Angeles DrupalCon Session - Drupal 8 Theming with <3 https://events.drupal.org/losangeles2015/sessions/drupal-8-theming Twig Reference (Coming Soon) https://loganfarr.com/twig This presentation + extended examples (Also coming soon) https://loganfarr.com/d8-theming Additional Reading Material
  • 25. Now go build a Drupal 8 theme.