---
title: "Drupal 8's theming options for custom markup and class names · Appnovation"
url: "https://www.appnovation.com/insights/drupal-8s-theming-options-custom-markup-and-class-names"
description: "How to customize markup and control CSS class names in a Drupal 8 theme, comparing the two theming approaches core offers front-end devs."
---

Article

# Drupal 8's theming options for custom markup and class names

[![](https://cdn.sanity.io/images/ey850001/production/d554cb30b50f2e0f5ec2f886c627b6f37dd65b94-68x68.png?w=68&auto=format) azvonkov azvonkov Senior Front End Developer](/people/azvonkov-azvonkov.md) Feb 23, 2015  
 7 min read 

![Drupal 8's theming options for custom markup and class names](https://cdn.sanity.io/images/ey850001/production/755a435d0a7bdc06425f91e6ceb8ebf9ee6a1e78-1400x400.jpg?w=1400&auto=format) 

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.

1.  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.
2.  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 (opens in new window)](https://austin2014.drupal.org) a so called "[banana consensus (opens in new window)](https://www.drupal.org/node/2289511)" 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:

1.  Want sensible markup with sensible default classes so they can apply CSS with minimal markup overrides. Roughly 2/3.
2.  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 (opens in new window)](https://www.drupal.org/node/2322163) was focused on moving the CSS classes from preprocess to twig templates. The [second phase (opens in new window)](https://www.drupal.org/node/2348543) 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 (opens in new window)](https://www.drupal.org/node/2349559) 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 (opens in new window)](https://github.com/zetagraph/monoset) and the demo [here (opens in new window)](http://subtleshift.net) .

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 (opens in new window)](https://en.bem.info) 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.

[![](https://cdn.sanity.io/images/ey850001/production/d554cb30b50f2e0f5ec2f886c627b6f37dd65b94-68x68.png?w=68&auto=format) azvonkov azvonkov Senior Front End Developer · Appnovation](/people/azvonkov-azvonkov.md) 

## Keep reading

[![What is Sovereign AI](https://cdn.sanity.io/images/ey850001/production/a5889abdd5e80376912546622e046e3fbef234b4-2496x1664.png?w=640&auto=format)](/insights/what-is-open-source-sovereign-ai.md)

 Article · 7 min AI 

### [What Is Open Source, Sovereign AI?](/insights/what-is-open-source-sovereign-ai.md)

Every company is encouraging more AI, and almost every AI bill is climbing. Sovereign AI is about two kinds of control: over your data and over your costs. Here's why open source sits at its foundation.

[Iain MacNeil](/people/iain-macneil.md) Article 

[![AI-first experience design](https://cdn.sanity.io/images/ey850001/production/8bbc2418e87924ef10f36115478a2e10d5bed95e-1584x624.jpg?w=640&auto=format)](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

 Article · 6 min AI Sep 10, 2026 

### [How to Build an AI-First Experience Without Throwing Out Everything You've Already Built](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

Users now expect a direct answer, not a list of links to click through. Here's how organizations can layer an AI-First experience onto their existing website or app, in weeks rather than years.

[Andrew Douglas](/people/andrew-douglas.md) Article 

[![What Becomes Possible When AI Can Read All the Data](https://cdn.sanity.io/images/ey850001/production/c28ab0bd26753421ee42937e13adc7a7f19b47f0-1296x510.jpg?w=640&auto=format)](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

 Article · 4 min AI Sep 09, 2026 

### [What Becomes Possible When AI Can Read All the Data](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

Most of the world's data has never been analyzed, only sampled. AI changes that. How AI-ready data platforms unlock questions no one could ask before.

[Appnovation](/people/appnovation.md) Article 

## Get the thinking,  
*before everyone else.*

One considered email a month. New essays, field notes from live engagements, and the occasional strong opinion. No noise.
