LC
Back to Tutorials
backendintermediateNovember 5, 2024

Custom Block Types in Drupal 8 — Stat Card Example

Build a reusable custom block type in Drupal 8 with fields, Twig templates, and conditional rendering.

drupaltwigthemingblocks

Create a custom block type in Drupal 8 with structured fields and a custom Twig template. This example builds a "Stat Card" block.

Define the Block Type

Go to Structure > Block layout > Block types > Add and create a new block type with these fields:

FieldTypeMachine name
IconText (plain)field_icon
Primary TextText (plain)field_primary_text
Secondary TextText (plain)field_secondary_text
Button URLLinkfield_button

Identify the Twig Template

Enable Twig debugging in services.yml:

yaml
      parameters:
  twig.config:
    debug: true

    

Inspect the page source to find the template suggestion, e.g.: block--inline-block--stat-card.html.twig

Create the Template

Place the template in your theme's templates/ directory:

twig
      {%- set primary = content.field_primary_text|render|striptags|trim -%}
{%- set secondary = content.field_secondary_text|render|striptags|trim -%}
{%- set icon = content.field_icon|render|striptags|trim -%}
{%- set button_url = content.field_button[0]['#url']|render|striptags|trim -%}
{%- set button_text = content.field_button[0]['#title']|render|striptags|trim -%}

<div class="stat-card">
  {% if icon %}
    <div class="stat-card__icon">{{ icon }}</div>
  {% endif %}

  <h3 class="stat-card__primary">{{ primary }}</h3>

  {% if secondary %}
    <p class="stat-card__secondary">{{ secondary }}</p>
  {% endif %}

  {% if button_url is not empty %}
    <a href="{{ button_url }}" class="stat-card__button">
      {{ button_text }}
    </a>
  {% endif %}
</div>

    

Style the Block

css
      .stat-card {
  padding: 2rem;
  border-radius: 0.5rem;
  background: #f8f9fa;
  text-align: center;
}

.stat-card__icon {
  font-size: 2.5rem;
  margin-bottom: 1rem;
}

.stat-card__primary {
  font-size: 2rem;
  font-weight: 700;
  margin: 0;
}

.stat-card__secondary {
  color: #6c757d;
  margin-top: 0.5rem;
}

.stat-card__button {
  display: inline-block;
  margin-top: 1rem;
  padding: 0.5rem 1.5rem;
  background: #007bff;
  color: white;
  border-radius: 0.25rem;
  text-decoration: none;
}

    

Key Twig Patterns

twig
      {# Strip HTML and trim whitespace from rendered fields #}
{{ content.field_name|render|striptags|trim }}

{# Check if a field has a value #}
{% if content.field_name|render|striptags|trim is not empty %}

{# Access link field URL and title #}
{{ content.field_link[0]['#url'] }}
{{ content.field_link[0]['#title'] }}