Few things are as annoying on the web as having the page layout unexpectedly change or shift while you’re trying to view or interact with it. Whether you’re attempting to read an article as it wriggles around in front of you, or you try to click a link only to have another one push it out of the way and take you off to somewhere unexpected, it’s always frustrating.
This layout shifting is especially frustrating on mobile devices, where a big enough change can push all familiar content off-screen and cause a visitor to completely lose her bearings. I would argue that shifting the page layout after the initial render (without relevant user interaction) may be the single most unpleasant user experience a site can create. I’m surprised to see it happen even on really big-name sites that are otherwise very well made. The good news is that it’s fixable.
Luckily, modern browsers don’t perform initial render until the style sheets have finished loading, which means that with some clever CSS we can do a lot toward fixing this problem.
What causes layout shifting?
Most commonly, it’s the result of loading Ajax partials. Ajax is asynchronous, meaning nothing is waiting for it to finish. But when it does finish, and the results are plopped into the document, it can cause re-layout and push other elements around.
It’s especially common with ads but can happen with any layout-affecting content that loads after initial render, including images or even fonts.
I’ve run into this problem on sites I work on myself
The first time I encountered this problem actually wasn’t for ads or images, but for rendered templates from our own server. I was working at Broadleaf Commerce, on a preexisting Admin interface that we were adding features to. We didn’t want to rebuild the whole thing using something like Angular, but we did want some of the content to be able to update without a page refresh. We created Ajax containers bound to server routes that would re-render and send back just a section of the page. It worked quite well, but in some cases, we had multiple of these sections going down the page with static headers in-between. A few seconds after initial visit the headings (and sometimes other static content) would all jump down – exactly the jarring layout shifting experience we’re trying to avoid.
min-height
Fixing with To fix it, I used the browser’s DevTools to measure the height of the resulting content and hardcoded it as a min-height
for the container in the CSS.

min-height: 363px
on a placeholder element.This meant that the surrounding layout began in more or less the state that it would end up, with the only change being the interior of the content boxes. I also set a background color for the containers to suggest that something would go there. These simple additions made the interface much more concrete and predictable. One could debate whether hardcoding the minimum height is wise, given that it decouples the layout from the content. This is why we used min-height
instead of height
. If the content ends up making the element taller, it can still do that, which isn’t great, but it’s slightly better than doing nothing.
Here’s an example of what this would look like (rerun to see delayed ad loading):
See the Pen Avoiding Content Jumps by CSS-Tricks (@css-tricks) on CodePen.
Another Example: A Third-Party Widget
Another time, I was working on a client site who wanted to use the Braintree drop-in UI (https://www.braintreepayments.com/products-and-features/drop-in-ui) for their checkout page.

It’s a great little widget, but you’ll notice that even on Braintree’s own site the content gets pushed around when the widget expands. To Braintree’s credit it does so with a smooth transition which helps maintain some continuity, but the page I worked on still benefitted from a wrapper element with a min-height
, keeping something as fundamental as the checkout button from moving around unexpectedly.
Fixing with Transitions
Using smooth transitions can make an unexpected content change a lot less jarring.
.ad-wrapper {
height: 0;
overflow: hidden;
transition: height 0.66s ease-out;
}
.ad-wrapper.loaded {
height: 100px;
}
See the Pen Avoiding Content Jumps by CSS-Tricks (@css-tricks) on CodePen.
The downside is that they only work when you set dimensions explicitly; min-
properties and content-derived layout changes won’t transition. Still, transitions can be used in cases where you have unpredictably sized content and you don’t mind using JavaScript to query its size and smoothly resize the container accordingly.
Another Example: Font Loading Shifts
In a more unusual case, I was once working on a client site that prominently used a horizontally condensed font. The problem was that it had to be loaded in, so after a few seconds, nearly all of the site content would suddenly change size. It wasn’t as drastic of a shift as the above examples, but since it affected nearly everything on the page it was much more of an eyesore. In the end I found this really great article that supplies a verbose but effective font-family
statement that covers websafe condensed fonts for all major platforms. But before finding that, min-height
was once again my friend.
Examples From Around The Web
The Verge (mobile)
I notice on The Verge that
- Their ad at the top is sometimes a small banner and sometimes a larger ad
- They seem to already be using a
min-height
technique for the banner-sized ad
It’s possible that their ad API doesn’t tell them what size the ad will be. If it does, they should adopt the min-height
accordingly. If this isn’t possible, they might already be doing all they can with pure CSS. Although even then, I would argue that from a UX perspective, a really large ad should go further down among the content instead of at the very top, and the banner would be more appropriate at the top. Then again, showing the user a nearly full-screen ad as soon as they visit the main page is probably a lucrative source of revenue.
Kotaku (mobile)

Worth noting on Kotaku is that there’s no ad at the very top of the main page, so when you first visit it there isn’t a jump. However, if the page ever loads while already scrolled down a way (such as after pressing the back button when you’ve finished reading an article), there is some massive, disorienting jumping caused by large ads peppered throughout the post stream. They all seem to be the same size, so this would be a simple fix.
Summary
One of the most important things to keep in mind when designing any user experience is expected behavior. We expect that clicking a blue, underlined segment of text will take us to another page. If it instead opens a modal or does nothing at all, we have a confusing and frustrating user experience. The same is true of navigating the page we’re already on. When we see an article appear in front of us, we expect it to sit still unless we scroll it. When we see a link or a button, we expect it to still be there when we reach to tap on that spot. Violations of these basic assumptions are at best unpleasant, at worst frustrating or even disorienting.
As I was creating a site that utilizes plain ol’ Moustache templating, I was wondering how sites deal with this when almost everything, even the main nav, comes from a backend.
Is there a good resource on dealing with this?
I hate content jumping! To me, it’s one of the most infuriating user experiences when on a mobile device. Thank you for writing this and hopefully this is picked up as a best practice by new developers.
You can maintain scroll position while images loaded with https://github.com/changbenny/scrollbear
demo http://changbenny.github.io/scrollbear/demo/static_img.html
Ahh, was just thinking about this for a couple of website projects. Good to know i was on the right path.
Very neat!
I came here from a link on the Front-end newsletter.
Bit of an irony that disposing of their ‘pop-up’ triggered a (wait for it) complete page refresh and thus ‘back to the top’ Content Jump.
I just came along this article, and guess what I experienced:
Content jumping due to unaligned ad placeholders!
Is this on purpose to enforce ad conversions, or is it just “pray water and drink wine”?
Anyway, there’s another strategy web developers should implement:
Choose a slow computer/browser environment and use a line speed limiting proxy server.
Good suggestion! Google Chrome lets you throttle the tab bandwidth to simulate slower connections, which could be a great way to debug these sorts of situations.
It really is the worst, especially when you go to click on a link and then UNEXPECTED LAYOUT SHIFT! and you click on something you didn’t mean to. UGH!
It was that exact event that motivated me to write this article. My hope is that by raising awareness of the issue, the web will become a slightly less annoying thing for me to navigate ;)
min-height’s hard-coded dimensions create further problems. Why not use containers of fixed aspect ratio? In this example, the image container always has the same aspect ratio regardless if the image is loaded or not or if the page is resized: https://radogado.github.io/natuive/#aspect-ratio
News.com is a good example of shifting UI components. They have this news stream that pops out on the left. Happens 100% of the time by accident, so it’s basically useless to me and super annoying.
Also Kijiji’s Android app constantly loads ads after content at the top and I’ve clicked numerous ads with no intention of viewing their products. I’ve probably generated over $1000 in revenue and the advertiser will never see the value because they were all accidental. Also very annoying and now that I know there is a fix, these kinds of issues will be even more annoying in the future.
In Chrome you can enable a flag for Scroll Anchoring. This automatically shifts the page when new content is loaded so that the current section you’re looking at remains in view.
Go to chrome://flags/#enable-scroll-anchoring
You can also use intrinsic ratios to create a placeholder for images or other components. This is typically preferable to setting a min-height since it’s a responsive solution.
This article explains the technique well: http://alistapart.com/article/creating-intrinsic-ratios-for-video
This is my absolute number one pet peeve with regards to user experience and web development. As the article suggests, we as developers need to hold an expectation that nearly nothing will populate the page’s layout since most everything is loaded asynchronously.
Mentioned briefly by Radoslav above, I think even more important than forecasting 3rd party widgets and the like is forecasting images by way of enforcing an aspect ratio. This is very easily remedied with having an
<img />
wrapper like<figure />
that has a set aspect ratio by the percentage-based padding-top/bottom strategy. Of course, the client code would need prior knowledge at page load of the images dimensions, but most web servers have methods for providing this.