Magento uses containers and blocks to structure the layout of a page. Containers define the structure of the page and do not contain any additional content, and occasionally you may need to go about adding Magento 2 containers that contain custom functionality from the blocks that reside within these containers.
In order to do this, specify a <container>
node within your layout file. Usually, a container definition will reside within the pair of <body>
nodes.
In the example below, a container has been defined that will render above the footer.container
container.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <container name="custom.container" as="customContainer" label="Custom Container" htmlTag="div" before="footer.container" htmlClass="row" /> </body> </xml>
The minimum requirements for defining a container is that the node should contain the name
attribute. The additional attributes are not required, however they may be useful to use.
In order to specify whether your custom container should render before or after an existing container, it is essential to know the names of the containers that Magento defines by default.
You could by looking at the vendor/magento/module-theme/view/frontend/page_layout/1column.xml
file, which defines three containers: header.container
, page.top
and footer.container
while referencing a page.wrapper
container.
<?xml version="1.0"?> <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> <update handle="empty"/> <referenceContainer name="page.wrapper"> <container name="header.container" as="header_container" label="Page Header Container" htmlTag="header" htmlClass="page-header" before="main.content"/> <container name="page.top" as="page_top" label="After Page Header" after="header.container"/> <container name="footer-container" as="footer" before="before.body.end" label="Page Footer Container" htmlTag="footer" htmlClass="page-footer"/> </referenceContainer> </layout>
The vendor/magento/module-theme/view/base/page_layout/empty.xml
also contains some useful container names.
<?xml version="1.0"?> <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> <container name="root"> <container name="after.body.start" as="after.body.start" before="-" label="Page Top"/> <container name="page.wrapper" as="page_wrapper" htmlTag="div" htmlClass="page-wrapper"> <container name="global.notices" as="global_notices" before="-"/> <container name="main.content" htmlTag="main" htmlId="maincontent" htmlClass="page-main"> <container name="columns.top" label="Before Main Columns"/> <container name="columns" htmlTag="div" htmlClass="columns"> <container name="main" label="Main Content Container" htmlTag="div" htmlClass="column main"/> </container> </container> <container name="page.bottom.container" as="page_bottom_container" label="Before Page Footer Container" after="main.content" htmlTag="div" htmlClass="page-bottom"/> <container name="before.body.end" as="before_body_end" after="-" label="Page Bottom"/> </container> </container> </layout>
One advantage of containers in Magento 2 over the structural blocks used in Magento is that within Magento 2, you do not have to add any further instructions to get the container to render (like using $this->getChildHtml()
within the template’s .phtml
file in M1).
With that said, your container will need some actual content within it in order for Magento to use the container within the page layout.
For example, to define a block within the container, you could write the following.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <container name="custom.container" as="customContainer" label="Custom Container" htmlTag="div" before="footer.container" htmlClass="row"> <block class="Magento\Framework\View\Element\Template" name="yourtheme.block.name" before="-" template="Magento_Theme::page/page.phtml"/> </container> </body> </page>
You’ll then have some content within your container that Magento will render wherever you specify.
If you need to include an empty container for whatever reason, you could define a block which has a class of Magento\Framework\View\Element\Text
. Then, include a text
argument that includes an empty HTML comment.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <container name="custom.container" as="customContainer" label="Custom Container" htmlTag="div" before="footer.container" htmlClass="row"> <block class="Magento\Framework\View\Element\Text" name="comment.placeholder"> <arguments> <argument name="text" xsi:type="string"><![CDATA[<!-- -->]]></argument> </arguments> </block> </container> </body> </page>
Similarly, you could use <![CDATA[ ]]>
in place of the empty HTML comment. Not the cleanest solution, but one that will render an empty container that you need.
Note: This article is based on Magento Open Source version 2.2.