Theme Development and Layout
Theme anatomy and inheritance
A Magento theme lives in app/design/frontend/Vendor/theme with theme.xml, registration.php, etc/view.xml, and media/. Inheritance is declared in theme.xml via <parent>, and a theme can also declare fallback order. Layout is XML: default.xml, cms_index_index.xml, page-specific handles, and page_layouts.xml for page layout variants. Understand the difference between page layout (1column, 2columns-left, empty) and layout update handles (e.g., catalog_product_view).
Containers, blocks, and arguments
Containers hold blocks; blocks render. referenceBlock/referenceContainer modify existing structure; move, remove, argument, and action are the common directives. Arguments passed to blocks are read in templates via $block->getData() or typed getters. A frequent trap: using referenceBlock for a container name, or forgetting that before/after ordering only applies among siblings.
Traps to expect
- Confusing
layout.xmlprecedence: module layout, then theme parent, then child theme. - Assuming a block removed in one handle is gone everywhere.
- Forgetting that
getChildHtml()requires the block to be added to the right container. setTemplatein layout vs._templatein the block class.
Rule of thumb
If a change should affect every page, put it in default.xml of your theme and use referenceBlock targeting a stable, documented block name; if it should affect one page type, use the specific handle. Always verify with layout debug (template hints) rather than guessing.
Worked example
To add a banner above the product description: create Magento_Catalog/layout/catalog_product_view.xml in the theme, use <referenceContainer name="product.info.main"> and insert <block class="Magento\Framework\View\Element\Template" name="product.banner" template="Magento_Catalog::product/banner.phtml" before="-"/>.
View models note
Prefer view models ($viewModel = $block->getData('view_model')) over logic in templates; this is a layout/template boundary concept tested often.