Sanity content loading bottom-to-top with staggered flash on first load
Based on your description of content loading "bottom-to-top in a staggered sequence," this is almost certainly a Next.js rendering issue rather than anything Sanity-specific. Here are the most likely causes and solutions:
1. React Suspense Boundaries / Streaming SSR
If you're using Next.js 13+ with the App Router, the default behavior uses streaming with React Server Components. This progressively sends HTML to the browser as components resolve, which can create that staggered loading effect.
Solutions:
- Add a
loading.tsxfile at your route level to show a loading state while everything resolves - Wrap sections in Suspense boundaries with meaningful fallbacks
- If you want everything to load at once, ensure all async operations complete before rendering (though this increases time-to-first-byte)
2. Client-Side Data Fetching
If you're fetching Sanity content with useEffect or client-side queries, each component renders empty first, then populates with data after hydration. This creates the exact "flash" you're describing.
Solution:
- Move to server-side data fetching using Server Components (App Router) or
getStaticProps/getServerSideProps(Pages Router) - This way, content is already in the HTML when it reaches the browser
3. Font Loading (FOIT/FOUT)
If you're using custom fonts without proper optimization, text might be invisible (FOIT - Flash of Invisible Text) or render with fallback fonts first (FOUT - Flash of Unstyled Text), causing layout shifts as fonts load.
Solution:
- Use
next/fontto automatically optimize font loading - This eliminates layout shift and prevents font flashing
4. Image Loading Without Dimensions
If you're using images without specified dimensions, content below them will shift as images load and establish their height.
Solution:
- Use
next/imagewith explicitwidthandheightprops - Add
priorityprop to above-the-fold images - This reserves space and prevents cumulative layout shift
5. CSS-in-JS / Styled Components FOUC
If you're using styled-components, Emotion, or similar CSS-in-JS libraries without proper SSR setup, styles may load after HTML, causing a Flash of Unstyled Content.
Solution:
- Follow the Next.js styled-components setup guide for App Router
- Ensure your CSS-in-JS library is properly configured for SSR
6. Dynamic Imports with ssr: false
If you're using next/dynamic with { ssr: false }, those components won't render until client-side hydration completes, causing content to pop in.
Solution:
- Only disable SSR when absolutely necessary (like for components that require
windowor browser APIs) - Add loading states to dynamic imports
Quick Diagnostic Steps
- Check Network Tab: Are multiple requests loading content after initial page load? That's client-side fetching.
- Check Performance Tab: Record a page load and look at the rendering timeline. Chrome DevTools can show you exactly when elements appear.
- Disable JavaScript: If content doesn't appear at all with JS disabled, you're relying too heavily on client-side rendering.
- Check for Hydration Errors: Look in your browser console for any React hydration mismatch warnings.
Most Likely Culprit
Given the "bottom-to-top" staggered pattern, I'd bet on client-side data fetching combined with Suspense streaming. If you're fetching Sanity content in individual components rather than at the page level, each component will resolve independently, creating that staggered effect.
Try consolidating all your Sanity queries into a single server-side fetch at the page level, then pass that data down to child components as props. This should eliminate the staggered loading entirely.
Show original thread9 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.