Welcome to The Super Guide to Theming in Magento 2 – Part 2 of 3. In this tutorial I will explain extending, overriding and customizing our custom or child theme via less compilation, templates, and xml.
Understanding Blank and Luma Themes:
Magento 2 Blank and Luma themes provide hooks to core functionality. Only the files or modules that are changed should be incorporated into custom themes. When creating a child theme, it is necessary to ensure a parent theme is named.
Static vs. Dynamic Theme Files explained
Files that are used by the browser to render a page are static and can be cached. Files used by the CMS to generate HTML are considered dynamic.
Static files are found in: app/design/frontend/<vendor_name>/<theme_name>/web and contain:
- CSS via Less
- Images for CSS and/or modules
- Frontend-specific JS
Let’s create a new vendor folder ‘Mytheme’ with theme ‘default’:
app/design/frontend/ ├── Mytheme/ │ │ ├──...default/ │ │ │ ├── ...web/ │ │ │ ├── ...
This is based off M2’s ‘Blank’ theme. There can be multiple themes and store views under one vendor. I chose ‘default’ as the base theme, so when we create multiple store views the global assets for the stores can remain here.
Static file deployment is affected by Magento modes as follows:
- Developer mode is where you develop your Magento site. Static files are written to
pub/directory every time they are called, as well as displaying exception errors being thrown in the front end.
- Production mode: Static files are deployed and when requested, it is pulled from cache only. These files are located in
root install dir/pub/static
- Modes are set via command line within the root of project directory via ssh.
- Set mode:
php bin/magento deploy:mode:set developeror
php bin/magento deploy:mode:set production
- Turn off caching:
php bin/magento cache:disable
- Turn on caching:
php bin/magento cache:enable
- Deploy static files:
php bin/magento setup:static-content:deploy
- Flush caches:
php bin/magento cache:flush
Dynamic view files are processed or executed by server to provide content on frontend. These are .less files, templates and layouts.
app/design/frontend/<vendor_name>/<theme_name>/ │ ├── Magento_<module>/ │ │ ├── web/ │ │ │ ├── css/ │ │ │ ├── source/ │ │ ├── layout/ │ │ │ ├── override/ │ │ ├── templates/ │ ├── web/ │ │ ├── css/ │ │ │ ├── source/ ...
Simplest way to extend parent styles
To extend the parent theme’s styles in your child theme:
- In your theme directory, create a
web/css/sourcesub-directory. So in this case,
- Within the source folder create a
_extend.lessfile there, so it looks like following:
<theme_name>/ │ ├── web/ │ │ ├── css/ │ │ │ ├── source/ │ │ │ ├──_extend.less ...
Extending a theme using
_extend.less is the simplest option when you want to add additional styles to what the parent theme already offers.
Simplest way to override parent styles
To override parent styles (that is, override default Magento UI library variables):
- In your theme directory, create a
web/css/sourcesub-directory.So in this case:
- Create a
_theme.lessfile here. The path to it then looks like following
<theme_name>/ │ ├── web/ │ │ ├── css/ │ │ │ ├── source/ │ │ │ ├──_theme.less ...
It is important to remember that your
_theme.less file overrides the parent file
- Copy all variables you need from the parent
_theme.less, including those which will not be changed. For example if your theme inherits from Blank, the
_theme.lessyou should copy from is located at
- Make the necessary changes.
To set up local compilation
- Install Node.js via command line in root directory of magento install.
grunt npm install -g grunt-cli
- Install npm packages
- Add theme to grunt configuration via
Grunt commands execute in developer mode. This recompiles your css while working locally or on dev server.
grunt clean:<theme>: Removes the theme related static files in the
grunt exec:<theme>: Republishes symlinks of the source files to the
grunt less:<theme>: Compiles less into
.cssfiles using the symlinks published in the
grunt watch: Tracks the changes in the source files, recompiles
.cssfiles, and reloads the browser page (you need to have LiveReload installed for you browser to reload).
Media queries in Magento default themes
According to the approach implemented in the library, the
.media-width() mix-in can be used in any
.less file in your theme, as many times as you need, but it is invoked only once within
lib/web/css/source/lib/_responsive.less. The resulting
styles.css has only one call for each media query with all the rules there, instead of multiple calls for the same query.
Breakpoints are used in the CSS code to set up the screen width at which the design switches from the mobile to the desktop version.
The Blank and Luma themes implement the following breakpoints:
- 768px (in the Blank and Luma themes, this breakpoint switches between mobile and desktop views)
You can change these breakpoints and add new ones in your custom theme.
In the Blank and Luma themes a mobile-first approach is used. It means that the styles for mobile devices (screen width less than 768px) are extended by the styles for the higher breakpoints. As a result, the extra styles are never loaded when a store is viewed on a mobile device.
In the Blank theme, the mobile and desktop styles are defined in separate files:
- styles-l.less is used to generate desktop-specific styles (768px and higher)
- styles-m.less is used to generate basic and mobile-specific styles
Basic layout elements
Magento application implements the Model-view-controller architecture pattern; meaning, the Magento software is architected into layers, including the view layer.
The major part of the view layer of Magento application is layout. Functionally, layout is a page structure represented by hierarchy of elements (called an element tree). These elements are the basic components of Magento page design, and can be either be blocks or containers. Technically, layout is defined within the .xml files, which contain element declarations and element manipulation instructions.
Here we will cover what you need to know to create or extend layouts for your custom theme. Part 3 will cover this in further detail.
A container exists for the sole purpose of assigning content structure to a page. A container has no additional content except the content of included elements. Examples of containers include the header, left column, main column, and footer.
A block represents each feature on a page and calls templates to generate the HTML to insert into its parent structural block. Examples of blocks include a category list, a mini cart, product tags, and product listing.
The basic view of all Magento storefront pages in defined within two page configuration layout files located in the Magento_Theme module:
<Magento_Theme_module_dir>/view/frontend/layout/default.xml: defines the page layout
<Magento_Theme_module_dir>/view/frontend/layout/default_head_blocks.xml: defines the scripts, images, and meta data included in a pages’
These basic page configuration layouts are extended in other Magento modules and themes.
In order to extend or override the parent themes page layout you would create a “default.xml” file within
For a particular page, it’s layout is defined by two major layout components: a page layout file and page configuration file (or a generic layout for pages returned in AJAX requests, emails, and so on).
The following are the definitions of each layout file type:
- Page layout: an XML file declaring a page wireframe inside the
<body>section of the HTML page markup, for example, a two-column page layout
- Page configuration: an XML file declaring detailed structure, contents and meta-information of a page; includes the
<body>sections of the HTML page markup
- Generic layout: an XML file declaring page detailed structure and contents inside the
bodysection of the HTML page markup; used for pages returned by AJAX requests, emails, HTML snippets, etc.
For example, to customize the layout of a page defined in
vendor/magento/module-catalog/view/frontend/layout/catalog_product_view.xml, you need to add layout files with the same name in your custom theme, such as the following:
This is true for extending any layout defined in a
<Namespace>_<Module> Here we are extending
magento/module-catalog . “Magento” is the namespace and “module-catalog” is module. This naming convention is true to extend any module. If you were extending or overriding the checkout module
magento/module-checkout, you would create folder in theme directory
Mytheme/default/Magento_Checkout. Otherwhile, the layout files will have the following format:
Customizing a theme using templates
In Magento templates are the part of the view layer. Templates define exactly how the content of layout blocks are presented on a page: order, CSS classes, elements grouping, & etc. In most cases, templates do not contain any logic about whether they will or will not be rendered, as this is typically handled by the layout XML files. Once a template is called in a layout, it will be displayed.
Default Magento templates are PHTML files. HTML templates are also used for Knockout JS scripts.
Template customization walkthrough
To customize or override a template:
- Locate the template which is associated with the page or block you want to change, using template hints in developer tools. For example, these would be located at:
- Copy the template to your theme folder according to the template storing convention.
- Make the required changes.
To add a new template in a theme:
- Add a template in your theme directory according to the template storing convention. The template folder of the module is
- Assign your template to a block in the corresponding layout xml file.
- Example: Create a template file call
and insert the following code:
<?php /** * @var \Mytheme\Hello\Block\Display $block */ echo $block->sayHello();
In the layout PHTML file, we define the template
Mytheme_Hello::hello.phtml. Magento will look for the file hello.phtml in templates folder of the module Mytheme_Hello.
In the final part of series, Super Guide to Theming Part 3, we will cover customizing layout illustration. This includes moving blocks, setting templates for blocks and creating custom modules for theming. You can always revisit Super Guide to Theming Part 1 as a reference for declaring a child theme and setting up Magento 2 via composer.