I am relatively new to Drupal and have just successfully pulled out a field value and used it to display a custom icon on the page.

Coming from a HTML/CSS only kind of world, I am finding it hard to understand how to do simple things, such as take variables I've created and insert them within the {{ content }} area.

In my specific application, I have a page that NOW looks like this:

Custom Icon 3, Custom Icon 4, Custom Icon 5

{{ content starts here }}

Node Title

Node Subtitle

Custom Icon 1, Custom Icon 2, Custom Icon 3


(page continues)

{{ content ends here }}

What I'd like to do is have the Custom Icons all in a nice line together beneath the Subtitle, but since the 3, 4, and 5 were generated by code, they're outside the {{ content }} block. Icons 1, 2, and 3 are created by hiding the text value (which is either there or not) and displaying a background image...a totally different method that doesn't work for 4, 5, and 6 because in those cases the value isn't binary, it's got several different values.

I'm not married to any specific method to accomplish this but am curious about how I can "best" make these all line up nicely together, one after another, in that order 1, 2, 3, 4, 5, 6.

I believe it's relatively easy to do it like this:

1, 2, 3, 4, 5, 6

Node Title

Node Subtitle


But that's not really what I'd like to do. This is how I'd like it:

Node Title

Node Subtitle

1, 2, 3, 4, 5, 6


This would be relatively easy to do with CSS if I had better access to the inside of the {{ content }} and could make a div, assign it a class, place it in the "4" position, and style it to show as with 1, 2, and 3. But I don't see how to actually accomplish that when the variables are OUTSIDE that immutable {{ content }} block.

Any help to better understand this process? Even if it is to say that I did everything bass-ackward and should simply make these icon fields images and upload the right image into the field each time. I have a site with a large amount of content on it but not so large I couldn't redo this Content Type from scratch the right way. It just seems so strange to me that something so easy to accomplish with a little PHP has been so difficult to get right in this case.

I've done CONTENT with Drupal for years, but this is the first time I've been delving deeper into the development side. Most of the documentation assumes a level of D7 knowledge that I don't have, and the explanations are aimed at people who have been developing D7 sites and need to know the differences, rather than at someone coming in fresh. Or instructions are for D7 entirely.

  • You shouldn't be doing this with templating at all. Use pseudo/extra fields or blocks for placing custom stuff simply through the admin interface. Pseudo/extra fields with custom markup will get printed in the same wrapper as all other fields and can be reordered in the display settings. The rest is CSS.
    – leymannx
    Jun 1, 2020 at 6:33

1 Answer 1


You don't have to use {{ content }} only - this is a variable made up of all the renderable elements in the entity being rendered.

For instance, if you have 4 fields, Field A, Field B, Field C, Field D, you can dictate how/where they are output in the entity template like so, by rendering individually:

<div class="section-main">
  {{ content.field_a }}
  {{ content.field_b }}

<h4>{{ content.field_c }}</h4>
<p>{{ content.field_d }}</p>

The most common thing most people will encounter in theming will be the theming of fields and entities (like node).

If you wanted the markup within the field, you'd create/edit the appropriate field-- template in your theme and move it there. Lets say you wanted to move the h4 into the Field C template:


{% for item in items %}
  <h4>{{ item.content }}</h4>
{% endfor %}

Now anytime that field is rendered, it is wrapped with an h4 (per value, if it is a multivalue field - check field.html.twig for more info).

Then, back in the node template you remove the h4:

{{ content.field_c }}

The h4 is still in the page, it's just in the field template now. You can break it down any number of ways that is suitable for you.

Let's say you did a mytheme_node_preprocess in your themes mytheme.theme file and created some new variables for the node template. Now that you know how to break down the content variable, you can intersperse custom variables with that:

<h1>{{ title }}</h1>

<h2>{{ content.field_subtitle }}</h2>

{{ custom_var }}

{{ content.field_a }}

<h6>{{ custom_var_2 }}</h6>

{{ content.field_b }}

and so on.

Here is a real example from a project of mine to demonstrate a little further:


  set classes = [
    'node--type-' ~ node.bundle|clean_class,
    node.isPromoted() ? 'node--promoted',
    node.isSticky() ? 'node--sticky',
    not node.isPublished() ? 'node--unpublished',
    view_mode ? 'node--view-mode-' ~ view_mode|clean_class,

<article{{ attributes.addClass(classes) }}>
  {{ title_prefix }}{{ title_suffix }}

  {% if node.field_featured_image %}
    <div class="hl__collection-details__main-image">
      {{ content.field_featured_image }}
  {% endif %}

  <section class="hl__rich-text">
    {{ content.body }}

  <div class="hl__collection-details__columns">
    <div class="hl__collection-details__divider"></div>
    <div class="hl__collection-details__how-to">
      <section class="hl__rich-text hl__rich-text--small">
        <h2 class="hl__comp-heading">Accessing These Materials</h2>
        {{ content.field_how_to_use }}

      {% if view_records %}
        <div class="hl__collection-details__how-to-button">
          {{ view_records }}
      {% endif %}
    <div class="hl__collection-details__ctas">
      <section class="hl__contact-list">
        <div class="hl__contact-list__container">
          <h2 class="hl__comp-heading ">Contact</h2>
          <div class="hl__contact-list__items">
            <section class="hl__contact-info">
              {% if node.field_contact_person.target_id %}
                {{ content.field_contact_person }}
              {% else %}
                {% include '@mytheme/misc/freeform--contact.html.twig' %}
              {% endif %}

      {% if node.field_call_to_action.target_id %}
        {{ content.field_call_to_action }}
      {% endif %}

  {% if node.field_related_collections.target_id or node.field_related_how_tos.target_id %}
    <hr class="hl__section-divider" />
  {% endif %}

  {% if node.field_related_collections.target_id %}
    <section class="hl__overlay-promo-grid">
      <div class="hl__overlay-promo-grid__container">
        <h2 class="hl__comp-heading hl__comp-heading--left">Related Collections</h2>
        <div class="hl__overlay-promo-grid__grid">
          {{ content.field_related_collections }}
        {% if node.field_see_all_collections %}
          <div class="hl__overlay-promo-grid__see-all">
            {{ content.field_see_all_collections }}
        {% endif %}
  {% endif %}

  {% if node.field_related_how_tos.target_id %}
    <section class="hl__staggered-type-list">
      <div class="hl__staggered-type-list__list-wrapper">
        <div class="hl__staggered-type-list__list">
          {{ content.field_related_how_tos }}
  {% endif %}

The more you try things, the more you are going to learn. You cannot do any PHP in Twig templates, which is why that has to be deferred to preprocess functions in the theme file, custom field formatters etc that tell Drupal what to do with the data you are about to output.

edit: the {% if node.field_name.value %} lines are simply checking in the node object that the field has an actual value before we output markup and render the field for it. node and content are two separate things.

  • This is a very thoughtful, helpful, and clear reply. I am going to pick through it shortly and really appreciate your time, @kevin. Thank you! Jan 10, 2019 at 17:39

Your Answer

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

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