v1.1.1

Media

Responsive image, video, and embed components for displaying visual content.

Image with Caption

Responsive image with figcaption, lazy loading, and rounded border.

html
A beautiful landscape photograph taken at sunset
<figure class="vt-w-full vt-max-w-md vt-rounded-2xl vt-border vt-border-border-default vt-overflow-hidden">
  <div class="vt-aspect-[16/9] vt-bg-gradient-to-br vt-from-info-fill/20 vt-to-info-fill/5 vt-flex vt-items-center vt-justify-center">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-10 vt-h-10 vt-text-info-fill/40">
      <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
    </svg>
  </div>
  <figcaption class="vt-px-4 vt-py-3 vt-text-sm vt-text-foreground-muted vt-bg-surface-card vt-border-t vt-border-border-default">
    A beautiful landscape photograph taken at sunset
  </figcaption>
</figure>

Video

Native HTML5 video player with controls, wrapped in a 16:9 aspect ratio container.

html
HTML5 Video Player
<div class="vt-w-full vt-max-w-lg vt-aspect-[16/9] vt-rounded-2xl vt-border vt-border-border-default vt-overflow-hidden vt-bg-surface-moderate vt-flex vt-flex-col vt-items-center vt-justify-center vt-gap-3">
  <div class="vt-w-14 vt-h-14 vt-rounded-full vt-bg-surface-subtle vt-flex vt-items-center vt-justify-center">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-play vt-w-6 vt-h-6 vt-text-foreground-muted vt-ml-0.5">
      <path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"></path>
    </svg>
  </div>
  <span class="vt-text-sm vt-font-medium vt-text-foreground-muted">HTML5 Video Player</span>
</div>

YouTube Embed

Responsive YouTube embed with 16:9 aspect ratio. Uses iframe with proper allow attributes.

html
YouTube Embed
<div class="vt-w-full vt-max-w-lg vt-aspect-[16/9] vt-rounded-2xl vt-border vt-border-border-default vt-overflow-hidden vt-bg-surface-moderate vt-relative vt-flex vt-flex-col vt-items-center vt-justify-center vt-gap-3">
  <div class="vt-w-16 vt-h-12 vt-rounded-xl vt-bg-error-fill vt-flex vt-items-center vt-justify-center">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-play vt-w-5 vt-h-5 vt-text-generic-white vt-ml-0.5">
      <path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"></path>
    </svg>
  </div>
  <span class="vt-text-sm vt-font-medium vt-text-foreground-muted">YouTube Embed</span>
</div>

Grid-based image gallery with consistent aspect ratios and lazy loading.

html
<div class="vt-grid vt-grid-cols-3 vt-gap-3 vt-max-w-lg">
  <figure class="vt-rounded-xl vt-border vt-border-border-default vt-overflow-hidden">
    <div class="vt-aspect-square vt-bg-gradient-to-br vt-from-info-fill/20 vt-to-info-fill/5 vt-flex vt-items-center vt-justify-center">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-6 vt-h-6 vt-text-info-fill/40">
        <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
      </svg>
    </div>
  </figure>
  <figure class="vt-rounded-xl vt-border vt-border-border-default vt-overflow-hidden">
    <div class="vt-aspect-square vt-bg-gradient-to-br vt-from-success-fill/20 vt-to-success-fill/5 vt-flex vt-items-center vt-justify-center">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-6 vt-h-6 vt-text-success-fill/40">
        <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
      </svg>
    </div>
  </figure>
  <figure class="vt-rounded-xl vt-border vt-border-border-default vt-overflow-hidden">
    <div class="vt-aspect-square vt-bg-gradient-to-br vt-from-warning-fill/20 vt-to-warning-fill/5 vt-flex vt-items-center vt-justify-center">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-6 vt-h-6 vt-text-warning-fill/40">
        <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
      </svg>
    </div>
  </figure>
  <figure class="vt-rounded-xl vt-border vt-border-border-default vt-overflow-hidden">
    <div class="vt-aspect-square vt-bg-gradient-to-br vt-from-error-fill/20 vt-to-error-fill/5 vt-flex vt-items-center vt-justify-center">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-6 vt-h-6 vt-text-error-fill/40">
        <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
      </svg>
    </div>
  </figure>
  <figure class="vt-rounded-xl vt-border vt-border-border-default vt-overflow-hidden">
    <div class="vt-aspect-square vt-bg-gradient-to-br vt-from-info-fill/20 vt-to-info-fill/5 vt-flex vt-items-center vt-justify-center">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-film vt-w-6 vt-h-6 vt-text-info-fill/40">
        <rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M7 3v18"></path><path d="M3 7.5h4"></path><path d="M3 12h18"></path><path d="M3 16.5h4"></path><path d="M17 3v18"></path><path d="M17 7.5h4"></path><path d="M17 16.5h4"></path>
      </svg>
    </div>
  </figure>
  <figure class="vt-rounded-xl vt-border vt-border-border-default vt-overflow-hidden">
    <div class="vt-aspect-square vt-bg-gradient-to-br vt-from-surface-strong/20 vt-to-surface-strong/5 vt-flex vt-items-center vt-justify-center">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-6 vt-h-6 vt-text-foreground-muted/40">
        <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
      </svg>
    </div>
  </figure>
</div>

Avatar Image

Circular image for profile pictures and avatars.

html
<div class="vt-avatar vt-w-16 vt-h-16 vt-bg-gradient-to-br vt-from-info-fill/30 vt-to-info-fill/10 vt-border-2 vt-border-border-default">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-6 vt-h-6 vt-text-info-fill/40">
    <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
  </svg>
</div>
<div class="vt-avatar vt-w-12 vt-h-12 vt-bg-gradient-to-br vt-from-success-fill/30 vt-to-success-fill/10 vt-border-2 vt-border-border-default">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-5 vt-h-5 vt-text-success-fill/40">
    <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
  </svg>
</div>
<div class="vt-avatar vt-avatar-md vt-bg-gradient-to-br vt-from-warning-fill/30 vt-to-warning-fill/10 vt-border-2 vt-border-border-default">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-image vt-w-4 vt-h-4 vt-text-warning-fill/40">
    <rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
  </svg>
</div>

Background with Overlay

Image used as a background with a gradient overlay and text content on top.

html

Featured Article

A guide to building responsive media layouts

<div class="vt-w-full vt-max-w-lg vt-relative vt-rounded-2xl vt-overflow-hidden vt-h-64">
  <div class="vt-absolute vt-inset-0 vt-bg-gradient-to-br vt-from-info-fill/30 vt-to-info-fill/60"></div>
  <div class="vt-absolute vt-inset-0 vt-bg-gradient-to-t vt-from-generic-black/80 vt-to-transparent"></div>
  <div class="vt-absolute vt-bottom-0 vt-p-6 vt-text-generic-white">
    <h3 class="vt-text-lg vt-font-bold">Featured Article</h3>
    <p class="vt-text-sm vt-opacity-80">A guide to building responsive media layouts</p>
  </div>
</div>

Guidelines

Present images, video, and embeds in responsive, aspect-ratio-locked containers with meaningful alt text.

Sunset over the hills
Do
Lock media to a fixed aspect ratio and describe it with a caption.
Don't
Don't crop media to a fixed height — lock its ratio.
Do
Keep gallery thumbnails on one consistent aspect ratio.
Don't
Don't mix aspect ratios in a grid — it looks ragged.

API Reference

All CSS classes and data attributes.

Class Type Description
vt-aspect-square / vt-aspect-video Layout Aspect-ratio boxes for images and embeds
vt-rounded-2xl vt-overflow-hidden Layout Card-radius clipping for media content
vt-object-cover Modifier Media fills its box without distortion

Accessibility

Keyboard and screen reader support.

Feature Details
Alt text Every img carries meaningful alt; decorative media uses alt=""
Embeds iframes get a title describing the embedded content