Skip to content
HomePagesHomePages template kit

frame-aspect-conflict

"No aspect utilities on a framed element — the slot's declared frame owns its aspect."

Venue: check — No aspect utilities on a framed element — the slot’s declared frame owns its aspect.

An element that carries a slot’s frame (the box Slot.Image / Slot.Video render for a slot whose schema declares frame) must not also carry an aspect utility. Every rendered fixture’s class lists are checked; plain (aspect-square), arbitrary-value (aspect-[4/3]), variant-prefixed (md:aspect-video) and arbitrary-property ([aspect-ratio:4/3]) forms all count.

The slot’s declared frame is the single source of truth for the framed element’s per-breakpoint aspect: the editor’s cropper reads it to decide what crop to bake, and the renderer reads the same declaration to draw the box. To keep those two in lockstep whatever else lands on the element, the frame’s aspect-ratio rules are emitted !important — so an aspect class you write on the same element is discarded by the cascade, silently.

That silence is the trap. The page looks right on the canvas and in the preview, because the frame is doing exactly what it declared — but the class you wrote does nothing, and an image cropped for the declared aspect would distort or letterbox if it ever did. The declaration and the class cannot both own the box, so the conflict is graded instead of left to the cascade.

Decide who owns the box. If the declared aspect is wrong, change frame in the slot’s declaration — the cropper and the render move together. If the parent should own the box, opt out with frame={false} and write your own classes; you then own the height as well as the aspect, and fit controls how the image fills it.

<Slot.Image slot={slot.hero_image} className="aspect-[4/3]" />

The slot declares a 16/9 frame, so the element renders 16/9 — the aspect-[4/3] is dead, and the baked crop is 16/9 either way.

Change the declaration, so the cropper follows:

hero_image: image({ label: "Hero image", frame: { breakpoint: 768, desktop: { aspect: 4 / 3 } } }),

Or take the box over entirely:

return <Slot.Image slot={slot.hero_image} frame={false} fit="cover" className="aspect-[4/3] w-full" />;