Skip to content
intermediate Phase 54 · Frontend Components

Layout Handles

Understanding Magento 2 layout handles: default, cms_index_index, catalog_product_view, custom handles, and handle hierarchy

45m
0 problems
Topic Progress 0%

Default and Core Handles

Handle Types

Handle Example When Loaded
default default Every page
base base Every page (frontend)
core_update core_rss_index RSS feeds
route catalog_product_view Product view page
action catalog_product_view_id_5 Specific product
theme frontend_theme_name Theme-specific

Default Handle

Loaded on every page:

<!-- default.xml -->
<?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>
        <referenceBlock name="header" remove="true"/>
    </body>
</page>

Base Handle

Also loaded on every page (frontend):

<!-- base.xml -->
<page>
    <body>
        <container name="root" htmlTag="div" htmlClass="page-wrapper">
            <block class="Magento\Theme\Block\Html\Header" name="header"/>
            <block class="Magento\Theme\Block\Html\Footer" name="footer"/>
        </container>
    </body>
</page>

Route Handles

Format: {area}_{route}_{controller}_{action}

Examples:

  • cms_index_index — Homepage
  • catalog_product_view — Product page
  • catalog_category_view — Category page
  • checkout_index_index — Checkout page

CMS and Catalog Handles

CMS Handles

<!-- cms_index_index.xml (Homepage) -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
      layout="1column">
    <body>
        <referenceContainer name="content">
            <block class="Magento\Cms\Block\Block" name="homepage-banner">
                <arguments>
                    <argument name="block_id" xsi:type="string">homepage-banner</argument>
                </arguments>
            </block>
        </referenceContainer>
    </body>
</page>

<!-- cms_page_view.xml (All CMS pages) -->
<page>
    <body>
        <referenceContainer name="content">
            <block class="Magento\Cms\Block\Page" name="cms_page"/>
        </referenceContainer>
    </body>
</page>

Catalog Product Handles

<!-- catalog_product_view.xml (All product pages) -->
<page>
    <body>
        <referenceBlock name="product.info">
            <block class="Vendor\Module\Block\Warranty" name="warranty"/>
        </referenceBlock>
    </body>
</page>

<!-- catalog_product_view_id_5.xml (Specific product) -->
<page>
    <body>
        <referenceBlock name="product.info">
            <block class="Vendor\Module\Block\Special" name="special"/>
        </referenceBlock>
    </body>
</page>

Catalog Category Handles

<!-- catalog_category_view.xml -->
<page>
    <body>
        <referenceContainer name="content">
            <block class="Vendor\Module\Block\CategoryWidget" name="category.widget"/>
        </referenceContainer>
    </body>
</page>

Custom Layout Handles

Creating Custom Handles

Via XML Layout Files

<!-- vendor_module_index.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
      layout="2columns-left">
    <body>
        <referenceContainer name="content">
            <block class="Vendor\Module\Block\Dashboard" name="dashboard"/>
        </referenceContainer>
    </body>
</page>

Via Layout Processor

<?php
namespace Vendor\Module\LayoutProcessor;

use Magento\Framework\View\Layout\Argument\BuilderInterface;

class CustomHandle
{
    public function process(array $layout): array
    {
        if ($this->isCustomPage()) {
            $layout['xml'] .= '<handle name="custom_handle"/>';
        }
        return $layout;
    }
}

Via Controller Action

public function execute()
{
    $this->layout->getUpdate()->addHandle('custom_handle');
    return $this->resultPageFactory->create();
}

Dynamic Handles

// Add handle based on condition
if ($this->isPreviewMode()) {
    $this->layout->getUpdate()->addHandle('preview_mode');
}

// Add handle with parameters
$handle = sprintf('product_view_id_%d', $productId);
$this->layout->getUpdate()->addHandle($handle);

Handle Loading Order

Loading Priority

  1. default — loaded on every page
  2. base — loaded on every frontend page
  3. Area handle — e.g., frontend
  4. Route handle — e.g., catalog_product_view
  5. Action handle — e.g., catalog_product_view_id_5
  6. Theme handle — e.g., frontend_Amazon_Prep
  7. Custom handles — added programmatically

Visual Loading Order

1. default.xml
2. base.xml
3. frontend.xml
4. catalog_product_view.xml
5. catalog_product_view_id_5.xml
6. frontend_Amazon_Prep.xml
7. custom_handle.xml (if added)

Override Behavior

Later handles override earlier ones for the same block names:

<!-- default.xml -->
<block name="product.info" class="Original\Block"/>

<!-- catalog_product_view.xml (overrides) -->
<referenceBlock name="product.info" class="Custom\Block"/>

Debugging Handles

# Enable layout hints
bin/magento dev:layout:hints:enable

# View loaded handles
bin/magento dev:layout:debug

# Check specific handle
bin/magento dev:layout:debug --handle=catalog_product_view

Quiz

1. Which layout handle is loaded on every page?

Question 1 options

2. What is the format for route handles?

Question 2 options

3. How do you add a custom handle programmatically?

Question 3 options

Flashcards

Question

What handle is loaded on every page?

Answer

default and base handles

Question

What is the route handle format?

Answer

{area}_{route}_{controller}_{action}

Question

How do you add a custom handle?

Answer

$this->layout->getUpdate()->addHandle('handle_name')

Question

What handle loads for the homepage?

Answer

cms_index_index

Question

What handle loads for product pages?

Answer

catalog_product_view

Revision Notes

Key Takeaways

  • 1. default and base handles load on every page
  • 2. Route handles follow area_route_controller_action format
  • 3. Action handles include specific parameters like product ID
  • 4. Custom handles can be added via XML or programmatically
  • 5. Later handles override earlier ones

Interview Tips

  • Explain the handle loading order
  • Know the difference between default, base, and route handles
  • Be ready to create custom handles
  • Discuss when to use action handles vs route handles

Cheat Sheet

Handles loaded:
1. default (every page)
2. base (frontend pages)
3. area (frontend)
4. route (catalog_product_view)
5. action (catalog_product_view_id_5)
6. theme (frontend_Vendor_Theme)
7. custom (added programmatically)

Add custom handle:
$this->layout->getUpdate()->addHandle('custom');