The Drupal 8
Theming Experience
Scott Reeves (Cottser)
Scott Reeves
-
Drupal 8 theme system
and Stable (co-)maintainer
-
Provisional Drupal 8 core
committer
-
Team Lead @ Digital Echidna
- Former child pilot
TX (Themer Experience)
DX (Developer Experience)
What we'll cover
- Core base themes
- The without filter
- Twig theme registry loader
- Working with libraries
Two main camps
- Sensible ⅔
- Clean ⅓
Use Classy
Use Stable
base theme: classy
my_theme.info.yml:
my_theme.info.yml:
Power to the templates*
{%
set classes = [
'node',
'node--type-' ~ node.bundle|clean_class,
node.isPromoted() ? 'node--promoted',
node.isSticky() ? 'node--sticky',
not node.isPublished() ? 'node--unpublished',
view_mode ? 'node--view-mode-' ~ view_mode|clean_class,
]
%}
{{ attach_library('classy/node') }}
<article{{ attributes.addClass(classes) }}>
Additive vs. Subtractive
{{ content|without('comments', 'links') }}
{{ content.links }}
{{ content|without('comments') }}
{% hide(content.comments) %}
{% hide(content.links) %}
{{ content }}
{{ content.links }}
{% show(content.links) %}
{# Content with links but without comments #}
{{ content }}
Print what you want, when you want
Referencing other Twig templates
- By namespace:
- Full path from Drupal root:
"core/themes/stable/templates/block/block.html.twig"
"@stable/block/block.html.twig"
Twig blocks
{% extends "@stable/block/block.html.twig" %}
{% block content %}
<div class="block-content-wrapper">
{{ parent() }}
</div>
{% endblock %}
<div{{ attributes }}>
{{ title_prefix }}
{% if label %}
<h2{{ title_attributes }}>{{ label }}</h2>
{% endif %}
{{ title_suffix }}
{% block content %}
{{ content }}
{% endblock %}
</div>
block.html.twig:
Starting to build
{% extends "@stable/block/block.html.twig" %}
{% block content %}
<div class="block-search-form-wrapper">
{{ parent() }}
</div>
{% endblock %}
.
├── my_theme.info.yml
└── templates
├── block--search-form-block.html.twig
└── page.html.twig
block--search-form-block.html.twig:
Starting to grow
{% extends "@stable/block/block.html.twig" %}
{% block content %}
<div class="block-search-form-wrapper">
{{ parent() }}
</div>
{% endblock %}
.
├── my_theme.info.yml
└── templates
├── block--search-form-block.html.twig
├── block.html.twig
└── page.html.twig
block--search-form-block.html.twig:
What more do
we need?
Planning for growth
{% extends "block.html.twig" %}
{% block content %}
<div class="block-search-form-wrapper">
{{ parent() }}
</div>
{% endblock %}
.
├── my_theme.info.yml
└── templates
├── block--search-form-block.html.twig
├── block.html.twig
└── page.html.twig
block--search-form-block.html.twig:
Referencing other Twig templates
- By template name:
- By namespace:
- Full path from Drupal root:
"@stable/block/block.html.twig"
"block.html.twig"
"core/themes/stable/templates/block/block.html.twig"
Extending variables*
{% extends "block.html.twig" %}
{% set title_attributes = title_attributes.addClass('hello-there') %}
{% set attributes = attributes.removeClass('from-earlier') %}
block--search-form-block.html.twig:
Libraries*
cuddly-slider:
version: 1.x
css:
theme:
css/cuddly-slider.css: {}
js:
js/cuddly-slider.js: {}
dependencies:
- core/jquery
my_theme.libraries.yml:
Overrides
libraries-override:
classy/base:
css:
component:
css/components/menu.css: false
user/drupal.user: false
my_theme.info.yml:
jQuery Update
libraries-override:
core/jquery:
js:
assets/vendor/jquery/jquery.min.js: js/jquery-5000.max.js
my_theme.info.yml:
Your Custom Modernizr Build
libraries-override:
core/modernizr:
js:
assets/vendor/modernizr/modernizr.min.js: js/modernizr.min.js
my_theme.info.yml:
Extending
libraries-extend:
user/drupal.user:
- my_theme/user
classy/node:
- my_theme/node
my_theme.info.yml:
Add library from Twig
{{ attach_library('my_theme/cuddly-slider') }}
whatever.html.twig:
Remember:
Drupal 8 is not done.
Thanks.
The Drupal 8 Theming Experience
By Scott Reeves
The Drupal 8 Theming Experience
Presented at DrupalCamp Toronto 2016
- 1,728