Image dimensions
Opt-inAuto-detect and inject width/height attributes on local img elements to eliminate Cumulative Layout Shift.
The imageDimensions feature reads image file headers at build time and injects width and height attributes on <img> elements that reference local files. Providing these attributes lets browsers allocate the correct space before the image loads, eliminating Cumulative Layout Shift (CLS).
Reference: rehype-img-size.
Enable
// zfb.config.ts
export default defineConfig({
markdown: {
features: {
imageDimensions: {},
},
},
});Behaviour
For each <img> element, the plugin:
Skips elements that already carry
widthorheightattributes.Skips
data:URLs unconditionally. Skipshttp:,/ / https:, and protocol-relative (/ / /) URLs when/ skipRemoteistrue(the default).Resolves the
srcto an absolute path (see Source resolution below).For raster images, reads only the file header — no full decode occurs — and injects
width="W" height="H".For SVG files (which carry no raster header), reads the intrinsic size from the markup: an explicit
width/heightpair (in user units orpx) is used when present, otherwise theviewBoxsupplies the size/aspect ratio. An SVG with no determinable size is left unchanged, silently.If a raster file cannot be found or is not a recognised image format, emits a build warning and leaves the element unchanged. Undimensionable SVGs do not warn.
Supported formats: PNG, JPEG, GIF, WebP, AVIF (header probe) and SVG (parsed from width/height/viewBox).
Source resolution
The plugin resolves src values against the file system using BuildContext:
Absolute paths (e.g.
/) are resolved against the project'simg/ hero. png publicdirectory.Relative paths (e.g.
.,/ assets/ hero. png assets/) are resolved relative to the markdown source file's directory.hero. png Remote and
data:URLs are skipped silently.
Options
skipRemote(defaulttrue) — whentrue,http:,/ / https:, and protocol-relative (/ / /) image sources are skipped. Set to/ falseonly for unusual setups; probing remote images requires network access at build time.data:URLs are always skipped regardless of this setting.
imageDimensions: { skipRemote: false },Example
Given a 400×300 PNG at public/ and this markdown:
The plugin produces:
<img src="/images/hero.png" alt="Hero image" width="400" height="300">An <img> with explicit dimensions is left unchanged:
<img src="/images/hero.png" width="200" height="150" />Caching
The plugin caches (path, mtime) → (width, height) in memory. A second <img> reference to the same file within the same build hits the cache rather than re-reading the file.
Ordering
ImageDimensionsPlugin runs in the hast phase, before SyntectPlugin. It injects width and height on <img> elements found in the document.
Requirements
This feature uses the wave-6 BuildContext seam. The pipeline must be invoked via Pipeline::run_with_context (or Pipeline::apply_hast_visitors_with_context) for dimensions to be injected. When the feature is wired but run (without context) is called, the plugin is a no-op.