Figure

Inline-block media container that shrink-wraps its child image and centres the caption underneath. Targets the native <figure> element and a .figure class fallback. Direct <img> and <picture> > <img> children get responsive sizing automatically; use the opt-in .figure-img class for descendants that aren't direct children.

Live

Native figure with caption

Figure 1. A placeholder graphic, full-width within the figure.
<figure>
<img src="https://placehold.co/600x300" alt="" width="600" height="300" />
<figcaption>Figure 1. A placeholder graphic, full-width within the figure.</figcaption>
</figure>
@use '@adnap/krysalicss' with (
  $feature-list: ('base-reset', 'base-global', 'typography-figure')
);
Playground

.figure class on a div carrier

Class-only carrier, useful when the surrounding markup forbids the figure tag.

<div class="figure">
<img src="https://placehold.co/400x200" alt="" width="400" height="200" />
<p class="figure-caption" style="margin: 0;">Class-only carrier, useful when the surrounding markup forbids the figure tag.</p>
</div>
@use '@adnap/krysalicss' with (
  $feature-list: ('base-reset', 'base-global', 'typography-figure')
);
Playground

.figure-img opts a non-direct child img into the defaults

The img sits inside a picture wrapper; .figure-img applies the responsive rule explicitly.
<figure>
<picture>
  <img class="figure-img" src="https://placehold.co/500x250" alt="" width="500" height="250" />
</picture>
<figcaption>The img sits inside a picture wrapper; .figure-img applies the responsive rule explicitly.</figcaption>
</figure>
@use '@adnap/krysalicss' with (
  $feature-list: ('base-reset', 'base-global', 'typography-figure')
);
Playground

Markup

markup
<!-- Native <figure>. Child <img> is responsive by default. -->
<figure>
  <img src="/diagram.svg" alt="System diagram" />
  <figcaption>Figure 1. Request lifecycle through the gateway.</figcaption>
</figure>

<!-- Class fallback on a non-semantic carrier. -->
<div class="figure">
  <img src="/diagram.svg" alt="" />
  <p class="figure-caption">Caption on a non-figure element.</p>
</div>

<!-- .figure-img opts a non-direct child <img> into the responsive defaults. -->
<figure>
  <picture>
    <source srcset="/diagram.avif" type="image/avif" />
    <img class="figure-img" src="/diagram.png" alt="" />
  </picture>
  <figcaption>The .figure-img class also applies the defaults to an arbitrary descendant img.</figcaption>
</figure>

Variables

VariableDefaultNotes
$selector'figure, .figure'Targets the tag and class fallback.
$img-selector'.figure-img'Opt-in class for non-direct child images.
$caption-selector'figcaption, .figure-caption'Targets the tag and class fallback.
$displayinline-blockShrink-wraps the image so captions centre within author-controlled width.
$margin-block-end1remTrailing space below the figure.
$img-margin-block-end0.5remGap between image and caption. Lives on the img so caption-less figures don't carry orphan whitespace.
$caption-font-size0.875remCaption sits below body size.
$caption-color-mix70%Caption mixes currentColor at 70% into transparent — softened but AA-legible.

Child images (direct <img>, <picture> > <img>, or any descendant carrying .figure-img) get display: block, max-inline-size: 100%, and block-size: auto. For fixed aspect ratios, intrinsic sizing, or art-direction patterns, see Image.

Override example

app.scss
@use '@adnap/krysalicss/typography/figure' with (
  $display: block,
  $margin-block-end: 2rem,
  $img-margin-block-end: 0.75rem,
  $caption-color-mix: 60%,
);

Tokens consumed

None — this module has no runtime --kc-* tokens. The caption uses color-mix against currentColor, so it re-tints automatically when the surrounding theme's foreground changes.