Magento 2 Module – Header and Footer Not Loading in Custom CMS Layout

cmsfrontendlayoutmagento2module

I am developing a custom theme which inherits from Magento/blank. I am attempting to develop a CMS homepage layout within a custom module.

I have created the module and successfully applied the layout to the homepage.

When I visit the homepage I should see a header and footer, and an empty container for the content.

Instead, I see an entirely blank page with the styles loaded from my custom theme.

My first thought is that my module is not able to fall back to the layouts contained within the Magento_Theme module and so the container "page.wrapper" cannot be referenced because it does not exist within my custom module. I'm just not certain what the solution would be.

My module is written as follows:

CatalogFilter  
    ├── composer.json  
    ├── etc  
    │   └── module.xml  
    ├── README.md  
    ├── registration.php  
    └── view  
        └── frontend  
            ├── layouts.xml  
            └── page_layout  
                └── cms_page_view_id_catalogfilter.xml  

app/code/JcfTools/CatalogFilter/composer.json

{
    "name": "jcftools/module-catalogfilter",
    "description": "",
    "type": "magento2-module",
    "version": "1.0.0",
    "license": "Private License",
    "authors": [
        {
          "name": "Joshua Flood",
          "email": "info@joshuaflood.com",
          "homepage": "https://www.joshuaflood.co.uk",
          "role": "Owner"
        }
    ],
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "JcfTools\\CatalogFilter\\": ""
        }
    }

}

app/code/JcfTools/CatalogFilter/registration.php

<?php
/**
 * Copyright © Joshua Flood. All rights reserved.
 * See COPYING.txt for license details.
 */

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'JcfTools_CatalogFilter',
    __DIR__
);

app/code/JcfTools/CatalogFilter/etc/module.xml

<?xml version="1.0"?>
<!--
  /**
   * Copyright © Joshua Flood. All rights reserved.
   * See COPYING.txt for license details.
   */
-->

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="JcfTools_CatalogFilter" setup_version="1.0.0">
    </module>
</config>

app/code/JcfTools/CatalogFilter/view/frontend/layouts.xml

<page_layouts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/PageLayout/etc/layouts.xsd">
    <layout id="jcftools-catalogfilter">
        <label translate="true">JcfTools Catalog Filter</label>
    </layout>
</page_layouts>

app/code/JcfTools/CatalogFilter/view/frontend/page_layout/cms_page_view_id_catalogfilter.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © Joshua Flood. All rights reserved.
 * See COPYING.txt for license details.
 */
-->

<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">
        <!-- Header container -->
        <container name="header.container"
                   as="header_container"
                   label="Page Header Container"
                   htmlTag="header"
                   htmlClass="page-header"
                   before="main.content" />
        <!-- Page top -->
        <container name="page.top"
                   as="page_top"
                   label="After Page Header"
                   after="header.container"/>
        <!-- Footer container -->
        <container name="footer-container"
                   as="footer"
                   before="before.body.end"
                   label="Page Footer Container"
                   htmlTag="footer"
                   htmlClass="page-footer" />
    </referenceContainer>
</layout>

Best Answer

If you want to have the header and footer, your layout need to update something else than empty (1column, 2columns-left, 2columns-right, 3columns).

<?xml version="1.0"?>
<!--
/**
 * Copyright © Joshua Flood. All rights reserved.
 * See COPYING.txt for license details.
 */
-->

<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd">
    <update handle="1column"/>
    <referenceContainer name="page.wrapper">
        <!-- Header container -->
        <container name="header.container"
                   as="header_container"
                   label="Page Header Container"
                   htmlTag="header"
                   htmlClass="page-header"
                   before="main.content" />
        <!-- Page top -->
        <container name="page.top"
                   as="page_top"
                   label="After Page Header"
                   after="header.container"/>
        <!-- Footer container -->
        <container name="footer-container"
                   as="footer"
                   before="before.body.end"
                   label="Page Footer Container"
                   htmlTag="footer"
                   htmlClass="page-footer" />
    </referenceContainer>
</layout>

You can see in "vendor/magento/module-theme/view/frontend/page_layout/1column.xml" the file adding the header and footer.

EDIT 1 : Why would you redefine page.wrapper, the header, page.top and footer instead of updating the 1column ?