8 things to know about theming in drupal 8
TRANSCRIPT
8 Things to Know About Theming in Drupal 8Or, “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.ymltemplate.php -> THEME_NAME.themehook_template.tpl.php -> hook_template.html.twig
dcu.info
name = DCUdescription = An example theme for Drupal Camp Utahbase theme = Omegascreenshot = screenshot.pngengine = phptemplatecore = 7.x
stylesheets[all][] = css/dcu.styles.cssscripts[] = js/dcu.behaviors.js
regions[content] = Content...
dcu.info.yml
name: DCUtype: themedescription: An example theme for Drupal Camp Utahbase theme: Omegaengine = phptemplatescreenshot: screenshot.pngcore: 8.x
libraries: - dcu/global-styling
#Regionsregions: 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_NAMEdcu/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.cssstylesheets[all][] = css/responsive.styles.cssstylesheets[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:<?phpfunction 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 commandslibrary-overridelibrary-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.ymlparameters: 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<?phpfunction 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.