Changing a layout XML of a Magento 2 module

In order to customize the layout to your own requirements, you can just add it to your theme and make the required changes. In order to change a layout from a Magento 2 module, you will need to locate the module and layout handle that you want to alter.

The following steps will show you how to change elements defined in a layout file to match your desired design:

  1. Create the layout handle file for the Magento_Catalog module:


[code language=”xml”]

<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<move element="" destination="" after=""/>
<move element="" destination="" before=""/>

<remove name="report.bugs"/>


  1. Upload the file to your Magento 2 installation and refresh the cache:
    bin/magento cache:clean
  2. Next, generate the static content:
    bin/magento setup:static-content:deploy
    Make sure that you remove your theme-generated files from the following locations:
    pub/static/frontend/ var/view_preprocessed/css/frontend/
    Otherwise, the changes in the Less files in your theme will not be used as the preprocessor checks if there is already a generated CSS file available.
  3. Navigate to a product page to see the changed position of stock info and SKU

How does it work…

In the layout XML files, there are a few commands available to change the way in which a page is rendered. Here is a short description of every available command.


A container defines a structural layout block that does not produce its own content and can hold other blocks and/or containers. The output of the content generated by the children can be rendered in any valid HTML 5 tag with the option to specify an ID or class used for the element. Here is an example of the container and the blocks that are added:

[code language=”xml”]

<container name="" label="Product auxiliary info" htmlTag="div" htmlClass="product-info-stock-sku">
<container name="" before="-"/>
<block class="Magento\Catalog\Block\Product\View\Description" name="" template="product/view/attribute.phtml" after="">
<argument name="at_call" xsi:type="string">getSku</argument>
<argument name="at_code" xsi:type="string">sku</argument>
<argument name="css_class" xsi:type="string">sku</argument>
<argument name="at_label" xsi:type="string">default</argument>
<argument name="add_attribute" xsi:type="string">itemprop="sku"</argument>


A block generates content from the specified class and assigned template file. In the arguments of the block, it’s possible to specify the load order using the before and  after tags. Depending on the class specified, it’s possible to pass information using the  &lt;argument&gt; tag:

[code language=”xml”]

<block class="Magento\Catalog\Block\Product\View\Description" name="" template="product/view/attribute.phtml" group="detailed_info" after="">
<argument name="css_class" xsi:type="string">overview</argument>


Arguments passed to the class can be the class methods or magic setters/getters and can be accessed in the template. The preceding css_class argument assigned can be requested in the template through $this-&gt;getCssClass(); .


In order to add a block or container to an element specified in another layout file, you will need to reference this element. This way it’s possible to add blocks to both the main content area and sidebar in the same layout file:

[code language=”xml”]

<referenceContainer name="">
<block class="Magento\Catalog\Block\Product\View\Type\Simple" name="" as="product_type_data" template="product/view/type/default.phtml"/>
<container name="" after="" as="product_type_data_extra" label="Product Extra Info"/>



The move command allows you to change the location where the element is shown to another element. In this recipe, the SKU information was placed after the block in the container, where the default location would be the first block shown.


The remove command will remove the block referenced with the name parameter; this will cause it not to be rendered on the page.


With the update instruction, it is possible to include a layout handle. This allows you to include
a set of instructions defined once to multiple layouts. An example of this is the customer
account; here, all account menu options for logged in users are defined in the customer_account.xml layout file:

[code language=”xml”]

<page xmlns:xsi="" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Customer My Account (All Pages)" design_abstraction="custom">
<attribute name="class" value="account"/>
<referenceContainer name="sidebar.main">

<block class="Magento\Framework\View\Element\Html\Links" name="customer_account_navigation" before="-" template="Magento_Customer::account/navigation.phtml">
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-account-link">
<argument name="label" xsi:type="string" translate="true">Account Dashboard</argument>
<argument name="path" xsi:type="string">customer/account</argument>
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-account-edit-link">
<argument name="label" xsi:type="string" translate="true">Account Information</argument>
<argument name="path" xsi:type="string">customer/account/edit</argument>
<block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-address-link">
<argument name="label" xsi:type="string" translate="true">Address Book</argument>
<argument name="path" xsi:type="string">customer/address</argument>


This file is then included in the customer_account_index.xml layout (and other pages using this menu):

[code language=”xml”]

<page xmlns:xsi="" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="customer_account"/>
<referenceBlock name="page.main.title">

<action method="setPageTitle">
<argument translate="true" name="title" xsi:type="string">My Dashboard</argument>
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template" name="customer_account_dashboard_top" as="top"/>
<block class="Magento\Customer\Block\Account\Dashboard\Info" name="customer_account_dashboard_info" as="info" template="account/dashboard/info.phtml" cacheable="false"/>
<block class="Magento\Customer\Block\Account\Dashboard\Address" name="customer_account_dashboard_address" as="address" template="account/dashboard/address.phtml" cacheable="false"/>


Overriding template files

Templates are loaded in the following order:

  1. Active theme, where it looks for the file in &lt;theme&gt;/&lt;Module_Namespace&gt;_&lt;Module_name&gt;/template/&lt;requested template&gt; .
  2. Parent theme(s) (until no parent is found).
  3. Module directory.

In order to override a template in your theme, it is possible to create your own version of the file. For example, to replace the left navigation file from the catalog module, copy the file from the original location &lt;Magento_Catalog path&gt;/view/frontend/templates/navigation/left.phtml to your theme location &lt;theme&gt;/Magento_Catalog/templates/navigation/left.phtml . Here, you can apply your own changes necessary to suit your theme.

Another option is to change the template file assigned through a layout change; this can be useful if you want to change the template only for a specific product, category, or other page handle available. For this, you need to create a new layout file based on the file handle where you reference the block where you want to update the template. Using the &lt;action&gt; method, setTemplate , you can now specify the new template you want to use:

[code language=”xml”]

<referenceBlock name="[blockname]">
<argument name="template" xsi:type="string">[Module name]::[path to template]</argument>



Creating a Magento 2 Theme

In order to understand the way theming is done, you should know how to work with Less, CSS,
XML, and PHP.

Creating a new theme

In this sample theme, the files are located in app/design/frontend/<Vendor>/<Theme> .

When a theme is installed through Composer, it will be installed in the vendor directory.

The following are the steps to create a new theme:

  1. First, we start by creating the theme definition file:

[code language=”xml”]
<?xml version="1.0"?>
<theme xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
<title>Magento2 Training Sample Theme</title>

  1. Create preview.png for how your theme will look like. (This file needs to be present, but you can start with a blank file and replace this later when your theme is done.) Place this preview image under app/design/frontend/Nhd/default/media/ .
  2. In order to have it installable through Composer, we need to create a composer.json file:

[code language=”javascript”]

"name": "genmato/sample-theme",
"description": "Nhd Sample Theme",
"require": {
"php": "~5.5.0|~5.6.0|~7.0.0",
"magento/theme-frontend-blank": "100.0.*",
"magento/framework": "100.0.*"
"type": "magento2-theme",
"version": "1.0.0",
"license": [
"autoload": {
"files": [


  1. In order to register the theme when loaded through Composer, it needs registration.php :

[code language=”php”]

  1. Create a static file directory structure in your theme:


  1. Define your logo file and size:

[code language=”xml”]

<?xml version="1.0"?>
<page xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<referenceBlock name="logo">
<argument name="logo_file" xsi:type="string">
<argument name="logo_img_width" xsi:type="number">
<argument name="logo_img_height" xsi:type="number">
<referenceBlock name="report.bugs" remove="true"/>


  1. Place your logo file in app/design/frontend/Genmato/default/web/images/; in this example, an SVG is used but you can also define a PNG or JPG file
  2. It is possible to configure your own image sizes for the different images; when generating the static content, all images will be created in the width/height configured in this file:

[code language=”xml”]
<?xml version="1.0"?>
<view xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd">
<images module="Magento_Catalog">
<image id="category_page_grid" type="small_image">

  1. Create your theme style (Less) file. In this file, all overrides for styles used in the blank theme and Magento UI framework can be specified. This can be used to change default colors in your theme:

@page__background-color: @color-gray20;
@primary__color: @color-gray80;
@genmato__green: #009A4E;
@genmato__blue: #0089CF;
@link__color: @genmato__green;
@link__hover__color: darken(@link__color, 10%);
@button-primary__background: @genmato__green;
@button-primary__border: darken(@genmato__green, 40%);
@button-primary__color: @color-black;
@button-primary__hover__background: darken(@genmato__green, 10%);
@button-primary__hover__border: darken(@genmato__green, 50%);
@button-primary__hover__color: @color-black;
@navigation__background: @genmato__blue;

  1. After all the files are uploaded to the Magento 2 installation, refresh the cache:
    bin/magento cache:clean
  2. Next, generate the static content:
    bin/magento setup:static-content:deploy

You can rerun this command every time you make changes to your theme and need to regenerate the CSS from the Less files. Make sure that you remove your theme-generated files from the following locations:
pub/static/frontend/&lt;Theme Vendor&gt;var/view_preprocessed/css/frontend/&lt;Theme Vendor&gt;
Otherwise, the changes in the Less files in your theme will not be used as the preprocessor checks if there is already a generated CSS file available.
Check the Using Grunt for CSS changes section of this tutorial on how to use live reloading of CSS changes without the need of recompiling.

  1. The theme should now be available to select for your store. In order to change the theme, go to the following:
    Stores | [General] Design | Design Theme
    Choose the newly created theme from the drop-down list and save the configuration change.
  2. Navigate to your store frontend and check whether the new theme is visible.

How does these new Magento theme work?

The theme configuration in Magento 2 is more powerful than in Magento 1, allowing you to have better control on changing elements that are available from installed modules. The way in which the fallback is configured makes it easier to create different variants of a theme by defining the parent theme only. During compilation of the theme, all the files are gathered from the right parent and merged into your theme. This improves page rendering as there is no more layout merging done. All static elements such as CSS and images are pregenerated. Building themes for distribution and changing them afterward is now also much easier and can be done without modifying the bought theme.

During the bin/magento setup:static-content:deploy command, the system collects all the Less files from the following:

  • Current active theme
  • The defined parent theme(s); this is done recursively for all parents until there is no parent defined
  • The module files

Next, it will use the built-in PHPLess module to merge all these files into the configured CSS files. In this example, it generated a styles-m.css and styles-l.css as configured in the blank theme ( Magento/blank/Magento_Theme/default_head_blocks.xml ):

[code language=”xml”]

<page xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<css src="css/styles-m.css" />
<css src="css/styles-l.css" media="screen and (min-width: 768px)"/>
<css src="css/print.css" media="print" />


The styles files are built from styles-m.less and styles-l.less (found in Magento/blank/web/css/ ) and define all the Less files that should be included. The two files are the definition files for the mobile and desktop versions of the layout. These external Less files are included through the default @import command used in Less. They also contain a special @magento_import command (which has to be commented out in order to avoid breaking the Less preprocessor). During compilation of the theme, Magento replaces these imports with a regular @import command but with a resolved path to the corresponding file location based on the fallback file found. During compilation, all files are stored at the pub/static/frontend/&lt;Vendor&gt;/&lt;theme&gt; location and served as static files to improve load times.

Adding theme variants

Creating a variant of a theme, for example, for seasonal promotions, is easy to add. Here, it is only necessary to create a new theme that has a parent to the default/normal theme; all separate themes need to be located in their own directories. The theme only needs the files that are different from the parent theme; this can be just CSS changes or static files used as backgrounds in the theme.

Layout files

In Magento 2, the layout files are split per layout handle; this makes it easier to modify a specific page only. A layout handle is a unique identifier for the layout definitions that are used to build the page. There are three different types of layout handles:

  • page type layout handles: These identify the page based on the full action names of the controller ( customer_account_create )
  • page layout handles: These are added identifiers based on a product type shown ( catalog_product_view_type_downloadable )
  • custom handles: These are added custom identifiers not referencing to any page

Every file is located in the corresponding Module directory, so for the customer_account_create page handle, the layout file would be located in [Theme Directory]/Magento_Customer/layout/customer_account_create.xml . In the design and building of the pages, the layout is configured based on containers and defines the basic structure of a page (such as the header, footer, and columns—left, main, and right). In the containers, the content is added using blocks ; every block has a template and block class assigned that is used to render the HTML for that block. It is possible to have multiple blocks assigned to a single container, allowing you to assign the order in which they must be shown. During generation, all layout files are merged together for each layout handle, allowing you to modify the output in the theme without the need of including the complete original files from the module.

Template files

Template files are phtml files containing the HTML and PHP code to build the specified content. In order to change or add data with a template in your theme, you will need to copy the original template file to your theme, for example, to change the account registration form, the &lt;customer-module-dir&gt;/view/frontend/templates/form/register.phtml file needs to be copied to &lt;theme-dir&gt;/Magento_Customer/templates/form/register.phtml and can be edited there.

Magento UI library

In Magento 2, there is a UI library available that includes basic interface CSS-class elements that can be used in the templates. The following components are available:

  • actions-toolbar
  • breadcrumbs
  • buttons
  • drop-downs
  • forms
  • icons
  • layout
  • loaders
  • messages
  • pagination
  • popups
  • ratings
  • sections
  • tabs and accordions
  • tables
  • tooltips
  • typography
  • list of theme variables

The CSS definition of all these elements can be altered to find out what variables to alter; check out &lt;magento-root&gt;/lib/web/css/source/lib/variables . In order to modify the way an element is rendered, you can look up the required variable and add your own definition in the &lt;theme-directory&gt;/web/css/source/_theme.less theme file.

Magento 2 System Tools

Using bin/magento and Composer is one of the new key features in Magento 2 that will rock
your world.

Here is an overview of all the command-line tools in Magento 2:

[code language=”bash”]

root@magento2training:/var/www/html# php bin/magento
Magento CLI version 2.0.2

command [options] [arguments]

–help (-h) Display this help message
–quiet (-q) Do not output any message
–verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
–version (-V) Display this application version
–ansi Force ANSI output
–no-ansi Disable ANSI output
–no-interaction (-n) Do not ask any interactive question

Available commands:
help Displays help for a command
list Lists commands
admin:user:create Creates an administrator
admin:user:unlock Unlock Admin Account
cache:clean Cleans cache type(s)
cache:disable Disables cache type(s)
cache:enable Enables cache type(s)
cache:flush Flushes cache storage used by cache type(s)
cache:status Checks cache status
catalog:images:resize Creates resized product images
cron:run Runs jobs by schedule
customer:hash:upgrade Upgrade customer’s hash according to the latest algorithm
deploy:mode:set Set application mode.
deploy:mode:show Displays current application mode.
dev:source-theme:deploy Collects and publishes source files for theme.
dev:tests:run Runs tests
dev:urn-catalog:generate Generates the catalog of URNs to *.xsd mappings for the IDE to highlight xml.
dev:xml:convert Converts XML file using XSL style sheets
i18n:collect-phrases Discovers phrases in the codebase
i18n:pack Saves language package
i18n:uninstall Uninstalls language packages
indexer:info Shows allowed Indexers
indexer:reindex Reindexes Data
indexer:set-mode Sets index mode type
indexer:show-mode Shows Index Mode
indexer:status Shows status of Indexer
info:adminuri Displays the Magento Admin URI
info:backups:list Prints list of available backup files
info:currency:list Displays the list of available currencies
info:dependencies:show-framework Shows number of dependencies on Magento framework
info:dependencies:show-modules Shows number of dependencies between modules
info:dependencies:show-modules-circular Shows number of circular dependencies between modules
info:language:list Displays the list of available language locales
info:timezone:list Displays the list of available timezones
maintenance:allow-ips Sets maintenance mode exempt IPs
maintenance:disable Disables maintenance mode
maintenance:enable Enables maintenance mode
maintenance:status Displays maintenance mode status
module:disable Disables specified modules
module:enable Enables specified modules
module:status Displays status of modules
module:uninstall Uninstalls modules installed by composer
sampledata:deploy Deploy sample data modules
sampledata:remove Remove all sample data packages from composer.json
sampledata:reset Reset all sample data modules for re-installation
setup:backup Takes backup of Magento Application code base, media and database
setup:config:set Creates or modifies the deployment configuration
setup:cron:run Runs cron job scheduled for setup application
setup:db-data:upgrade Installs and upgrades data in the DB
setup:db-schema:upgrade Installs and upgrades the DB schema
setup:db:status Checks if DB schema or data requires upgrade
setup:di:compile Generates DI configuration and all non-existing interceptors and factories
setup:di:compile-multi-tenant Generates all non-existing proxies and factories, and pre-compile class definitions, inheritance information and plugin definitions
setup:install Installs the Magento application
setup:performance:generate-fixtures Generates fixtures
setup:rollback Rolls back Magento Application codebase, media and database
setup:static-content:deploy Deploys static view files
setup:store-config:set Installs the store configuration
setup:uninstall Uninstalls the Magento application
setup:upgrade Upgrades the Magento application, DB data, and schema
theme:uninstall Uninstalls theme

Magento 2 After Installation configuration

Cron setup:

See magento user’s cron list:

Edit magento user’s cron:

(To find php binary and php.ini which php)

(In php 7, ini file is at  /etc/php/7.0/apache2/php.ini)

Set Magento environment to developer mode: