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
  • WebFonts

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:

  1. 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.
  2. 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
  3. Modes are set via command line within the root of project directory via ssh.
  • Set mode:php bin/magento deploy:mode:set developer or 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:

  1. In your theme directory, create a web/css/source sub-directory. So in this case, app/design/frontend/Mytheme/default/web/css/source/
  2. Within the source folder create a _extend.less file 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):

  1. In your theme directory, create a web/css/source sub-directory.So in this case: app/design/frontend/Mytheme/default/web/css/source/
  2. Create a _theme.less file 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  _theme.less .

  1. 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.less you should copy from is located at <blank_theme_name>/<blank_area_name>/web/css/source/_theme.less
  2. Make the necessary changes.

To set up local compilation

  • Install Node.js via command line in root directory of magento install.
  • Install grunt npm install -g grunt-cli
  • Install npm packages npm install
  • Add theme to grunt configuration via dev/tools/grunt/configs/theme.js

theme: {
area: 'frontend',
name: 'Mytheme/default',
locale: 'language',
files: [
'path_to_file1',
'path_to_file2'
],
dsl: 'less'
},

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 pub/static and var directories.
  • grunt exec:<theme> : Republishes symlinks of the source files to the pub/static/frontend/<vendor_name>/<theme_name>/<locale> directory.
  • grunt less:<theme> : Compiles less into .css files using the symlinks published in the pub/static/frontend/<vendor_name>/<theme_name>/<locale> directory.
  • grunt watch : Tracks the changes in the source files, recompiles .css files, and reloads the browser page (you need to have LiveReload installed for you browser to reload).

Media queries in Magento default themes

The Blank and Luma theme styles are based upon the Magento UI library. The library uses CSS3 media queries, an extension of the @media rule, to adapt the layout to the screen width.

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.

Media Breakpoints

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:

  • 320px
  • 480px
  • 640px
  • 768px (in the Blank and Luma themes, this breakpoint switches between mobile and desktop views)
  • 1024px
  • 1440px

You can change these breakpoints and add new ones in your custom theme.

Mobile first

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.

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.

Basic layouts

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’ <head> section

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 app/design/frontend/Mytheme/default/Magento_Theme/layout/

Understanding layouts

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 <html><head>, and <body> sections of the HTML page markup
  • Generic layout: an XML file declaring page detailed structure and contents inside the body section 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:

Mytheme/default/Magento_Catalog/layout/catalog_product_view.xml

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: {router_id}_{controller_name}_{action_name}.xml

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:

  1. 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: app/design/<vendor_name>/<module_name>/view/frontend/templates/
  2. Copy the template to your theme folder according to the template storing convention.
  3. Make the required changes.

To add a new template in a theme:

  1. Add a template in your theme directory according to the template storing convention. The template folder of the module is app/code/<vendor_name>/<module_name>/view/frontend/templates/.
  2. Assign your template to a block in the corresponding layout xml file.
  3. Example: Create a template file call hello.phtml
    app/code/Mytheme/Hello/view/frontend/templates/hello.phtml 

    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.

What’s Next?

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.