Best way to handle totally different desktop/mobile layouts (heavy components, SSR flicker issue)
Unanswered
Greek Shepherd posted this in #help-forum
Greek ShepherdOP
When building Next.js apps with totally different layouts for desktop and mobile, is it better to use Tailwind’s responsive utilities (keeping both layouts in the DOM but hidden) or to conditionally render components with JS?
The JS-based approach causes a brief flicker on reload due to SSR/client width mismatch (desktop renders first, then switches to mobile).
The issue is that both layouts are pretty heavy, so having both in the DOM at once isn’t ideal either.
Ik this has probably been asked before, but I haven’t found a solid solution yet. Anyone figured out the clean way to handle this?
The JS-based approach causes a brief flicker on reload due to SSR/client width mismatch (desktop renders first, then switches to mobile).
The issue is that both layouts are pretty heavy, so having both in the DOM at once isn’t ideal either.
Ik this has probably been asked before, but I haven’t found a solid solution yet. Anyone figured out the clean way to handle this?
9 Replies
@Greek Shepherd When building Next.js apps with totally different layouts for desktop and mobile, is it better to use Tailwind’s responsive utilities (keeping both layouts in the DOM but hidden) or to conditionally render components with JS?
The JS-based approach causes a brief flicker on reload due to SSR/client width mismatch (desktop renders first, then switches to mobile).
The issue is that both layouts are pretty heavy, so having both in the DOM at once isn’t ideal either.
Ik this has probably been asked before, but I haven’t found a solid solution yet. Anyone figured out the clean way to handle this?
When building Next.js apps with totally different layouts for desktop and mobile, is it better to use Tailwind’s responsive utilities (keeping both layouts in the DOM but hidden) or to conditionally render components with JS?
Still better to use CSS.
conditionally rendering components with JS has never been very intuitive and would require hacky solution to get the device info before you render them which means janky <script> and ruins SEO at worst.
Unless you can get device information at the server, that means you can render them in the server using conditionals but at the cost of making the route fully dynamic (to get the device info via headers or cookies)
Pacific sand lance
it's up to you, with simple things i'd go with css, with more complex (e.g. completly different on mobile and desktop) i'd go with conditional renders
also you can render conditionally without screen flickering, nextjs provides
userAgentFromString (from next/server) which can be used to resolve device type (mobile etc.)@Pacific sand lance also you can render conditionally without screen flickering, nextjs provides `userAgentFromString` (from `next/server`) which can be used to resolve device type (mobile etc.)
Greek ShepherdOP
Hey man, mind showing a code example of how you handle it?
Pacific sand lance
import { headers } from "next/headers";
import { userAgentFromString } from "next/server";
async function ConditionalComponentStuff() {
const _headers = await headers();
const userAgent = _headers.get("user-agent");
const isMobile = userAgentFromString(userAgent ?? undefined).device.type === "mobile";
return <MediaQuery query="some desktop media query" fallback={<MobileVersionOfSomeComponent />} initialValue={!isMobile}><DesktopVersion /></MediaQuery>;
}something like that i guess
MediaQuery would be client component which accepts default/initial value to prevent flickeringTurkish Van
The CSS should be fine.
If you’ve got a heavy component used only on Desktop or Mobile, you can split it out and dynamically import it with a hook that checks if it’s really needed.
No flickering, no heavy redundant parts being loaded, and you remain static.
If you’ve got a heavy component used only on Desktop or Mobile, you can split it out and dynamically import it with a hook that checks if it’s really needed.
No flickering, no heavy redundant parts being loaded, and you remain static.