Creating sub-themes

Last updated on
1 February 2024

Sub-themes are just like any other theme, with one difference: They inherit the parent theme's resources. There are no limits on the chaining capabilities connecting sub-themes to their parents. A sub-theme could be a child of another sub-theme, and it could be branched and organized however you see fit. This is what gives sub-themes great potential. See also Sub-theme inheritance properties.

To create a sub-theme, define it like any other theme and declare its base theme with the "base theme" key. (Note that this key has no underscore.)

Generating a new sub-theme using starterkit

A new sub-theme of Stable 9 can be generated in the /themes directory by running the following command:

php core/scripts/drupal generate-theme fluffiness

The generated theme is based on a core Starterkit theme, which includes some default templates and CSS that helps you get started with your subtheme of Stable 9.

Generating a new sub-theme using Drush

A new sub-theme can be generated by running the following Drush command:

drush generate theme

Answer the resulting command line questions and the skeleton of your new theme will be created for you. Enter the machine name of you desired base theme under question #3, "Base theme".

Note: Before installing your new sub-theme, you need to manually copy over the regions from the base-theme *.info.yml file into your new sub-theme, to allow inheriting block positions. See Inheriting Theme Regions and Inheriting Block Placement below.

Creating sub-theme manually: Fluffiness

Fluffiness is an example of a sub-theme that uses Stable 9 as a base theme.

This is the folder structure you'll end up with by implementing the following files.

themes/
└──  fluffiness/
     ├── fluffiness.info.yml
     └── fluffiness.libraries.yml

The info file is named fluffiness.info.yml. You don't need to quote a YAML string, as long as the first character is not a special character.

name: Fluffiness
type: theme
description: This is a fluffy sub theme of Stable 9
core_version_requirement: ^8 || ^9 || ^10
# Defines the base theme
base theme: stable9
# Defines libraries group in which we can add CSS/JS.
libraries:
  - fluffiness/global-styling
# Regions, quote the names
regions:
  header: Header
  featured: Featured
  content: Content
  sidebar_first: First sidebar
  sidebar_second: Second sidebar
  footer: Footer

Include fluffiness.libraries.yml file to add CSS/JS in a global-styling group, defined above in the libraries: key.

global-styling:
  css:
    component:
      css/style.css: {}

Read more about adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme.

If you want to use a different name instead of fluffiness, just replace all occurrences of fluffiness with your own name (including the folder name), like the following, for example.

themes/
└──  my_custom_theme/
     ├── my_custom_theme.info.yml
     └── my_custom_theme.libraries.yml

The text you put in the name: line of the info.yml file is free-form and doesn't need to exactly match your sub-theme's filename. For example, it could be like this.

name: My Custom Theme
# (all the other lines omitted for brevity)

Sub-theme of a sub-theme

When creating a sub-sub-theme of a sub-theme, you must specify the sub-theme you want to extend as a base theme.

  • Fluffiness: First sub-theme of Stable 9
    name: Fluffiness
    type: theme
    description: This is a fluffy sub theme of Stable 9
    # Defines the base theme
    base theme: stable9
    
  • Shaved: sub-theme of Fluffiness (sub-sub-theme of Stable 9)
    name: Shaved
    type: theme
    description: This is a reduced fluff sub theme of Fluffiness
    # Defines the base theme
    base theme: fluffiness
    

Note that the base theme:parameter is the machine name of the base theme, whereas the name: parameter is a descriptive name.

Inheriting Theme Regions

Theme regions are not inherited from the specified base theme.  If the regions: parameter is left blank in your sub-theme's info.yml file or doesn't contain all regions from your base theme, then Drupal default regions may be used as fallbacks for block placement in your sub-theme. We highly recommend copying all regions defined in your base theme into your sub-theme's info.yml file.

# Because regions are not inherited, any region including standard
# Drupal regions as well as base theme regions must be defined in
# the sub-theme. This example demonstrates a sub-theme that leverages
# a subset of the standard Drupal regions (1), plus some custom
# regions defined in the base theme (2), and finally three
# "colophon"-related regions defined in this sub-theme.  
regions:
  # 1. Standard Drupal regions (also defined and used by base theme).
  # 2. Regions copied from base theme.
  # 3. Additional custom sub-theme regions.
  header:             Header                    # 1
  primary_menu:       Main menu                 # 1
  secondary_menu:     Secondary menu            # 1
  highlighted:        Highlighted               # 1
  help:               Help                      # 1
  section_nav:        Section Nav               # 2
  breadcrumb:         Breadcrumb                # 1
  page_title:         Page Title                # 2
  local_tasks:        Local Tasks               # 2
  content:            Content (Constrained)     # 1
  content_fullwidth:  Content (Edge-to-edge)    # 2
  colophon_first:     Colophon First Col        # 3
  colophon_second:    Colophon Second Col       # 3
  colophon_third:     Colophon Third Col        # 3
  footer:             Footer                    # 1

Inheriting Block Placement

In Drupal 8, themes may come with config/install/ or config/optional/ folders where pre-defined block configurations—including placement into theme regions—will be imported upon enabling the theme. If a sub-theme does not supply its own block configurations, Drupal will inherit these block configurations and region placement from the base theme. But, if the theme regions defined in your sub-theme's info.yml file do not match those available in the base theme, unpredictable placements in random regions can occur. 

Block placement inheritance only occurs:

  • From the current default theme
  • Only if the sub-theme does not have any of its own block placement configs
  • Will place blocks in the theme's default region if a matching region could not be found

Inheriting Block Templates

If the theme you are extending has custom block templates these won't be immediately inherited because a sub-theme creates copies of all the blocks in the parent theme and renames them with the sub-theme's name as a prefix. Twig block templates are derived from the block's name, so this breaks the link between these templates and their block. Fixing this problem currently requires a hook in the sub-theme. Following the examples above, we'd create a file called shaved.theme in the sub-theme's directory. In that file insert this code.

/**
 * Implements hook_theme_suggestions_HOOK_alter for blocks.
 */
function shaved_theme_suggestions_block_alter(&$suggestions, $variables) {

  // Load theme suggestions for blocks from parent theme.
  foreach ($suggestions as &$suggestion) {
    $suggestion = str_replace('shaved_', 'fluffiness_', $suggestion);
  }
}

For your own sub-themes replace shaved with the name of your sub-theme and fluffiness with the name of your base theme. 

Avoid "No available releases found"

If you see your sub-theme listed with a "No available releases found" warning on the "Available updates" page at /admin/reports/updates page, it may be due to a project: 'My theme' entry in the *.info.yml file. Just remove the line, and the warning should disappear. See also #208201: ignore certain projects at update scan.

Differences with Drupal 7

The most notable difference with Drupal 7 is that .info files have become YAML files that use .info.yml as an extension.

Help improve this page

Page status: No known problems

You can: