The key feature of the Magento platform is its modularity. It consists of a number of small elements (modules), which are designed to work both individually and In connection with each other. When all parts are combined, the platform resembles a living organism that consists of a multitude of cells, each having its own function.
To connect these components and to manage their interactions, Magento 2 uses XML layouts and XML page configurations. Each web page of the store has its own XML file, in which a special syntax describes the structure and identifies all the elements necessary for displaying on it.
All the elements used in these files are divided into two types: containers and blocks. According to the standard, containers are mainly used in XML layouts, while in XML configurations blocks are used. It directly depends on the functional load of each.
XML layout serves to position the containers on the entire page, as well as to set the type of view and the structure. Here is an example of an XML template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="columns.top"> <container name="category.view.container" htmlTag="div" htmlClass="category-view" after="-"> <block class="Magento\Catalog\Block\Category\View" name="category.image" template="Magento_Catalog::category/image.phtml"/> <block class="Magento\Catalog\Block\Category\View" name="category.cms" template="Magento_Catalog::category/cms.phtml"/> </container> </referenceContainer> <referenceContainer name="content"> <block class="Magento\Catalog\Block\Category\View" name="category.products" template="Magento_Catalog::category/products.phtml"> <container name="category.product.list.additional" as="additional"/> <block class="Magento\Framework\View\Element\Template" name="category.product.type.details.renderers.default" as="default"/> </block> </block> </block> </page> |
XML configuration distributes each block separately into containers and also assigns each of them its own configurations, which we will see in more detail below.
Often, these two concepts are blurred and it will be all right to combine layout and configuration files into one document. That’s what happens if you add the configuration parameters to the above-mentioned document.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="columns.top"> <container name="category.view.container" htmlTag="div" htmlClass="category-view" after="-"> <block class="Magento\Catalog\Block\Category\View" name="category.image" template="Magento_Catalog::category/image.phtml"/> <block class="Magento\Catalog\Block\Category\View" name="category.description" template="Magento_Catalog::category/description.phtml"/> <block class="Magento\Catalog\Block\Category\View" name="category.cms" template="Magento_Catalog::category/cms.phtml"/> </container> </referenceContainer> <referenceContainer name="content"> <block class="Magento\Catalog\Block\Category\View" name="category.products" template="Magento_Catalog::category/products.phtml"> <block class="Magento\Catalog\Block\Product\ListProduct" name="category.products.list" as="product_list" template="Magento_Catalog::product/list.phtml"> <container name="category.product.list.additional" as="additional" /> <block class="Magento\Framework\View\Element\RendererList" name="category.product.type.details.renderers" as="details.renderers"> <block class="Magento\Framework\View\Element\Template" name="category.product.type.details.renderers.default" as="default"/> </block> <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="category.product.addto" as="addto"> <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare" name="category.product.addto.compare" as="compare" template="Magento_Catalog::product/list/addto/compare.phtml"/> </block> <block class="Magento\Catalog\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml"> <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/> </block> <action method="setToolbarBlockName"> <argument name="name" xsi:type="string">product_list_toolbar</argument> </action> </block> </block> <block class="Magento\Cookie\Block\RequireCookie" name="require-cookie" template="Magento_Cookie::require_cookie.phtml"> <arguments> <argument name="triggers" xsi:type="array"> <item name="compareProductLink" xsi:type="string">.action.tocompare</item> </argument> </arguments> </block> </referenceContainer> <referenceBlock name="page.main.title"> <arguments> <argument name="id" xsi:type="string">page-title-heading</argument> <argument name="add_base_attribute_aria" xsi:type="string">page-title-heading toolbar-amount</argument> </arguments> <block class="Magento\Catalog\Block\Category\Rss\Link" name="rss.link" template="Magento_Catalog::category/rss.phtml"/> </referenceBlock> </body> </page> |
The default layout and configuration files can be found here: module_name/view/frontend/ layout.
More about containers and blocks
Containers in layouts can contain blocks and are designed to effectively position them within the page. The main containers include DOM elements such as:
- head
- header
- main
- aside (left or right)
These elements divide our page layout into containers for conveniently arranging the blocks we need inside them. By default, 5 types of page layouts are pre-installed in Magento 2:
- empty (a page without containers)
- 1 column (one general container for the content)
- 2 column with left bar (a container for content with a left sidebar)
- 2 column with right bar (a container for content with a right sidebar)
- 3 column (3 optional containers)
The highlighted elements in the picture are our containers, we can place any blocks that are necessary on our page in them. Placing the blocks inside is the main distinguishing feature of the <container> element, but it is worth noting that if necessary, the <block> element can also contain other elements and even containers, and thus it automatically becomes a container for its child element. Therefore we can assume that the <container> and <block> elements are absolutely identical to each other, but they still have significant differences in their implementation and methods of working. Further, we will consider the main methods, their similarities and distinctive features.
You should know that no one forbids creating custom layouts. You can select the grid for a specific page either via the admin panel at Content ➜ Pages ➜ Target_Page_Edit ➜ Design ➜ Layout.
or by using an xml layout of the page. To do this, we use a dedicated layout attribute for the <page> container, in which we specify which grid option we want to use on the page.
1 2 3 4 5 6 7 8 9 10 11 |
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="page.main.title"> <arguments> <argument name="id" xsi:type="string">page-title-heading</argument> <argument name="add_base_attribute_aria" xsi:type="string">page-title-heading toolbar-amount</argument> </arguments> <block class="Magento\Catalog\Block\Category\Rss\Link" name="rss.link" template="Magento_Catalog::category/rss.phtml"/> </referenceBlock> </body> </page> |
You can see the use of the <page> and <body> xml tags to configure our page containers, their syntax is very similar to the <html> syntax. Similarly to the html markup, all tags must be closed. In our situation they can be closed either by the </page> or </body> closing tags or they can be self-closing, such as the <block name = ”blockName” /> tag.
All elements can have special attributes to control their parameters. Like containers, for example, have the layout = ”Layout_View_Grid” attribute, in which we specify its 1column value. As for containers and blocks, the lists of attributes and their values are approximately the same:
Common attributes for blocks and containers
Attribute | Value | Description |
name | 0-9, A-Z, a-z и (-)(_)(.)
*Should start with a letter name=”current_name” |
A unique name for addressing is recorded. |
before | (-) an element is displayed before all in the current block.
(element’s name) displaying the element before the element with the specified name. () if the parameter is missing, the element is considered to be non-positioned and is displayed according to the current layout. before=”-” |
This attribute is used to position the elements inside the page layout or inside the container itself. |
after | (-) an element is displayed after all in the current block or container.
(element’s name) displaying the element after the element with the specified name. () if the parameter is missing, the element is considered to be non-positioned and is displayed according to the current layout. after=”target_elemement” |
This attribute is used to position elements inside the page layout or inside the container itself. Has an advantage over before. |
as | 0-9, A-Z, a-z и (-)(_)(.)
*Should start with a letter name=”current_allias” |
The specified name is used to identify the current element in the parent element. |
cacheable | true, false
cacheable=”false” |
Enables and disables caching of pages where the elements with this attribute are located. It’s necessary when creating dynamic elements, widgets and pages. |
*All attributes except name are optional.
Attribute values and their functional load are identical for both blocks and containers. However, containers have methods that are unique only to them:
Container attributes
Attribute | Value | Description |
output | 0 / 1 or true / false
output=”1” |
This attribute is specified in order to determine whether to render the parent container in which the element is located. By default it’s false. |
HtmlTag | Html 5 теги (aside, main, div …)
HtmlTag=”div” |
Everything inside the container will be displayed to the user inside the specified tag. |
htmlId | 0-9, A-Z, a-z и (-)(_)(.)
*Valid only when the HtmlTag value is set. htmlId=”current_id_name” |
The html Id selector for the specified wrapper is installed. |
htmlClass | 0-9, A-Z, a-z и (-)(_)(.)
*Valid only when HtmlTag value is set. htmlClass=”current_class_name” |
The html class selector for the specified wrapper is installed. |
label | Any value | An arbitrary container name is set to display in a browser. |
layout | The value of the page layout template name.
layout=”grid_name” |
It’s used to set the required grid pattern. |
*the attributes are optional
Let’s also consider the parameters for specifying the attributes that are unique to blocks:
Block attribute
Attribute | Value | Description |
class | The path to the class and its name:
class=”Vendor\Folder_Name\Block\Class_Folder\Class_Name” |
This attribute specifies the path to the class that is responsible for processing the information for the current template block. It is used to point a new element to its handler or to overwrite the current program block handler with a custom one. |
template | The path to the template and its name:
template=”Vendor_Name::folder_template/name_template.phtml” |
This attribute specifies the path to the template that is responsible for rendering information for the current layout block. It is used to specify a new element for its template or to overwrite the default template with a custom one. |
*the values are optional
Instructions
The so-called instructions are an additional tool for working with XML file layouts and page configurations in Magento 2. These include the <block> and <container> tags themselves, as well as a number of auxiliary ones. These are the main ones:
referenceBlock and referenceContainer
An instruction that is applied respectively to a block or container in order to pass on the necessary parameters using the following attributes:
Attribute | Value | Description |
name | The name of the target block or container | Indicates the name of the block or container to which the instructions will be passed. |
remove | true/false | Deletes or cancels the deletion of the current block or container. When a container is deleted, all the child elements are deleted as well. |
display | true/false | Turns off or cancels the shutdown of the rendering on the page of the current container or block. When an item is disabled, the further possibility of manipulating it and its child elements is preserved. |
Nested attributes
Magento 2 has several attributes in stock that can be inserted inside, the syntax is familiar to us from the declaration of containers and blocks and looks something like this:
1 2 3 |
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> <move element="category.cms" destination="page.wrapper" after="category.view.container"/> </layout> |
An example of move instructions for rewriting a container position with the name “category.view.container’.
Move
It is an ideal tool for positioning elements on a page and migrating it from one container to another.
Consider an example of the migration of the title block, which displays the current tab in the user account in the top of the main container:
1 2 3 4 5 |
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" > <body> <move element="page.main.title" destination="main" before="-"/> </body> </page> |
Migration of the title block from the account-nav block to the container
Before:
After:
Using only one command in the layout, you can easily change the structure of the entire page, without using styles and working with templates. This instruction includes the following attributes:
- element — the name of the target element to send instructions;
- destination — the name of the parent element to move elements to;
- as — the name of the alias for the element is set for the element after it is moved;
- after/before — is used for positioning inside the target parent element.
Remove
With it, you can remove static resource elements such as blocks with the connection of script files and styles in the <head> container.
Here is an example of its application:
1 2 3 4 5 |
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> <head> <remove src="css/style-m.css"/> </head> </layout> |
deleting previously connected css mapping file
Update
It is recommended to apply it in cases when there is a need on the current page for duplication of all or most of the containers and blocks from the page layout of the parent.
This instruction is specified at the beginning of the XML layout and is used with the handle attribute, which specifies the path and file name of the parent layout. This method is similar in its functionality to the super () method in prototype-oriented programming and performs the same functions. The target layout file will be updated recursively, i.e. sequentially.
For example, in our project, there is a need to connect a slider with certain information on many pages. In this case, it is advisable to create a layout file with the XML markup necessary to connect the slider, which can take the following form:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="page.wrapper"> <!--rev slider--> <container name="page.index.slider.container" htmlTag="div" htmlClass="page-slider-container" before="main.content"> <block class="Nwdthemes\Revslider\Block\Revslider"> <arguments> <argument name="alias" xsi:type="string">Midleton</argument> </arguments> </block> </container> </referenceContainer> </body> </page> |
An example of page layout with a slider connection
In future, we can use this layout as a prototype for our inheritor files. For this, you need to specify a path to the parent layout file for the update directory in each target document.
1 2 3 4 5 6 7 |
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <update handle="{name_of_handle_to_include}"/> <!-- CONTENT --> </body> </page> |
recursive layout update
Thus, we will see our slider on each page, where the update directive will be indicated with the slider connection file as a prototype.
Argument
The tag is used to pass arguments to the container or block.
It has the required name and type tags. The type of the passed element is passed to type:
- string
- boolean
- object
- number
- null
- array
For example, earlier in the user account, we moved our title from the header to the main container, now we need to set a custom string for the myDashboard title tab. To do this, we open the layout responsible for the myDashboard page and with the help of the action directive and the setPageTitle method we pass the string with the necessary title for our page as an argument:
1 2 3 4 5 |
<referenceBlock name="page.main.title"> <action method="setPageTitle"> <argument translate="true" name="title" xsi:type="string">Hello, Customer!</argument> </action> </referenceBlock> |
passing the parameter as a string for page-title
We specified a string as a type and passed the required text as a string. We get what we aimed for as a result:
The transmitted values can also be accessed from the current template file using the get() method. This functionality perfectly corresponds to the principles of universality and modularity in Magento. By using it, you can create a universal and dynamic template for applying in several places on our store, just like in the example of a universal layout with a slider connected to the pages.
As an example, let’s consider creating a template with a button rendering with any functionality on the client. We will use the same template on different pages, but depending on the requirements, we can transfer to it the CSS class, to which some style from the style sheet can be attached or even the functional load implemented on js. Here is how it will look like in the markup:
1 2 3 4 5 |
<block class=”Magento\Framework\View\Element\Template" name="button" template="Magento_Theme::buttons/dynamic_button.phtml" > <arguments> <argument name="css_class" xsi:type="string">white</argument> </arguments> </block> |
Passing a custom argument to the template
To pass a class, we declare our block and specify our template to it in the template attribute, which we will consider it later. After that, we simply pass any parameters to the template as arguments, and to pass multiple parameters we use the <arguments> container and the <argument> blocks enclosed in it. We passed our class as an argument named css_class. In order to get it in the template file, you need to resort to the knowledge of PHP and write the following structure:
1 2 3 4 |
$_className = $block->getCssClass(); <div class="actions-toolbar <?= $_className ?>"> <button class="action primary">Button</button> </div> |
An example of the method used to get the argument that was passed from the template
Further, depending on the written logic, the button may accept different modifications on different pages. In this example it became white.
In fact, this is the simplest example of using this functionality, which is necessary to learn the principle of its work. By using the method of passing arguments, you can do many useful things, including passing the argument that will determine the controller to process our template.
There can be any arguments with any names and it is possible to pass not only a string but also 6 basic data types as mentioned earlier. In order to get the attributes in the template, the function takes the following form:
getCssClass();
The name parameter passed in xml in the form of “css_class”, takes the CamelCase form and looks like “СssClass”. This method is similar to the method of passing arguments in JavaScript by using data attributes.
Thus, Magento 2 has a huge range of tools for managing page layouts and making it easier to change page configurations and adjust it to the necessary parameters. Having mastered the principles of working with them, a Magento 2 developer opens up the possibility to customize the user interface and unified code structure more quickly and easily, so that its further support and expansion bring pleasure not only for themselves but also for subsequent developers.
Need an expert Magento development team? BelVG is here to help you.