Image and Video tags
In web development, there are many ways to render elements. However, within Terra, we standardize our approach so all team members follow a consistent structure and methodology. This consistency enhances:
- Maintainability
- Readability
- Scalability
- Overall quality across projects
Images
Section titled “Images”Typically, when adding images, we might use a simple <img src="asset.jpg" /> tag, which works well for many cases.
However, to achieve perfect rendering, performance optimization, and visual stability, additional attributes are essential.
At Terra, images must follow specific structural and performance rules.
01. Width, Height & Layout Stability
Section titled “01. Width, Height & Layout Stability”We always include the image’s width and height directly in the HTML. This:
- Improves performance
- Prevents layout shifts (CLS)
- Stabilizes lazy loading behavior
Additionally, we set a dynamic aspect-ratio, unless one of the following conditions applies in the images:
- The aspect ratio is already defined in CSS.
- The image has a fixed height in CSS.
- The image is positioned absolutely and does not affect surrounding layout.
02. Responsive Images (srcset & sizes)
Section titled “02. Responsive Images (srcset & sizes)”We use the srcset attribute to prevent loading unnecessarily large images on smaller devices.
srcset allows us to provide multiple versions of the same image at different widths (e.g., 580w, 1024w, 2000w). The browser then selects the most appropriate file based on:
- The viewport size
- The device pixel ratio (Retina, 2x, etc.)
- The space the image occupies in the layout (defined by sizes)
In simple terms:
srcset→ defines the available image versionssizes→ tells the browser how large the image will render in the layout
Together, they allow the browser to choose the smallest possible image that still looks sharp.
Both WordPress and Sanity provide built-in tools to manage responsive images.
What You Need to Define
Section titled “What You Need to Define”When adding an image, you only need to determine its expected width in layout and define it in the sizes attribute.
Examples:
-
Full-width image:
sizes="100vw" -
50% width on desktop, 100% on ≤580px:
sizes="(min-width: 581px) 50vw, 100vw" -
Fixed 100px icon:
sizes="100px"
The sizes attribute:
- Can include media queries
- Can use any unit (vw, px, etc.)
- Must clearly reflect real layout behavior
This ensures optimal image loading and consistent layout rendering.
Preferred Image Formats
Section titled “Preferred Image Formats”To maximize performance, we prioritize formats in this order:
- WebP → Best compression and smallest file sizes
- JPG → If WebP is not supported or available
- PNG → Only when necessary
Example: WordPress - generate_image_tag and render_wp_image()
Section titled “Example: WordPress - generate_image_tag and render_wp_image()”<?php render_wp_image([ 'image' => $image, 'sizes' => '(min-width: 1025px) 33vw, (min-width: 581px) 50vw, 95vw', 'class' => 'c--media-a', 'isLazy' => true, 'showAspectRatio' => true, 'decoding' => 'async', 'fetchPriority' => 'auto', 'addFigcaption' => false, ]);?>Example: Astro
Section titled “Example: Astro”<Asset payload={{ type: "Image", url: "https://example.com/image.jpg", sizes: "(max-width: 600px) 480px, 800px", alt: "Example image", customClass: "image-class", }} />Example: Vue
Section titled “Example: Vue”<template> <Asset :payload="imagePayload" /></template>
<script setup>const imagePayload = { type: 'Image', url: 'https://example.com/image.png', alt: 'Example Image', customClass: 'image-class', attributes: { width: 800, height: 600, },};</script>Resulting HTML Output
Section titled “Resulting HTML Output”<img alt="Image alt" src="imageSrc.webp" srcset="imageSrc.webp 2000w, imageSrc.webp?w=1300 1300w, imageSrc.webp?w=1024 1024w, imageSrc.webp?w=810 810w, imageSrc.webp?w=580 580w" width="2000" height="500" sizes="(max-width: 580px) 95vw, (max-width: 1024px) 50vw, 33vw" class="c--media-a g--lazy-01" style="aspect-ratio: 2000 / 500;" decoding="async" fetchpriority="auto">Videos are heavy assets. Our goal is to: Avoid loading them on initial page load, load them only when needed and reduce unnecessary resource consumption
We typically use Boostify so videos:
- Load only when scrolled into view (autoplay)
- Load only when clicked (non-autoplay)
- Do not block initial rendering
A Boostify video setup only requires a <div> element; when the video needs to load, the <video> element is dynamically created within that div.
- In HTML
<div class="c--video-a js--boostify-player" data-video-src="video.mp4"></div>In this setup, data-video-src holds the video file source, and the video will only load when necessary, contributing to improved page performance.
- In JavaScript
To use Boostify, you’ll need to import the Boostify package and include some JavaScript code, like this:
document.querySelectorAll('.js--boostify-player').forEach(element => { bstf.videoPlayer({ url: { mp4: getAttribute('data-video-src'), }, attributes: { class: "c--video-a__media", loop: false, muted: false, controls: true, autoplay: true, }, appendTo: element, });})- Rendered Output
<div class="c--video-a js--boostify-player" data-video-src="video.mp4"> <video class="c--video-a__media" controls autoplay playsinline="true"> <source src="video.mp4" type="video/mp4"> </video></div>- Example: Astro
<Asset payload={{ type: "Video", video_type: 'file', //file example video_file: '/asset/video/placeholder.mp4', hasPosterImg: true, poster_url: 'https://example.com/image.jpg' customClass: 'video-class', isBoostify: true, }}/>- Example: Vue
<template> <Asset :payload="videoPayload" /></template>
<script setup>const videoPayload = { type: 'Video', video_type: 'url', //embed example video_url: 'https://www.youtube.com/watch?v=example', customClass: 'video-class', isBoostify: true, //boostify enabled};</script>Native <video> Tag (When Boostify Is Not Possible)
Section titled “Native <video> Tag (When Boostify Is Not Possible)”Sometimes we cannot use Boostify (e.g., hero background videos). When embedding directly with <video>, autoplay requires:
- muted
- playsinline
- poster
Example:
<div class="c--video-a"> <video class="c--video-a__media" poster="video-poster.webp" autoplay loop playsinline muted> <source src="video.mp4" type="video/mp4"> </video></div>Knowledge Check
Test your understanding of this section
Loading questions...