BlogDevelopment

Layout Shift From a Designer's Side: Images, Fonts, Embeds

Layout shift is often a design problem, not a dev one. Here is why it happens with images, fonts and embeds, and what to specify in your files.

Denny Pratama

04 Nov 2026 · 7 min read · Development

Layout Shift From a Designer's Side: Images, Fonts, Embeds

The mistake is simple: designing every screen as if it were already fully loaded.

In Figma, the hero image is there. The custom font is there. The video embed is there. Nothing arrives late, so nothing moves. In a browser, all of those things arrive at different times, and the page rearranges itself as they do.

That rearranging is layout shift. It's what happens when you go to tap a link and the page jumps, and you hit something else. Google measures it as Cumulative Layout Shift (CLS), one of the Core Web Vitals. I'm a designer who recently started building his own designs, so I'll stay on the design side of it: what causes shift, why we create it without noticing, and what to put in a file to prevent it.

01Why designers cause layout shift without meaning to

Developers get blamed for layout shift, but the root is often in the design.

A static mockup has no loading order. It never shows the space a banner will take once it appears, or what a headline does when the font swaps. Those gaps are invisible in the file, so they stay invisible in the build, until someone opens the page on a slow connection.

If you build your own designs with AI tools, this matters even more. The tool produces what you describe. If you never mention reserved space, you will likely get an image tag with no dimensions and a banner that pushes everything down.

02Images: the biggest offender

A browser can't know how tall an image is until it has downloaded at least enough of it to read its dimensions. If the page doesn't say how much room to leave, the text below sits at the top, then jumps down when the image arrives.

What goes wrong

Say a blog card has a thumbnail, a title and a date. In the design, the thumbnail is a neat 16:9 rectangle. In the code, it's an image with no width, height or aspect ratio. On a slow connection, the title renders right under the card's top edge, then drops when the image loads. Multiply that by a grid of twelve cards.

What to specify

  • An aspect ratio for every image slot. Write "16:9" or "4:3" in the file, not just a pixel size at one breakpoint.
  • Width and height attributes on images. Modern browsers use them to work out the ratio before the file loads. This is widely documented, and it's the first thing I'd check.
  • CSS aspect-ratio for containers where the image is cropped to fit.
  • A background color or placeholder for the slot, so the empty space looks intentional.

One more point: if users upload images, the slot ratio should be fixed and the image cropped to it. Otherwise a portrait photo breaks a layout designed for landscape ones.

03Fonts: the shift you can't see in Figma

Figma has your custom font installed. A visitor's browser doesn't, until it downloads it.

Browsers handle that gap in one of two ways. They show text in a fallback font and swap when the real one arrives, or they hide the text briefly. If the fallback is wider or taller than your font, lines wrap differently and the text block changes size on swap. Everything under it moves.

What to do about it

  • Pick a fallback that's close. Compare your font to common system fonts and choose the nearest in width and x-height. Your developer or tool can then adjust the fallback's metrics with CSS properties like size-adjust, which exist for exactly this.
  • Use fewer weights. Each weight is another file to load. Two or three weights cover most interfaces.
  • Don't put fragile layouts on top of a font swap. A button sized tightly to its label, or a headline that must fit exactly two lines, will visibly jump.
  • Preload the font used above the fold, if your developer or framework supports it.

A good test is to temporarily set your design to a fallback font in Figma. If the layout falls apart, the real page will wobble during loading.

04Embeds, ads and late-arriving banners

Anything inserted after the page starts rendering can push content down. Common examples:

  • Video embeds (YouTube, Vimeo)
  • Social posts and maps
  • Cookie banners
  • Announcement bars
  • Chat widgets that expand
  • Newsletter prompts at the top of content

Reserve the space

For embeds, the answer is the same as images: give the container a fixed aspect ratio so the space exists before the content does. A 16:9 video wrapper holds its shape whether the player has loaded or not.

For banners, decide where they live. A cookie notice that overlays the bottom of the screen doesn't move anything. One that gets inserted above the header shoves the whole page down. As a designer, you can choose the first option on purpose.

If something has to appear at the top, either reserve its height from the start or place it where nothing below depends on it.

05Interactions that look like shift but aren't the same problem

Layout shift that comes right after a user action, such as clicking to expand an accordion, is treated differently from unexpected movement, and it's generally fine. The problem is movement the user didn't ask for.

Still, I'd be careful with:

  • Content that appears in the middle of a list while someone is reading it.
  • Buttons that change position when a label changes, such as "Save" becoming "Saving…". Giving the button a stable width avoids the jump.
  • Skeleton screens that don't match the final layout. A skeleton helps only if the real content fills the same space. For more on this thinking, see Designing Loading and Error States for AI Features, which covers loading states in more detail.

06A small handoff checklist

Add this to your design file or your prompt to the AI tool:

  1. Every image slot has an aspect ratio, and the crop behavior is stated.
  2. Embeds have a fixed-ratio container.
  3. Body and heading fonts have a named fallback, and you've viewed the design with it.
  4. Banners, bars and widgets have a defined position and reserved height.
  5. Dynamic buttons and labels have a stable width.
  6. Skeletons match the real layout.

Then test it. Open Chrome DevTools, throttle the network to a slow setting, and reload. Watch what moves. Lighthouse reports a CLS score and highlights the elements responsible, so you can trace a jump to a specific component rather than guessing. If you're reviewing AI-generated pages, add this to the routine in A Designer's Checklist for Reviewing AI-Built UI Before Shipping.

07The takeaway

Layout stability is a design decision. Any element that arrives late needs a space that exists before it does, and a state that looks fine while it's empty.

You don't have to write the code to prevent most shift. You only have to stop designing the finished state alone, and start drawing the page as it looks one second into loading.

08Frequently asked questions

What is Cumulative Layout Shift (CLS)?

CLS is a Core Web Vitals metric that measures how much visible content moves unexpectedly while a page loads. Google's guidance treats a score of 0.1 or less as good. The lower the number, the more stable the page feels.

Do I need to know how to code to prevent layout shift?

No, but you need to specify things a developer or AI tool can't guess: image aspect ratios, reserved space for embeds and banners, and a fallback font. Handing these over in the design file prevents most shifts before any code is written.

How do I check whether my page shifts?

Open the page in Chrome DevTools, throttle the network in the Network tab, and reload while watching the layout. Lighthouse and the Performance panel also report layout shifts and show which elements moved.

Development

Denny Pratama

Product designer in Indonesia. Since 2018 I’ve designed SaaS products, dashboards and marketing sites, and now I build my own designs too.

About me