A Theme

A theme is a directory with theme.xml and registration.php: what each file does and how a parent is declared.

Syntaxapp/design/<area>/<Vendor>/<theme>/theme.xml

A theme is the component that decides how pages look. It holds templates, layout XML, stylesheets, images and fonts, and it lives in app/design/<area>/<Vendor>/<theme>. An area is the part of the application the files apply to: frontend for the storefront, adminhtml for the admin. A storefront theme has no effect on admin pages.

Two files make a theme

theme.xml declares it. It carries the title shown in the admin, an optional preview image, and the <parent> theme it inherits from. Magento 2.4.9 ships two storefront themes, Magento/blank and Magento/luma, and a custom theme normally names one of them as its parent. registration.php tells the framework that the directory is a theme and under which name, for example frontend/Acme/storefront.

The rest of the directory

  • etc/view.xml — image sizes and view variables
  • web/css, web/images, web/fonts, web/js — the theme's own assets
  • <Vendor>_<Module>/templates and <Vendor>_<Module>/layout — per-module overrides
  • media/preview.jpg — the thumbnail the admin shows
  • composer.json — needed only to distribute the theme as a package

Making it visible

Themes are written into the database by a data patch, so after adding the files run bin/magento setup:upgrade and then bin/magento cache:flush. The theme then appears in Content > Design > Configuration, where you apply it to a store view.

Example

Example · xml
<!-- app/design/frontend/Acme/storefront/theme.xml -->
<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Acme Storefront</title>
    <parent>Magento/luma</parent>
    <media>
        <preview_image>media/preview.jpg</preview_image>
    </media>
</theme>

<!--
    The title is what merchants see in Content > Design > Configuration.
    <parent> makes every file this theme does not define fall back to Luma,
    and then to Blank, which is Luma's own parent.
    Put the thumbnail at app/design/frontend/Acme/storefront/media/preview.jpg.

    Apply it with:
      bin/magento setup:upgrade
      bin/magento cache:flush
    then select Acme Storefront for a store view in the admin.
-->

When to use it

  • Start a client build as a child of Luma without editing Luma itself.
  • Give two similar themes preview images so a merchant can tell them apart in the admin.
  • Package a finished theme so another installation can require it with Composer.
  • Create a second theme for a second store view that differs in only a few files.

More examples

registration.php for a theme

Every theme needs this file, and the string is the theme's identity: area, vendor, theme, matching the directory it sits in. For a theme inside app/design the framework finds the file when it scans app/design at bootstrap; for a theme installed through Composer the autoload.files entry in composer.json loads it. Adding or changing the file needs bin/magento setup:upgrade before the theme is usable, and bin/magento cache:flush afterwards.

Example · php
<?php
// app/design/frontend/Acme/storefront/registration.php

declare(strict_types=1);

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::THEME,
    'frontend/Acme/storefront',
    __DIR__
);

composer.json, only for distribution

A theme in app/design works without this file. You add it when the theme must travel: the type magento2-theme tells the Magento Composer installer where to place it, and the require section names the parent theme's package so the parent cannot be missing. Luma's package is magento/theme-frontend-luma, Blank's is magento/theme-frontend-blank.

Example · json
{
    "name": "acme/theme-frontend-storefront",
    "description": "Acme storefront theme",
    "type": "magento2-theme",
    "license": "proprietary",
    "require": {
        "php": "~8.4.0",
        "magento/framework": "*",
        "magento/theme-frontend-luma": "*"
    },
    "autoload": {
        "files": [
            "registration.php"
        ]
    }
}

What the directory looks like filled in

A realistic small theme: two declaration files, view configuration, its own styles and images, and overrides for exactly the two modules it needed to change. Nothing here is mandatory except theme.xml and registration.php, and a file you do not create is taken from the parent theme instead.

Example · text
app/design/frontend/Acme/storefront/
├── theme.xml
├── registration.php
├── composer.json
├── media/
│   └── preview.jpg
├── etc/
│   └── view.xml
├── web/
│   ├── css/
│   │   └── source/
│   │       └── _extend.less
│   ├── fonts/
│   └── images/
│       └── logo.svg
├── Magento_Theme/
│   ├── layout/
│   │   └── default.xml
│   └── templates/
│       └── html/
│           └── copyright.phtml
└── Magento_Catalog/
    └── web/
        └── css/
            └── source/
                └── _extend.less

Discussion

  • Be the first to comment on this lesson.