7

I create custom page layout. In admin area select this layout:

Amin -> Products -> Categories -> MyCategory -> Design -> Layout

Q: How add css class to body tag?

My file:

app/design/frontend/{Vendor}/{theme}/Magento_Theme/page_layout/custom.xml

<?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="1column"/>
    <!-- my references -->
</layout>

Tried, but not work:

<body>
    <attribute name="class" value="my-class" />
</body>
----------------------
<referenceContainer name="root" htmlClass="my-class" />
----------------------
<referenceContainer name="root">
    <argument name="css_class" xsi:type="string">my-class</argument>
</referenceContainer>

Update. PY Yick answer not work too (for me):

<referenceContainer name="root">
    <arguments>
        <argument name="css_class" xsi:type="string">my-class</argument>
    </arguments>
</referenceContainer>

8 Answers 8

13

 Page Layout XML

As far as I'm aware this isn't possible out of the box via page layout XML, the existing implementation is done via PHP (checkout the addDefaultBodyClasses() function here);

/**
 * Add default body classes for current page layout
 *
 * @return $this
 */
protected function addDefaultBodyClasses()
{
    $this->pageConfig->addBodyClass($this->request->getFullActionName('-'));
    $pageLayout = $this->getPageLayout();
    if ($pageLayout) {
        $this->pageConfig->addBodyClass('page-layout-' . $pageLayout);
    }
    return $this;
}

Layout XML

Just in case anyone ends up on this question for standard layout XML it can be done this way:

Add the following attribute inside the <body> tags.

<body>
    <attribute name="class" value="your-class"/>
</body>

If this doesn't work you may need to clear your caches?

3
  • Thank you for trying help. But i wrote that it not work. It work only for "<page "urn:magento:framework:View/Layout/etc/page_configuration.xsd">"
    – orthener
    Jun 30, 2017 at 12:16
  • I didn't notice it was a page layout sorry, I don't think it's possible out the box. I've updated my answer with my findings.
    – Ben Crook
    Jun 30, 2017 at 12:51
  • Yes. Same issue for me. @BenCrook do you have solution of that?
    – Mehta Prem
    Sep 20, 2020 at 10:41
4

The only solution i've found is to add a class to the root container. This element will be displayed immediately after the body tag.

I've used this code:

<referenceContainer name="root" htmlTag="div" htmlClass="custom-class">
</referenceContainer>

For me worked in the Layout Update XML for CMS pages and categories.

Unfortunately is the only solution iv'e found similar to the old "addBodyClass".

1
  • It wasn't what I was looking for as I wish to add the class on body tag. But that solution worked as well so +1 for you! thanks. Jul 20, 2020 at 13:13
3

You can do this using a Observer:

=> Create the file :

app/code/Myvendor/Mymodule/etc/frontend/event.xml with the following content:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <event name="layout_generate_blocks_after">
        <observer name="samgranger_storecodebodyclass" instance="Myvendor\Mymodule\Observer\AddBodyClass" shared="false" />
    </event>
</config>

=> Create the file :

app/code/Myvendor/Mymodule/Observer/AddBodyClass.php with the following content:

<?php
namespace Myvendor\Mymodule\Observer;

use Magento\Framework\View\Page\Config;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer as EventObserver;

class AddBodyClass implements ObserverInterface
{
    protected Config $config;

    public function __construct(
        Config $config
    ){
        $this->config = $config;
    }

    public function execute(EventObserver $observer){
        $name = $observer->getFullActionName();
        if($name == "amblog_index_category") {
            $this->config->addBodyClass("events-page");
        }
    }
}
1
  • This is added the class in the begining , can we add at the end?
    – Manjunath
    Dec 1, 2021 at 5:09
1

You're almost there. Change <referenceContainer name="root"> to the following code:

<referenceContainer name="root">
    <arguments>
        <argument name="css_class" xsi:type="string">my-class</argument>
    </arguments>
</referenceContainer>

Ref: http://devdocs.magento.com/guides/v2.1/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_ref

1

My own workaround: use autogenerated class. Magento 2 add class to <body> that based on layout name:

page-layout-{layout-id}

Example. My page-layout file name "category-blog.xml". Body will have class "page-layout-category-blog".

2
  • Where i need to add this? could you please help me?
    – Mehta Prem
    Sep 20, 2020 at 10:42
  • @Mehta Prem Hi. Yoy can create "custom page layout". Filename of this layout will be in body classes.
    – orthener
    Sep 21, 2020 at 18:31
1

You can do this using a plugin:

Create the file app/code/Myvendor/Mymodule/etc/frontend/di.xml with the following content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">


<type name="Magento\Framework\View\Result\Page">
<plugin name="myModuleResultPage" type="Myvendor\Mymodule\Plugin\Result\Page"/>
</type>

</config>

Create the file app/code/Myvendor/Mymodule/Plugin/Result/Page.php with the following content:

<?php
namespace Myvendor\Mymodule\Plugin\Result;

use Magento\Framework\App\ResponseInterface;

class Page
{
private $context;
private $registry;

public function __construct(
\Magento\Framework\View\Element\Context $context,
\Magento\Framework\Registry $registry
) {
$this->context = $context;
$this->registry = $registry;
}

public function beforeRenderResult(
\Magento\Framework\View\Result\Page $subject,
ResponseInterface $response
){

$category = $this->registry->registry('current_category');

if($this->context->getRequest()->getFullActionName() == 'catalog_category_view'
  && $category 
  && $category->getId() == <some_category_id>){
   $subject->getConfig()->addBodyClass('my_custom_class');
}

return [$response];
}
}

Replace the "some_category_id" with the category id that you want to add the custom body class in.

Note: In order to this solution to work, you need a working plugin "Myvendor_Mymodule", if you don't have the plugin, just do the following to create it:

Create the following file -

app/code/Myvendor/Mymodule/etc/module.xml

With the following content

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Myvendor_Mymodule" setup_version="1.0.0" />
</config>

And the following file - app/code/Myvendor/Mymodule/registration.php

with the following content -

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Myvendor_Mymodule',
__DIR__
);

Reference: https://www.mexbs.com/magento-blog/adding-custom-body-class-magento2/

1
  • Downvoted because this is crazy overkill, just use an <attribute> tag in layout per Ben Crook's answer. Sep 13, 2020 at 17:11
0
<body>
    <attribute name="class" value="body-class-aaa" />
</body>

Add these lines to layout xml file or Layout section of cms page/category.

0

Currently you just can't add class to <body> in the page layout using only XML, but you can add it to the containers inside the <body>. In most cases this trick may help.

Since almost everything on the page is placed inside the page.wrapper container, you can change the class of this container instead of <body> in page layout:

<?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">

    <referenceContainer name="page.wrapper" htmlClass="page-wrapper my-class" />

</layout>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.