Variants
When to Use
Use variants for pre-defined, mutually exclusive visual styles of a component. Use props for data-driven values, typed inputs, or field-sourced values. For per-placement variant control in Layout Builder, choose between the entity-field pattern (same variant per block content) and the LB block configuration pattern (different variant per placement).
Decision
| Use Case | Use Variants | Use Props |
|---|---|---|
| Visual theme/style switching | Yes | No |
| Multiple mutually exclusive appearances | Yes | No |
| Data that affects rendering logic | No | Yes |
| Values that need specific typing (boolean, number) | No | Yes |
| Values that come from entity fields | No | Yes |
Per-Instance Variants in Layout Builder
| Need | Pattern |
|---|---|
| Variant tied to the block content (same everywhere it's placed) | Option 1 — entity field |
| Variant tied to the placement (different per page) | Option 2 — LB block configuration + template |
Plus Suite project with BlockPropertiesEvent already wired |
Option 2 |
| No template overrides allowed (pure UI Patterns shop) | Option 1 |
Pattern
Defining Variants in YAML
variants:
default:
title: "Default"
description: "Standard card appearance"
highlighted:
title: "Highlighted"
description: "Emphasized card with accent border"
compact:
title: "Compact"
description: "Reduced padding version"
Always Set a Default in Twig
{# GOOD: handles missing variant #}
<div class="alert alert--{{ variant|default('info') }}">
{# BAD: breaks if variant is empty #}
<div class="alert alert--{{ variant }}">
Option 1 — Entity Field (variant same per block content)
Add field_variant (list_string) to the block content type with allowed values matching the SDC's variant keys. Map it in Manage Display:
variant_id:
source_id: 'field_property:block_content:field_variant:value'
source:
type: value
Pro: pure UI Patterns wiring, no template required. Con: variant is per-block-content — duplicating content to vary the variant.
Option 2 — LB Block Configuration + Twig Template (variant per placement)
Plus Suite (or a custom BlockPropertiesEvent subscriber) adds a variant select to the LB block placement form. A block template reads configuration.{prop} and passes it to the SDC:
{# templates/block--inline-block--hero.html.twig #}
{% set variant = configuration.hero_variant|default('default') %}
{% include 'mytheme:hero' with {
variant: variant,
heading: content.field_heading[0]['#context'].value,
body: content.field_body|render,
image: content.field_image,
} only %}
Pro: each placement carries its own variant value.
Con: incompatible with pure UI Patterns wiring — the formatter has no access to LB block configuration arrays.
Common Mistakes
- Wrong: Faking variants with a string prop + enum → Right: Variants get a dedicated variant selector UI and per-variant story rendering that a plain enum prop loses.
- Wrong: Not using
|default('...')in Twig → Right: If no variant is configured, the template receives an empty string, producing malformed class names likecard--. - Wrong: Expecting
variant_idin entity view display to differ per LB placement → Right: View display config is per-bundle and applies to every instance. Use Option 1 or 2 for per-instance variation. - Wrong: Trying to wire
configuration.variantinto afield_propertysource → Right: UI Patterns formatters can't read LB block configuration. Use the template pattern for per-placement variants.
See Also
- Defining Components
- Pattern Library
- Plus Suite Custom Block Types —
BlockPropertiesEventsubscriber for adding LB block configuration fields