Post

Create and Activate a Custom Drupal Theme

How to create a custom Drupal theme from scratch and set it as the default.

Generate with Drush

The fastest way to scaffold a theme is with Drush’s code generator:

1
ddev drush generate theme

It will prompt you for:

  • Theme name
  • Machine name
  • Base theme (stable9 recommended for Drupal 10/11)
  • Whether to include a *.libraries.yml, *.theme, and starter templates

It outputs the full directory structure into web/themes/custom/. From there, skip to Enable and Set as Default.

If you prefer to build it manually, the structure is as follows.

Directory Structure

Create your theme inside web/themes/custom/:

1
2
3
4
5
6
7
8
9
web/themes/custom/mytheme/
├── mytheme.info.yml
├── mytheme.libraries.yml
├── mytheme.theme
├── css/
│   └── style.css
├── js/
│   └── script.js
└── templates/

mytheme.info.yml

This file is required. Without it Drupal won’t recognise the theme.

1
2
3
4
5
6
7
8
9
10
11
12
13
name: My Theme
type: theme
description: Custom theme for My Site.
core_version_requirement: ^10 || ^11
base theme: stable9
libraries:
  - mytheme/global
regions:
  header: Header
  primary_menu: Primary Menu
  content: Content
  sidebar: Sidebar
  footer: Footer
  • base theme — inherits templates and preprocessing from the parent. Use stable9 for Drupal 10/11, classy for older.
  • libraries — attaches your CSS/JS globally. Remove if you want to attach per-template instead.
  • regions — defines the available block placement regions. The content region is required.

mytheme.libraries.yml

Defines asset libraries that can be attached to the theme or templates.

1
2
3
4
5
6
7
8
global:
  css:
    theme:
      css/style.css: {}
  js:
    js/script.js: {}
  dependencies:
    - core/drupal

mytheme.theme

Optional PHP file for preprocess functions. See Drupal preprocess functions for usage.

1
2
3
4
5
6
7
8
<?php

/**
 * Implements hook_preprocess_HOOK() for page templates.
 */
function mytheme_preprocess_page(&$variables) {
  // Add variables to page.html.twig here.
}

Enable and Set as Default

1
2
3
4
5
6
7
8
# Enable the theme
ddev drush theme:enable mytheme

# Set as the default (front-end) theme
ddev drush cset system.theme default mytheme --yes

# Clear cache
ddev drush cr

To set the admin theme separately:

1
ddev drush cset system.theme admin claro --yes

Verify in the UI

Appearance → your theme should show as Installed with a Set as default option if not already set via Drush.

Export Config

After enabling and setting the theme, export config so it’s tracked in version control:

1
2
3
ddev drush cex --yes
git add config/sync/system.theme.yml
git commit -m "Enable mytheme as default theme"
This post is licensed under CC BY 4.0 by the author.