Media
Theme images live outside the media library, so WordPress knows nothing about their dimensions and every unstyled image shifts layout while it loads. Blockstudio closes that gap with a generated metadata manifest, a template helper that always emits real dimensions, and an optional lazy loader.
Rendering images
bs_media_image() renders theme assets with real width, height, and a reserved
aspect ratio:
<?php
echo bs_media_image([
'src' => 'assets/images/hero.webp',
'alt' => 'Hero',
'class' => 'hero-media',
'sources' => [
['srcset' => '/hero-small.webp', 'media' => '(max-width: 640px)'],
],
]);
?>
The output is a figure.blockstudio-media with an inline aspect-ratio around
an img carrying real width, height, loading, and decoding values.
src takes a theme-relative path, an absolute path, or a full URL, and
attachmentId covers media library images. eager opts out of lazy loading
above the fold, and sources emits a <picture> element with the given
alternates.
The helper always emits known width, height, and aspect ratio values when
metadata exists. Lazy mode uses only blockstudio-* classes, attributes,
handles, and globals.
The metadata manifest
Dimensions come from assets/media.json, written by
Blockstudio\Media_Metadata_Builder in a build step or by hand:
use Blockstudio\Media_Metadata_Builder;
(new Media_Metadata_Builder())->write(
get_stylesheet_directory(),
true
);
This writes deterministic metadata for the theme’s assets and, with the second
argument, optional WordPress attachments. Regenerate it whenever files under
assets/ change.
Media_Metadata_Builder::build( string $root ) returns the manifest without
writing it; write() is the variant that persists.
Blockstudio\Media_Metadata::reset() clears the in-process cache after a
rebuild, which long-lived build processes need before rendering against fresh
metadata.
Lazy loading
The performance.media settings drive the frontend loader:
{
"performance": {
"media": {
"lazy": true,
"skeleton": true,
"metadata": true,
"rootMargin": "300px"
}
}
}
With lazy on, the real URL moves to data-src behind a correctly sized
placeholder and Blockstudio’s intersection-based loader swaps it in as the
image approaches the viewport, rootMargin ahead of time. skeleton shows the
built-in loading placeholder, and metadata declares that assets/media.json
is in use.
The speed and strict performance profiles
enable the loader by default; compat leaves it off. Every child value can
override its profile default.
The full
performance.mediaoption table.
Media metadata is step two of the production adoption order.