Skip to content
This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

Latest commit

 

History

History
326 lines (262 loc) · 12.3 KB

3.1-creating-themes.md

File metadata and controls

326 lines (262 loc) · 12.3 KB

Creating Themes and Subthemes

In Drupal 8 you can create base themes and subthemes. A base theme provides some set of predefined styles and functionality that a frontend developer can base a subtheme on. Any theme can be used as a base theme, even if it is a subtheme of some other theme.

Core Themes

Drupal 8 comes with five preloaded themes, located in core/themes/.

  1. Stable: Default base theme for all other themes unless otherwise specified. It is a minimalist theme, that only introduces essential CSS and functionality.

  2. Classy: Base theme that comes prepackaged with "sensible" default markup and css classes.

  3. Bartik: Based on Classy. The default frontend Drupal theme. It is simple and responsive.

  4. Seven: Based on Classy. The default admin Drupal theme.

  5. Stark: Is not based on any other theme. It is intentionally styleless to demonstrate default Drupal HTML, CSS and Javacript from core and contrib modules.

Choosing a Base Theme

Choosing a base theme is a big decision when creating a new Drupal theme as it lays the framework for the way you will be building your frontend. From a D8 perspective, Stable and Classy are the two standard base themes provided out of the box, although you could technically use Bartik, Seven and Stark as a base theme if you really wanted to.

The reason Drupal 8 provides two base themes is to appeal to two different groups of developers:

  • "Sensible 2/3" developers who want sensible markup and default classes to apply CSS with minimal overrides.
  • "Clean 1/3" developers who want a minimalist theme that doesn't place unnecessary markup and css upon themers.

As a compromise, Stable was established for the minimalists, and Classy was for those wanting sensible markup and classes.

See Results of Drupalcon Austin's Consensus Banana for more information about that decision.

But these are only two out of a theoretically infinite number of base themes you can choose from, including a custom base theme that is shared by all of your different projects.

You can also opt out of using a base theme (see Stark theme), but just recognize that by doing so you are no longer guaranteeing backwards compatibility when core functionality changes.

File Structure

Custom and third-party themes should be installed in /themes/{themename}.

Inside each theme it is recommended to have css, js and images directories.

{themename}.info.yml

Drupal automatically searches the themes directory looking for {themename}.info.yml. This file provides information about your theme to Drupal.

For example - substable.info.yml:

name: Substable
type: theme
description: 'A stable subtheme'
core: 8.x
libraries:
  - substable/global-styling
  - substable/global-scripts
base theme: stable
regions:
  header: Header
  content: Content
  sidebar_left: 'Sidebar - Left'
  sidebar_right: 'Sidebar - Right'
  footer: Footer

Theme Keys

Here is a list of available theme keys from Defining a theme with an .info.yml file:

  • name (required) - The human-readable name. This will appear on the "Appearance" page where the theme is activated.
  • type (required) - Indicates the type of extension, i.e., "module", "theme", or "profile". For themes this should always be set to "theme".
  • description (optional) - The description, displayed on the "Appearance" page.
  • package (optional) - Specifies a "package" that allows you to group themes together.
  • core (required) - Specifies the version of Drupal core that the theme is compatible with.
  • php (optional) - The minimum version of PHP required. Defaults to value of DRUPAL_MINIMUM_PHP constant.
  • version (optional) - Specifies a version. For themes hosted on drupal.org, the version number will be filled in by the packaging script. Do not specify it manually, but leave out the version line entirely.
  • libraries (optional) - A list of libraries (which can contain both CSS and JavaScript assets) to add to all pages where the theme is active.
  • libraries-override (optional) - A collection of libraries and assets to override.
  • base theme (recommended) - A theme can inherit the resources from another theme by specifying it as a base theme. It is recommended to use classy or stable (stable is the default if the key is not supplied) – this makes it easier for your theme to inherit future changes in core theming.
  • hidden (optional) - Indicates whether or not to hide the theme from the "Appearance" page so that it cannot be enabled/disabled via the UI.
  • engine (optional) - The theme engine. Defaults to "twig".
  • screenshot (optional) - The path to screenshot relative to the theme's .info.yml file. Screenshots should be 588 pixels wide and 438 pixels high, though they are displayed at a smaller size. By default, Drupal will look for a file named "screenshot.png" in the root of your theme folder and use that as the theme image on the "Appearance" page.
  • regions (optional) - A list of theme regions. (Note that region keys are not preceded by a dash.) A content region is required. Read more about adding regions to a theme.
  • regions_hidden (optional) - A list of inherited regions to remove.
  • features (optional) - A list of features to expose on the theme "Settings" page.
  • stylesheets-remove (deprecated) - A list of stylesheets from other modules or themes to remove from all pages where the theme is active. Each value must be a full path relative to the docroot to resolve ambiguity when more than one file with the same name exists. In cases where the file is part of a library that belongs to a module or theme, a token in the form @module_or_theme_name can be used in place of the full path. Note that when using the token the value must be quoted because "@" is a reserved indicator in YAML. Note: This key is deprecated and will be removed in Drupal 9. In most cases libraries-override should be used.
  • ckeditor_stylesheets (optional) - A list of stylesheets to add to the CKEditor frame.

{themename}.libraries.yml

If you wish to include Javascript and CSS in your theme, you can do so by creating libraries in {themename}.libraries.yml.

For example - substable.libraries.yml:

global-styling:
  version: 1.x
  css:
    theme:
      css/style.css: {}
      css/print.css: { media: print }
global-scripts:
  version: 1.x
  js:
    js/substable.js: {}
  dependencies:
    - core/jquery

Libraries also need to be included in the {themename}.info.yml file. See substable.info.yml example above.

See the Javascript/jQuery section for more information about Javascript and attaching libraries to a subset of pages.

Breakpoint Module

The breakpoints module allows you to predefine breakpoints for use in your responsive design. Breakpoints are defined in a {themename}.breakpoints.yml file.

Here is an example from the bootstrap theme:

bootstrap.screen-xs-max:
  label: screen-xs-max
  mediaQuery: 'all and (max-width: 767px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-sm-min:
  label: screen-sm-min
  mediaQuery: 'all and (min-width: 768px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-sm-max:
  label: screen-sm-max
  mediaQuery: 'all and (max-width: 991px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-md-min:
  label: screen-md-min
  mediaQuery: 'all and (min-width: 992px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-md-max:
  label: screen-md-max
  mediaQuery: 'all and (max-width: 1199px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-lg-min:
  label: screen-lg-min
  mediaQuery: 'all and (min-width: 1200px)'
  weight: 1
  multipliers:
    - 1x

From Working with breakpoints in Drupal 8:

Please note that inputting your CSS breakpoints into your breakpoints.yml file is only necessary when Drupal needs to interact with the breakpoints as in the case of the Responsive Images module.

Breakpoint Keys

  • label - A human readable label for the breakpoint.
  • mediaQuery - Media query text proper, e.g. 'all and (min-width: 851px)'.
  • weight - Positional weight (order) for the breakpoint.
  • multipliers - Supported pixel resolution multipliers.

Breakpoint Groups

From Working with breakpoints in Drupal 8:

Breakpoints can be organized into groups. Modules and themes should use groups to separate out breakpoints that are meant to be used for different purposes, such as breakpoints for layouts or breakpoints for image sizing.

yourtheme.group1.mobile:
  label: narrow
  mediaQuery: ''
  weight: 0
  multipliers:
    - 1x
  group: yourtheme.group1
yourtheme.group1.narrow:
  label: narrow
  mediaQuery: '(min-width: 560px)'
  weight: 0
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group1
yourtheme.group1.wide:
  label: wide
  mediaQuery: '(min-width: 851px)'
  weight: 1
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group1

yourtheme.group2.mobile:
  label: narrow
  mediaQuery: ''
  weight: 0
  multipliers:
    - 1x
  group: yourtheme.group2
yourtheme.group2.narrower:
  label: narrow
  mediaQuery: '(min-width: 400px)'
  weight: 0
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group2
yourtheme.group2.wider:
  label: wide
  mediaQuery: '(min-width: 1001px)'
  weight: 1
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group2

You can also add breakpoints to breakpoint groups defined by other modules or themes, but you must use the full name.

yourmodule.yourtheme.group2.superwide
  label: superwide
  mediaQuery: '(min-width: 1501px)'
  weight: 1
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group2

Adding Regions to a Theme

All regions should be declared in the theme info file. The keys match the machine name and the values match the label for each available region.

For example:

regions:
  header: Header
  content: Content
  sidebar_left: 'Sidebar - Left'
  sidebar_right: 'Sidebar - Right'
  footer: Footer

Then each region can be referenced in your page.html.twig file:

<div class="container">

  {% if page.header %}
    <div class="row">
      <div class="header col-xs-12">
        {{ page.header }}
      </div>
    </div>
  {% endif %}

  <div class="row">

    {% if page.sidebar_left %}
      <div class="sidebar-left col-xs-2">
        {{ page.sidebar_left }}
      </div>
    {% endif %}

    {% if page.sidebar_left and page.sidebar_right %}
      <div class="content col-xs-8">
        {{ page.content }}
      </div>
    {% elseif page.sidebar_left or page.sidebar_right %}
      <div class="content col-xs-10">
        {{ page.content }}
      </div>
    {% else %}
      <div class="content col-xs-12">
        {{ page.content }}
      </div>
    {% endif %}

    {% if page.sidebar_right %}
      <div class="sidebar-right col-xs-2">
        {{ page.sidebar_right }}
      </div>
    {% endif %}

  </div>

  {% if page.footer %}
    <div class="row">
      <div class="footer col-xs-12">
        {{ page.footer }}
      </div>
    </div>
  {% endif %}

</div>

Default regions

If you declare any regions in your theme, even just one, all the default regions will no longer be applied and you assume responsibility for declaring any and all regions you want to use.

Additional Resources