Building a Custom Theme in Drupal 8

AnneTomasevich 6,707 views 48 slides Aug 15, 2015
Slide 1
Slide 1 of 48
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48

About This Presentation

Little documentation and few base themes with 8.x branches - what's a front end developer to do? I'll show you what's changing in Drupal theming between D7 and D8 and how to create a custom theme based on the Classy base theme, step by step. We'll go over Twig basics and Twig debuggi...


Slide Content

BUILDING A CUSTOM
THEME IN DRUPAL 8
BASED ON THE CLASSY BASE THEME
Presentation by Anne Tomasevich

INTRODUCTION
This is the part where I talk about myself
Photo by Jessie Gladdek
savaslabs.com
@Savas_Labs

AGENDA
What's changing?
Let's make a theme
Twig basics and debugging

LET'S START FROM THE VERY
BEGINNING
WHAT IS THEMING?
Themes allow you to change the look and
feel of your Drupal site.
- Someone who's good at being very general

WHY WOULD YOU USE DRUPAL 8
NOW?!
And when is it coming out?

WHAT'S CHANGING?
...and how do I, a person who probably doesn't like change, cope with these changes...

WHAT'S NEW IN DRUPAL 8?
Twig, a template engine by SensioLabs
Classy, a new base theme
template.php becomes [theme-name].theme. (Dear Drupal
gods, can we please have theme.php?)

WHAT'S NEW IN DRUPAL 8?
Responsive design elements are included by default
Breakpoints can be set and used across modules and themes

WHAT'S NEW IN DRUPAL 8?
LOOK AT ALL THE PRETTY THINGS
WE GET TO USE NOW!!
HTML5
CSS3
Modern jQuery libraries
SMACSS
BEM
Standardized breakpoints

WHAT'S NEW IN DRUPAL 8?
Support for IE8 and below is dropped meaning the use of
jQuery 2.0, HTML5, and CSS3 (including pseudo selectors) are
now supported
CSS:
Far fewer IDs are used
CSS file structure now uses
Default class names follow the format
CSS and JS files are attached to pages differently
SMACSS
BEM

WHAT'S NEW IN DRUPAL 8?
For a more comprehensive list, visit Drupal's change log.

WHY ALL THE CHANGES?
ACCESSIBILITY TO NON-DRUPALERS
Fewer Drupal-specific conventions and more popular, well-
documented frameworks (such as Twig), meaning non-
Drupalers can jump in much more quickly.
D8 themers don’t need to know PHP to whip up a theme.*
* I mean kinda ¯\_(ツ)_/¯

WHY ALL THE CHANGES?
SECURITY
Text is automatically escaped in Twig, meaning a lower
chance of XSS attacks.
Template files are more secure since they no longer contain
PHP code.
<?php db_query('DROP TABLE {users}'); ?>
Scary example courtesy of sqndr at d8.sqndr.com.

WHY ALL THE CHANGES?
CURRENT FRAMEWORKS AND TOOLS
Separation of logic from appearance = more modular
(reusable) code
More semantic CSS class names = leaner CSS and a more
readable DOM
A general trend towards more extendable, modular, well-
organized, better-performing code

ANY DISADVANTAGES?
1. Many contributed themes and modules don't having their 8.x
branches ready.
A fun note on the 8.x branch of a popular contrib theme:
This is a development branch. Please note
that this branch is probably severely broken.
It is strongly recommended to wait before
using this branch or even creating issues
regarding it.

ANY DISADVANTAGES?
2. Serious lack of documentation online
Of the documentation that DOES exist, much of it is:
Outdated, and marked as such.
Outdated, and NOT marked as such.

LET'S BUILD THIS THING

WHAT AM I TOTALLY GLOSSING
OVER?
template.php *.theme
Grid framework and CSS architecture
Probably a lot of other things

CREATE A THEME FOLDER
Drupal core now resides in its own folder. Contributed and
custom modules and themes are in the modules and themes
folders, respectively.
Don't forget to create a custom folder for your custom
theme!

CREATE A .INFO.YML FILE
# mappy.info.yml
name: Mappy
type: theme
description: 'D8 Theme for a basic leaflet site.'
core: 8.x
base theme: classy
libraries:
- mappy/global-styling
- mappy/leaflet
regions:
navbar: 'Top Navigation Bar'
content: Content # required!
sidebar: 'Sidebar'
footer: 'Footer'
[theme-name].info becomes [theme-name].info.yml

DOT INFO DOT WHAT?
YAML is a data serialization language.
Key-value pairs.
Check out on YAML syntax
before getting started.
And mind your whitespace!
Symfony's excellent writeup

CREATE A .INFO.YML FILE
# mappy.info.yml
name: Mappy
type: theme
description: 'D8 Theme for a basic leaflet site.'
core: 8.x
regions:
navbar: 'Top Navigation Bar'
content: Content # required!
sidebar: 'Sidebar'
footer: 'Footer'
This looks familiar, right?

CLASSY, A NEW BASE THEME
# mappy.info.yml
base theme: classy
In D8, default classes are stripped from Drupal core and
moved into the base theme Classy.
To avoid these default classes, simply don't base your theme
on Classy.
But we want them because BEM is awesome! Check out this
awesome introduction.

LIBRARIES
# mappy.info.yml
libraries:
- mappy/global-styling
- mappy/leaflet
In D8, assets can be added in a few different ways: globally,
per-template, per-page, and more.
All libraries must be defined in your *.libraries.yml file.

CREATE A .LIBRARIES.YML FILE
# mappy.libraries.yml
global-styling:
css:
theme:
css/styles.css: {}
leaflet:
css:
theme:
css/leaflet.css: {}
js:
js/leaflet.js: {}
js/map.js: {}
dependencies:
- core/jquery
Note that jQuery is listed as a dependency of the Leaflet library.
Since jQuery is no longer loaded automatically on every page, it
must be explicitly required.

ADDING ASSETS TO YOUR SITE
# mappy.info.yml
libraries:
- mappy/global-styling
- mappy/leaflet
Since this is a small site and we need our libraries on every
page, we're adding them globally.
Visit for more information on methods for adding
assets.
drupal.org

CREATE A .BREAKPOINTS.YML
FILE
# mappy.breakpoints.yml
mappy.mobile:
label: mobile
mediaQuery: '(min-width: 0px)'
weight: 2
multipliers:
- 1x
mappy.narrow:
label: narrow
mediaQuery: 'all and (min-width: 560px) and (max-width: 850px)'
weight: 1
multipliers:
- 1x
mappy.wide:
label: wide
mediaQuery: 'all and (min-width: 851px)'
weight: 0
multipliers:
Ours is stolen adapted from the Bartik theme.

BREAKPOINTS
Once you add a .breakpoints.yml file (and uninstall and
reinstall your theme), the breakpoints you've set will be
exposed in the admin UI.
These breakpoints can be used across various modules.

WITH THESE FILES SET UP, WE
NOW HAVE A WORKING CUSTOM
THEME!

TEMPLATE FILES
In our theme's current state, we're using Classy's default
template files.
If we want to override them, it's time to learn some Twig.
If one more person makes a "Gettin' Twiggy with it" joke...

INTRO TO TWIG
is a template engine with syntax similar to Django, Jinja,
and Liquid.
It simplifies template creation with clean syntax and useful
built-in filters, functions, and tags.
In a Drupal template file (now with the extention .html.twig),
anything between curly braces is Twig.
Twig

TWIG DELIMITERS
{{ These }} are for printing content, either explicitly or via
functions
{% These %} are for executing statements
{# These #} are for comments

PRINTING VARIABLES AND
REGIONS
In D7 we render content like so:
<?php print render($page['sidebar']); ?>
Printing variables in D8 is as easy as including them inside
double curly braces:
{# In page--front.html.twig #}
{# Print the sidebar region. #}
{{ page.sidebar }}

PRINTING VARIABLES WITH
SPECIAL CHARACTERS
If a variable name contains special characters, use Twig's
subscript syntax (which will look familiar to seasoned
Drupalers).
{# In page--front.html.twig #}
{# Print the page type. #}
{{ page['#type'] }}
This will come in handy more during debugging.

FILTERS
Twig comes with many that variables are passed
to via the pipe character.
built-in filters
Here's the date filter:
{# Format the post date. #}
{{ post.published|date("Y-m-d") }}

DRUPAL-SPECIFIC FILTERS
Check them out here.
Remember our old friend t()?
{# Run an ARIA label through t() #}
<nav class="tabs" role="navigation" aria-label="{{ 'Tabs'|t }}">

FUNCTIONS
Twig also comes with various that can be used in
double curly braces.
functions
Here's the cycle function doing some very important work:
{% set fruits = ['apple', 'orange', 'banana'] %}
{% for i in 0..10 %}
{{ cycle(fruits, i) }}
{% endfor %}

TAGS
Used for control flow and other fun things.
{# From Bartik's page.html.twig #}
{# If there are tabs, output them. #}
{% if tabs %}
<nav class="tabs" role="navigation" aria-label="{{ 'Tabs'|t }}">
{{ tabs }}
</nav>
{% endif %}
In template files, we’ll use the if statement quite often.

GET PSYCHED
Make sure you check out the Twig coding standards!

TWIG DEBUGGING
To enable debug mode and turn off caching, we need to do 3
things:
1. Turn on Twig’s debug mode
2. Turn on Twig auto reload, meaning that Twig templates are
automatically recompiled when the source code is changed
3. Disable Drupal’s render cache
You do NOT need turn off Twig caching - turning on auto reload
is enough.

USE SETTINGS.LOCAL.PHP
1. Copy sites/example.settings.local.php to
sites/default and rename to settings.local.php. Fill out
your local database settings.
2. Uncomment the following at the bottom of
sites/default/settings.php:
if (file_exists(__DIR__ . '/settings.local.php')) {
include __DIR__ . '/settings.local.php';
}

TURN ON DEBUG MODE AND
AUTO RELOAD
Check out settings.local.php
// In settings.local.php
/**
* Enable local development services.
*/
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml';
This tells us to head over to development.services.yml.
// In sites/development.services.yml
parameters:
twig.config:
debug: true
auto-reload: true

TURN OFF DRUPAL'S RENDER
CACHE
Just kidding, you already did.
// In settings.local.php
/**
* Disable the render cache (this includes the page cache).
*
* This setting disables the render cache by using the Null cache back-end
* defined by the development.services.yml file above.
*
* Do not use this setting until after the site is installed.
*/
$settings['cache']['bins']['render'] = 'cache.backend.null';

DEBUG AWAY
Now you can:
View HTML comments in your browser’s code inspector with
lots of helpful info:
Which theme hook is being implemented
Theme hook suggestions (i.e. how to override the current
theme hook)
Which template file is being output.
Make changes to your source code and simply refresh the
page to see your changes rather than constantly rebuilding
the cache.

DUMP( )
With Twig debugging turned on, we can use the Twig function
dump().
{# In a template file #}
{# Print out all variables on the page. #}
{{ dump() }}
{# Print the page's base path. #}
{{ dump(base_path) }}

EVEN BETTER: KINT( )
Install the Devel and Devel Kint modules to use kint() in the
same way, but with a pretty, expandable array instead.
{# In a template file #}
{# Print out all variables on the page. #}
{{ kint() }}

RESOURCES AND FURTHER
READING
A brilliant blog post about D8 theming (Savas)
D8 theming guide (Sander)
YAML formatting (Symfony)
Intro to BEM (CSS Wizardry)
Adding assets to pages (drupal.org)
Twig documentation (Sensiolabs)
Drupal-specific Twig filters (drupal.org)
Twig coding standards (drupal.org)
Twig debugging and devel (drupalize.me)

QUESTIONS?
@Savas_Labs
savaslabs.com