Drupal is a registered trademark of Dries Buytaert
Views Bootstrap 5.5.2 Minor update available for module views_bootstrap (5.5.2). oEmbed Providers 3.0.0 Major update available for module oembed_providers (3.0.0). Byte (theme) 1.0.3 Minor update available for theme byte_theme (1.0.3). Token Content Access 3.1.3 Minor update available for module tca (3.1.3). Emulsify 7.2.1 Minor update available for theme emulsify (7.2.1). Opensolr Search 4.1.0 Minor update available for module opensolr_search (4.1.0). AG-UI 1.0.2 Minor update available for module agui (1.0.2). FileGate 1.5.0 Minor update available for module file_gate (1.5.0). oEmbed Providers 2.2.4 Module oembed_providers updated after 7 months of inactivity (2.2.4). Provus Mega Menu Module provus_mega_menu crossed 1,000 active installs.

This module allows render arrays to add CSS classes to the `<body>` tag through `#attached`. These classes bubble up the render tree and are automatically de-duplicated and sanitized for the final HTML response. It works with render caching and is useful for tasks like adding a class when a specific block is present or indicating a particular page context directly from code.

This module lets render arrays add classes to the <body> tag through #attached. Any render array can contribute body classes, and they bubble up the render tree like libraries, drupalSettings, or html_head.

Features

  • Adds a new #attached['body_class'] key that any render array can use:
    $build['#attached']['body_class'][] = 'page-fancy';
    $build['#attached']['body_class'] = ['page-fancy', 'has-promo'];
  • Classes bubble up the render tree the same way as other attached metadata. A render array can declare body classes, and the final HTML response gets them all on <body>.
  • Works with render caching. If a block is render-cached, its body classes are reapplied on the next cache hit, without the originating PHP running again. The static-helper pattern (a class with a static accumulator) can not do that.
  • De-duplicates automatically. Existing classes from template_preprocess_html and the theme are kept.
  • Sanitises class names through \Drupal\Component\Utility\Html::getClass() before writing to the body tag.
  • Only touches HtmlResponse. Ajax, JSON, and other response types pass through untouched.

When to use:

  • A block wants the body to have has-promo-banner while it is on the page.
  • A controller wants the body to have page-checkout-step-3.
  • A field formatter on a node wants has-video on body when a video is rendered.
  • Anywhere you build a render array and want a CSS hook on the body without writing a hook_preprocess_html() for each case.

Post-Installation

Just enable the module. There is no admin page and no configuration.

After enabling, anywhere in your code that returns a render array, set:

$build['#attached']['body_class'][] = 'page-foo';

The class will appear on <body class="..."> in the rendered HTML. You can do this from a controller, a block plugin's build(), a field formatter's viewElements(), a hook_preprocess_* for a render element, or anywhere else a render array passes through.

For Twig templates, set the value before the template renders — Twig itself does not yet have a way to attach metadata to a render array.

Additional Requirements

Drupal core 10 or 11. No other dependencies.

None.

Similar projects

There are several contrib modules that add body classes — for example Page Body Attributes, Body Attributes, Extra Body Classes, Body Class. They all add body classes from admin configuration (path match rules, per-node form fields, etc.), via a hook_preprocess_html().

This module is different: it is render-array driven. Any code that builds a render array can declare body classes through #attached, and they bubble up. There is no admin UI and no path matching. If you need site builders to manage classes through the UI, use one of the other modules. If you need code-level declaration that follows the render tree, use this one.

Supporting this Module

If you find a bug or have an idea, please open an issue on the project page. Patches and merge requests welcome.

Activity

Total releases
1
First release
May 2026
Latest release
2 months ago
Releases (12 mo)
1 ▲ from 0
Maintenance
Active

Releases

Version Type Release date
1.0.x-dev Dev May 2, 2026