Working with HTML Classes

I like this approach as it keeps it easy to read, and git diffs are easier to understand as well. I think that the concept of including something and setting a value like isDark to true and getting a BEM Modifier class added works really well.

{% set classes = [
  'card',
  media ? 'card--has-media',
  isDark ? 'card--is-dark',
] %}
<div class="{{ classes|join(' ') }}"></div>

If you want to take it even further, you can enable the file that is including the above template to add some classes. So our first template, let's call it a.twig, would look like this instead:

{% set classes = [
  'card',
  media ? 'card--has-media',
  isDark ? 'card--is-dark',
] | merge(classes|default([])) %}
<div class="{{ classes|join(' ') }}">
What's that default([]) all about? Well, I'm trying to merge classes with classes if it's already there, and if it isn't, then using merge will yell at me as I'm trying to merge an array with null so I tell it to merge it with [] if classes is not present. So basically the default of classes if it's not present, is [].

And our second template could add some classes to that like so:

{% include 'a.twig' with {
    isDark: true,
    classes: ['my-extra-class'],
  }
%}

This would result in this HTML:

<div class="card  card--is-dark my-extra-class"></div>
About that extra space... If you spotted the extra space in the class list, good catch – that comes from the fact that media was false and therefore returned null - however it took up a spot in our array which was joined with a space to make the list. I'll often pass the end string through | trim to get rid of the ones at the beginning and end, but it's not that big of a deal and is totally valid, functional markup.

Drupal 8 & Twig

Accessing Data

If you want to access fields and their values, start off with node, not content, which is a render array with the configured fields.

If you want a field's value, most of the time you simply append .value: node.field_name.value.

When trying to figure out what's in a content entity, use node.toArray(), that gives you an array representation that's very close to how you can access it as an object. While the internal structure is quite different.

Entities References

If it's an entity reference, you can dive into it via .entity.

To access the label of a term reference for example, you can access it as block_content.field_tags.entity.name.value.

This all maps directly to PHP, you can also do $block_content->field_tags->entity->name->value in preprocess and other places where you have the block_content.