In this post I wanted to show how easy it is to customize markup and control classes of a Drupal 8 theme.
Out of the box Drupal 8 is offering Front End Devs two different approaches that they can adopt for their theming needs.
- Drupal 8's core will not provide any default classes, instead it will serve as a clean slate that can be easily customized with custom class names and markup.
- We can use some sensible default class names and markup that are provided by the "Classy" theme if it is set as a base theme.
At the last North American DrupalCon a so called "banana consensus" was reached. Basically it is a way to get drupal to serve two different flavors of itself. It was determined that there are two camps that can have different needs or different expectations from Drupal core:
- Want sensible markup with sensible default classes so they can apply CSS with minimal markup overrides. Roughly 2/3.
- Want minimal markup with no default classes so they can add their own classes and override the markup when necessary. Roughly 1/3.
The first phase of Banana Consensus was focused on moving the CSS classes from preprocess to twig templates. The second phase is to copy those templates into the new "Classy" theme.
The idea is that if you don't want any classes by default you will not get any, and if you do, you would declare "Classy" as you base theme. Declaring "Classy" as your base theme is easy, you just need to add base theme: classy
in your theme_name.info
.
Curently "Bartik" and "Seven" in core/themes
declare "Classy" as a dependency and therefore inherit all its default classes. Obviously Drupal 8 is still work in progress and things are still in flex. There is an outgoing conversation as to how these templates should be organized.
Recently I've been working on a D8 theme which I wrote about it in this post. For this theme I wanted to have a clean slate and was only adding classes and overriding templates as needed. You can check out the source code on GitHub and the demo here .
Lets look at the example of this process and use a menu template as a sample. First make sure you set the debug: true
in your Drupal 8 services.yaml
file in sites/default/
Then inspect your source code. You will see that the menu comes from core/modules/system/templates/menu.html.twig
<-- THEME DEBUG -->
<-- THEME HOOK: 'menu__main' -->
<-- FILE NAME SUGGESTIONS:
* menu--main.html.twig
x menu.html.twig
-->
If you look at menu.html.twig
in core/modules/system/templates/menu.html.twig
you will see that by default there are no assumptions and no provision of any classes. This is nice as we might want to chose a certain convention for our theme. For example BEM style or something else for that matter. So now we have an ability to name these classes anyway we want.
Lets now modify this template. We can either go to core/modules/system/templates/menu.html.twig
as our twig template suggestion shows us. Or we can look into/core/themes/classy/templates/system/menu.html.twig
. The second will have the "menu" class added to it already. If you have Drupal 8 (beta 6) release and browse to /core/themes/classy/templates
you will see a large collection of templates in the "Classy" theme's template directory /core/themes/classy/templates/
. There we can see how classes are added and can adjust classes and markup of our custom theme in a similar way. For example we can add a custom class: <ul{{ attributes.addclass('my-classs') }}>
.
Of course in order for this changes to be picked up we need to copy this menu template into our custom theme's directory themes/your_theme_name/templates/menu.html.twig
and clear the caches.
Classy has a big list for template at this point. Just look at core/themes/classy/templates
. All these template candidates can be copied modified and used as core overrides in our custom theme.
├── aggregator
│ ├── aggregator-feed.html.twig
│ └── aggregator-item.html.twig
├── block
│ ├── block-list.html.twig
│ └── block.html.twig
├── book
│ ├── book-all-books-block.html.twig
│ ├── book-export-html.html.twig
│ ├── book-navigation.html.twig
│ ├── book-node-export-html.html.twig
│ └── book-tree.html.twig
├── comment
│ ├── comment.html.twig
│ └── field--comment.html.twig
├── file
│ ├── file-link.html.twig
│ ├── file-managed-file.html.twig
│ ├── file-upload-help.html.twig
│ ├── file-widget-multiple.html.twig
│ └── file-widget.html.twig
├── filter
│ ├── filter-caption.html.twig
│ ├── filter-guidelines.html.twig
│ ├── filter-tips.html.twig
│ └── text-format-wrapper.html.twig
├── forum
│ ├── forum-icon.html.twig
│ ├── forum-list.html.twig
│ ├── forum-submitted.html.twig
│ └── forums.html.twig
├── image
│ ├── image-anchor.html.twig
│ ├── image-crop-summary.html.twig
│ ├── image-formatter.html.twig
│ ├── image-resize-summary.html.twig
│ ├── image-rotate-summary.html.twig
│ ├── image-scale-summary.html.twig
│ ├── image-style-preview.html.twig
│ ├── image-style.html.twig
│ └── image-widget.html.twig
├── link
│ └── link-formatter-link-separate.html.twig
├── node
│ ├── field--node--created.html.twig
│ ├── field--node--title.html.twig
│ ├── field--node--uid.html.twig
│ ├── node-add-list.html.twig
│ ├── node-edit-form.html.twig
│ └── node.html.twig
├── rdf
│ └── rdf-metadata.html.twig
├── search
│ ├── block--search-form-block.html.twig
│ └── search-result.html.twig
├── system
│ ├── block--system-branding-block.html.twig
│ ├── block--system-menu-block.html.twig
│ ├── breadcrumb.html.twig
│ ├── checkboxes.html.twig
│ ├── confirm-form.html.twig
│ ├── container.html.twig
│ ├── datetime-form.html.twig
│ ├── datetime-wrapper.html.twig
│ ├── details.html.twig
│ ├── dropbutton-wrapper.html.twig
│ ├── feed-icon.html.twig
│ ├── field-multiple-value-form.html.twig
│ ├── field.html.twig
│ ├── fieldset.html.twig
│ ├── form-element-label.html.twig
│ ├── form-element.html.twig
│ ├── form.html.twig
│ ├── html.html.twig
│ ├── image.html.twig
│ ├── input.html.twig
│ ├── item-list.html.twig
│ ├── links.html.twig
│ ├── maintenance-page.html.twig
│ ├── mark.html.twig
│ ├── menu-local-action.html.twig
│ ├── menu-local-task.html.twig
│ ├── menu-local-tasks.html.twig
│ ├── menu.html.twig
│ ├── page.html.twig
│ ├── pager.html.twig
│ ├── progress-bar.html.twig
│ ├── radios.html.twig
│ ├── region.html.twig
│ ├── select.html.twig
│ ├── status-messages.html.twig
│ ├── table.html.twig
│ ├── tablesort-indicator.html.twig
│ ├── textarea.html.twig
│ ├── time.html.twig
│ └── vertical-tabs.html.twig
├── taxonomy
│ └── taxonomy-term.html.twig
├── toolbar
│ └── toolbar.html.twig
└── user
├── user.html.twig
└── username.html.twig
Having these options in Drupal 8 gives as greater flexibility and satisfies two theming camps. Those who want some defaults just need to declare "Classy" as a base and those who want no assumptions from the core can start with a clean slate and use their preferred naming syntaxes and conventions.