Magento 2 Containers and Blocks

term-blocks-contentMagento 2 has introduced containers in addition to blocks in layout files. This post is a bit of background of why, with an invitation to share your perspective.


In case you are not familiar with the Magento 2 page layout engine, here is a quick summary. This is very similar to Magento 1, but there have been a few tweaks.

A page that a user sees is built from a tree of “structural elements” (blocks and containers). To generate the HTML for a page, the structural element tree is rendered into HTML. Each structural element is asked to produce a fragment of HTML for the final page. During rendering, structural elements can ask children for their HTML to merge into the final result.

The reason for layouts is to make it easy for a module to add something to a page introduced by another module. For example, when viewing a product maybe you want to add into the side bar a link to any blog posts you have written on the product. This sort of manipulation in Magento is done at the structural element level (blocks and containers), not the HTML level. Every structural element can declare a global name (stored in the ‘name’ attribute in a layout XML file) that is used for such cross references. (To me, this ‘name’ is like an ‘id’ in HTML.)

More precisely, layout files actually contain layout instructions. Normally you declare changes you want to apply to the structure element tree that has been built up so far. For example, you can reference a container somewhere in the tree by name and add another child block to it. You can also move elements in the tree. <referenceContainer> and <referenceBlock> are the most common layout instructions which locate a container or block in the tree by ‘name’, then manipulate that element (frequently by adding or replacing children structural elements). Layout instructions are not the focus of this blog post, so I don’t mention them much further. I also don’t mention here the difference between pages, page layouts, and layout instructions.

Blocks vs Containers

Those familiar with Magento 1 will be familiar with blocks. Typically a block has a PHP class and a PHTML template file used to generate the HTML for the block. Methods of the PHP block class can be called from the PHTML template file to keep the amount of PHP in the PHTML file minimal.

There are two common patterns in Magento – a block can have a set of named children, or it can have an array of unnamed children. In Magento 2, these two patterns have been split into Blocks and Containers. (You can still find some old-style blocks with an array of children, such as Magento\Framework\View\Element\Html\Links. Ideally these would be all converted to the new approach.)

For example, the block Magento\Customer\Block\Account\Forgotpassword allows for a child structural element ‘form_additional_info’. The current terminology is to call this an ‘alias name’ – conceptually I think of it as a parameter name to reference child elements. Blocks can have both ‘arguments’ (configuration settings specified in <argument> elements in the layout file) and children structure elements (blocks/containers). The ‘as’ attribute of the child structural element holds the ‘alias name’ used by the parent block to find a child element by name. The forgot password child element allows other layout files to inject some additional content into the “I forgot my password” page.

Containers do not use the ‘as’ attribute on its children. The children are just an array to be displayed in order – there is no need to name them. Attributes ‘before’ and ‘after’ are used to help place children of containers relative to each other. Containers also do not have a PHTML file. All the cases examined so far had very simple markup, so the HTML markup to be generated by a container is currently held in attributes such as ‘htmlTag’ and ‘htmlClass’ of the <container> element.

     label="Form Fields Before"

So what if you want a block to have a group of zero or more children? The answer is to put a container under a block. The container will have an ‘as’ attribute that the block refers to.

In Magento 1 there were no containers. The implementation of a block just asked for a child element by name or it asked for all children. That is, blocks did the job of a container as well. The reason for the split in Magento 2 was to help introduction of a visual design tool. (This tool is not being delivered as part of Magento 2.0 due to resource constraints.) Having blocks with named children and containers with zero or more unnamed children makes development of such a tool easier.

Possible Changes

The following are some ideas that have floated around, but not considered important enough to make. This is where your voice can be heard – leave a comment if you think any of these changes are worth doing, or have a better recommendation.

  • One could consider changing the ‘name’ attribute of blocks and containers to ‘id’ to better reflect that it is globally unique in the structural element tree. <referenceBlock> and <referenceContainer> elements could then have a ‘ref’ attribute (rather than the current ‘name’ attribute) to reference an ‘id’.
  • I find myself referring to ‘as’ attributes as the child name (rather than ‘alias name’). The term ‘alias’ is not really the right concept to me. It is not an alternative way to reference the child – it is the only way a parent block references a child. The only problem with ‘child name’ is that it’s easy confused with the current ‘name’ attribute (a further reason for the previous bullet point of renaming ‘name’ to ‘id’).
  • Remove the ability for blocks to have an array of children by removing the function to fetch all children. This would help ferret out the few remaining blocks with arrays of children. Each should be changed to a container.
  • Or maybe you think blocks should still be able to have an array of children. In that case, the current APIs to accessing children does not allow access to children as an array without also picking up all named children. Maybe the function to return all children should only pick up those without an ‘as’ attribute set.
  • Rename the <update> layout instruction in layout files (not mentioned above) to say <include> to better explain what the element does. Ok, unrelated to the rest of this blog post but it always annoyed me!😉  Currently you say <update handle=’xxx’> which does not update the referenced handle – instead it includes the instructions in the referenced layout file into the current file.
  • The XML Schema (XSD file) for layouts could be tightened up so the ‘as’ attribute is only permitted on <block> and <container> elements under <block> and <referenceBlock>. At present the ‘as’ attribute is allowed in many places where it has no meaning. This has led to some Magento layout files specifying the ‘as’ attribute in the wrong place by accident. This should be cleaned up to reduce confusion.
  • Unrelated again to this blog post, the XML Schema also allows some nesting of <referenceBlock> and <referenceContainer> elements that serves no semantic purpose. For example, a <referenceBlock> inside a <referenceBlock> actually has no meaning. They should be siblings, allowing nesting to have some meaning in a future release.
  • Add metadata to each block (a new function?) to return documentation about the block, the ‘alias’ names it supports for child elements, and the <argument> markup the block supports. Then develop a tool to print out this information for all available blocks for online documentation.
  • If blocks did have metadata available as to the legal children alias names, this could be verified in a structure element tree to spot spelling errors in ‘as’ attribute values (in developer mode).
  • For the brave, consider implementing an interactive layout file editor that can manipulate layout files and hence the structural element tree. The challenge here you need to capture the instructions to manipulate a tree, not just capture the final tree itself. But a tool that could show the final tree while editing the layout instructions (using the metadata from the previous point) would be kinda cool.


The purpose of this blog post was to clarify the reason for separating containers from blocks. While Magento 2.0 will not have a visual design editor, it is not ruled out for a future release.

I also snuck in a few personal favorite little changes that I would like to make, but do not have the clear business value to make them worth the cost of implementing. We may do some, but no guarantees. If you think they are worth introducing, or any other related changes, feel free to leave a comment.


  1. Matthias Zeis · · Reply

    Hi Alan,

    I like these ideas:

    * changing the ‘name’ attribute to ‘id’
    * introducing a ‘ref’ attribute instead of ‘name’ for and >referenceContainer>
    * “Remove the ability for blocks to have an array of children by removing the function to fetch all children.”
    * Rename to .

    While these wordings shouldn’t be a problem if you worked with Magento for some time, it’s easier for beginners to get started with it. Also, the similarity with the HTML attributes may help.

    Concerning the alias name / “child name”: I always wondered if there isn’t a way to solve this with only one name. If the “name” (or “id”) is unique, this could be possible. I personally didn’t experience name conflicts when using 3rd-party extensions in M1 so this wouldn’t be a big concern for me.

    1. Regarding alias name vs name/id for children, the theory is blocks can be generic so the ‘alias’ is like a function parameter name. The ‘name’ attribute is like a global variable.

      1. Matthias Zeis · ·

        In practice I saw that most devs use pretty much the same string for the name/id and the alias. The alias may be simplified sometimes.

    2. “I personally didn’t experience name conflicts when using 3rd-party extensions in M1 so this wouldn’t be a big concern for me”

      I don’t think there were conflicts either, but there would be if you cross checked all the values of the “as” attribute for uniqueness… even amongst core. The “as” is unique amongst siblings, the “name” globally unique. I like to think of “as” as a nickname that I call that block as it’s familiar “parent”

  2. Jason Neumann · · Reply

    I may be misunderstanding these lines:
    “Containers do not use the ‘as’ attribute on its children. The children are just an array to be displayed in order – there is no need to name them. Attributes ‘before’ and ‘after’ are used to help place children of containers relative to each other.”
    But if i take them as I see it now I disagree. I think child blocks of containers should be required to have the as attribute and the parent container should use that in its ordering.

    A problem I have run into in Magento 1 is while trying to add a block using the ‘before’ or ‘after’ attributes and i can’t use the names of the other blocks because they are random numbers like ‘group_27’. Hardcoding that number into the layout xml will almost guarantee it to break when the extension is added to a different installation.

    I think containers should print the blocks in the order they are received unless a before or after attribute is specified, that attribute should reference the name of the other children so you can guarantee consistency across different installations. if the name isnt found among the current children, then the block is placed at the end like a block without a before or after attribute.

    1. I believe names like ‘group_27’ occurs when no ‘name’ attribute has been set. Using that name in before/after clauses I agree is ‘evil’ and likely to break.

      If you suggest children of containers should use ‘as’, what should they be set to? And then why not just use the ‘name’ attribute instead?

      I think the default behavior is much like what your last paragraph says – there is a consistent default position.

  3. I am all for the following:

    * changing “name” to “id” — although very semantical, it makes a ton of sense, and I see folks assume that “name” should be what a block references a child as. Name (as a concept) is generally not unique, but an id is. Nobody has the same SSN, but many of us have the name David. If it weren’t for possibly confusing former M1 developers, I’d say “name” -> “id” and what’s currently “as” change to “name”

    * Supporting arrays of children in blocks will encourage theme vendors to continue using blocks where containers should otherwise be used. I would like to see them have an exclusive purpose.

    * Renaming “update” to “include” — You don’t know how many times I’ve had to explain this as being semantically incorrect to a less experienced developer…

    * Removing support for nested <reference nodes. It doesn't make sense to nest them and it confuses the intent of the markup

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: