When building dynamic layouts in Craft CMS, you often need to know which section a specific entry belongs to. Whether you want to apply a unique CSS class to your <body> tag, load a specific sidebar, or trigger conditional logic based on the content type, knowing how to get the current section handle is a fundamental skill for any Craft developer.

In this guide, we will explore why the section handle isn't globally available by default, how to retrieve it from the standard entry object, and how to implement advanced custom Twig functions for more complex routing scenarios.

Understanding the Relationship Between Templates and Sections

One of the most powerful features of Craft CMS is the decoupling of content from presentation. In many other CMS platforms, a template is strictly bound to a specific content type. In Craft, any template can display any entry from any section.

Because of this flexibility, there is no inherent "current section" global variable. A single template could theoretically fetch entries from five different sections simultaneously using craft.entries. Therefore, to get a section handle, you must first identify which Entry Model you are referencing.

If your section has the "Entries in this section have their own URLs" setting enabled, Craft automatically provides an entry variable to the template defined in that section's settings. This entry variable is your gateway to the section data.

Retrieving the Handle from the Entry Object

If you are viewing a single entry page (like a blog post or a generic page), the easiest way to get the section handle is to access the properties of the automatically injected entry variable.

There are several ways to write this in Twig, ranging from explicit method calls to concise property access. Here are the most common methods:

The Explicit Approach

You can use the getSection() method to retrieve the Section model and then access its handle:

{% set section = entry.getSection() %}
{% set handle = section.handle %}

The Simplified Approach

Craft allows you to chain these calls together for a cleaner template:

{% set handle = entry.getSection().handle %}

Thanks to Craft’s property magic, you can access the section directly as a property of the entry. This is the cleanest and most common way to retrieve the handle:

{% set handle = entry.section.handle %}

You can then use this handle directly in your HTML. For example, to add a section-specific class to your wrapper:

<div class="container section-{{ entry.section.handle }}">
    <!-- Content goes here -->
</div>

Advanced Approach: Custom Twig Functions

In some scenarios, you might not have a direct entry variable available, or you might be working with complex routing where you need to determine the section based on the URL structure. For developers working with Craft 5.x, you can extend Twig with custom PHP functions to make section retrieval even more robust.

By creating a custom Twig extension, you can fetch sections by their handle or even guess the section based on the current URI format. This is particularly useful for building navigation logic or breadcrumbs.

Below is an example of a PHP class that adds getCurrentSection and getSectionByHandle functions to your Twig environment:

class CustomTwigFunctions extends AbstractExtension
{
  public function getFunctions()
  {
    return [
      new TwigFunction('getCurrentSection', $this->getCurrentSection(...)),
      new TwigFunction('getSectionByHandle', $this->getSectionByHandle(...)),
    ];
  }

  /**
   * Returns a section if the current URL matches the entry page URI
   * defined in the section's Control Panel page.
   *
   * E.g. if the current URL is `news` it returns the section with an
   * entry URI of `news/{slug}`.
   */
  public function getCurrentSection(): Section|null
  {
    $currentUrl = substr(Craft::$app->request->url, 1);
    $sections = Craft::$app->entries->getAllSections();
    $currentSection = array_find(
      $sections,
      fn($s) => $s->siteSettings[1]->uriFormat === $currentUrl . '/{slug}',
    );
    return $currentSection;
  }

  /**
   * Returns a section by its handle defined in the Control Panel,
   * or `null` if it doesn't exist.
   */
  public function getSectionByHandle(string $handle): Section|null
  {
    $sections = Craft::$app->entries->getAllSections();
    return array_find($sections, fn($s) => $s->handle === $handle);
  }
}

Using these custom functions in Twig becomes very straightforward:

{# Get the section object based on the URL pattern #}
{% set section = getCurrentSection() %}

{% if section %}
    <p>You are browsing the {{ section.name }} section.</p>
{% endif %}

Why Version Context Matters

If you are using Craft 5.x, ensure your PHP environment is updated to at least PHP 8.4 if you plan to use modern array functions like array_find as shown in the custom function example. If you are on an older version of Craft (like Craft 3 or 4), the core logic of entry.section.handle remains the same, but the underlying PHP service names (like Craft::$app->entries) might differ slightly in their implementation details. Always verify your custom code against the official Craft CMS documentation.

Frequently Asked Questions

Why does {{ handle }} return nothing in my template?

In Craft CMS, handle is not a global variable. It is a property that belongs to specific objects like Sections, Categories, or Entry Types. To display a handle, you must specify which object you are talking about, such as entry.section.handle or category.group.handle.

Can I get the section handle inside a Matrix block?

Yes! Inside a Matrix block loop, the block variable has an owner property which refers to the entry the block belongs to. You can access the section handle using block.owner.section.handle.

Is there a performance penalty for calling entry.section.handle?

No. Craft CMS caches these relationships efficiently. Accessing the section property on an entry that is already loaded is a very lightweight operation and will not significantly impact your page load times.

Wrapping Up

Retrieving the current section handle is a simple yet vital task in Craft CMS development. While the most common method is using entry.section.handle, understanding the decoupled nature of Craft allows you to build more flexible templates.

Key Takeaways: - Use entry.section.handle for standard entry pages. - Remember that templates are not strictly tied to sections; they are tied to URLs and the data you fetch. - For complex needs, consider a custom Twig extension to bridge the gap between URLs and Section models. - Always check for the existence of the entry variable before accessing its properties to avoid template errors on non-entry pages.