Using attributes in templates

Last updated on
17 March 2025

Many Twig templates will have one or more Attribute objects passed in as variables. The job of the Attribute object is to store a set of HTML attributes, providing the developer helpful methods to interact with that data and allow for easy printing of the attributes. For example, attributes.addClass('myclass') makes it easier to add one class without worrying about precise string concatenation.

Generally, attributes in a template should look something like this:

<div{{ attributes }}></div>

There should not be any space between the tag name and the Twig syntax. The "stable" theme included with Drupal 8 core has many examples of attributes to examine.

By default, the following attribute object variables are available to all templates: attributes, title_attributes, and content_attributes.

You can use your debug helper of choice (kint(), dump(), dpm(), etc) to inspect what's available. Below is an example of using {{ kint(attributes) }} in node.html.twig

{{ kint(attributes) }} on a node

Attributes' methods

Here are some of the helpful methods you can use with the Attribute object:

attributes.addClass()

Adds classes or merges them on to an array of existing CSS classes.

Single class:

<div{{ attributes.addClass('my-class') }}></div>

Multiple classes:

{%
  set classes = [
    'red',
    'green',
  ]
%}
<div{{ attributes.addClass(classes) }}></div>

outputs <div class="red green"></div>.

attributes.removeClass()

Removes a class from an Attribute object. Used similarly to addClass. Let's say you get the classes variable from somewhere else like a preprocess function.

{% set classes = [ 'red', 'green', 'blue' ] %}

<div{{ attributes.addClass(classes).removeClass('green') }}></div>

outputs <div class="red blue"></div>.

attributes.setAttribute($attribute, $value)

Sets values for an attribute key.

<div{{ attributes.setAttribute('id', 'myID') }}></div>

outputs <div id="myID"></div>

attributes.removeAttribute($attribute)

Removes an attribute from an Attribute object.

<div{{ attributes.removeAttribute('id') }}></div>

attributes.hasClass($class)

Checks if the class array has the given CSS class.

{% if attributes.hasClass('myClass') %}
  {# do stuff #}
{% endif %}

attributes.key

If the key is associated with a value, the value is returned. It acts a lot like one might expect a getAttribute() function to work. (Note that there is no getAttribute() function, and that this syntax is equivalent to offsetGet().)

<div style="{{ attributes.style }}"></div>

Depending on the key, you may have to use brackets instead of a dot. This is the case if the key contains a hyphen as with most data attributes.

{% if attributes['data-my-data'] %}
  {# do stuff #}
{% endif %}

Create Attributes in Twig

As of Drupal 8.3.x, there is a new Twig function create_attribute() See the change record: https://www.drupal.org/node/2818293

This provides a new blank Attribute object to use to build up attributes.

{% set my_attribute = create_attribute() %}
{%
  set my_classes = [
    'kittens',
    'llamas',
    'puppies',
  ]
%}
<div{{ my_attribute.addClass(my_classes).setAttribute('id', 'myUniqueId') }}>
  {{ content }}
</div>
<div{{ create_attribute({'class': ['region', 'region--header']}) }}>
  {{ content }}
</div>

Other helpful snippets

Dot notation can be chained

{% set classes = ['red', 'green', 'blue'] %}
{% set my_id = 'specific-id' %}
{% set image_src = 'https://www.drupal.org/files/powered-blue-135x42.png' %}
<img{{ attributes.addClass(classes).removeClass('green').setAttribute('id', my_id).setAttribute('src', image_src) }}>

outputs <img id="specific-id" class="red blue" src="https://www.drupal.org/files/powered-blue-135x42.png">

Using without filter

The twig filter without to retrieve part of attributes:

<div class="myclass {{ attributes.class }}"{{ attributes|without('class') }}></div>

Note: In most cases code like the above should be avoided in favor of using addClass().

Be extremely cautious when assigning attributes manually in twig templates. Be sure to always enclose the attribute strings in double quotes or the site may be left open to an XSS attack. Twig will automatically escape the contents of the double quotes and protect from an XSS attack.

This twig template:

<b class={{ attributes.class }}>Hello</b>

With user input:

foo onclick=alert(bar)

Will result in this output:

<b class=foo onclick=alert(bar)>Hello</b>

This twig template with double quotes:

<b class="{{ attributes.class }}">Hello</b>

Double quotes will result in this output from the same input:

<b class="foo &quot; onclick=&quot;alert(bar)">Hello</b>

Modifying attributes without printing them

{% set attributes = attributes.addClass('my-class') %}
<div{{ attributes }}></div>

The above syntax will not work for arrays, such as row.attributes in views-view-table.html.twig, but instead will return an 'Unexpected token "punctuation" of value "."' error. Try the Twig "do" tag instead:

{% do row.attributes.addClass('my-class') %}
<tr{{ row.attributes }}></tr>

Another example:

{% do attributes.setAttribute('title', 'The Title') %}
<div{{ attributes }}></div>

Help improve this page

Page status: No known problems

You can: