Utilizing themes with server rendering
Answered
Standard Chinchilla posted this in #help-forum
Standard ChinchillaOP
I just picked up nextjs yesterday, so forgive me if this is something obvious (and fwiw, I've read through the docs)- but how does one facilitate themes (with user specific toggles) with server rendering?
A good example is dark mode.
I want to take advantage of SSR wherever possible- but if the user theme settings are saved in the local browser, I'm not sure how I'd accomplish this. Ignoring the fact that saving the configuration in a cookie would probably work as a workaround- I feel there's a design point here I'm missing.
Maybe passing the server component as a prop to a child component that then wraps it in some client component for faciliating css? Although, I'm not sure If that'd work.
Any and all help would be greatly appreciated!
A good example is dark mode.
I want to take advantage of SSR wherever possible- but if the user theme settings are saved in the local browser, I'm not sure how I'd accomplish this. Ignoring the fact that saving the configuration in a cookie would probably work as a workaround- I feel there's a design point here I'm missing.
Maybe passing the server component as a prop to a child component that then wraps it in some client component for faciliating css? Although, I'm not sure If that'd work.
Any and all help would be greatly appreciated!
Answered by Aleutian Tern
The cookie solution is what is being used to remove the flickering that occurs when the wrong selection is rendered. For example, if you only save to localStorage, you can render the incorrect theme on the server side, and after hydration, the correct theme will be loaded, causing a flickering effect. You’ll also need to inject a script tag into the HTML for the theme to render correctly on the server side. In this repository, you can see how to implement a cookie-based dark mode solution:
You can use as a base for any user related config that needs to be sync at the first render.
https://github.com/rauchg/blog/blob/main/app/theme-effect.ts
You can use as a base for any user related config that needs to be sync at the first render.
https://github.com/rauchg/blog/blob/main/app/theme-effect.ts
7 Replies
Aleutian Tern
The cookie solution is what is being used to remove the flickering that occurs when the wrong selection is rendered. For example, if you only save to localStorage, you can render the incorrect theme on the server side, and after hydration, the correct theme will be loaded, causing a flickering effect. You’ll also need to inject a script tag into the HTML for the theme to render correctly on the server side. In this repository, you can see how to implement a cookie-based dark mode solution:
You can use as a base for any user related config that needs to be sync at the first render.
https://github.com/rauchg/blog/blob/main/app/theme-effect.ts
You can use as a base for any user related config that needs to be sync at the first render.
https://github.com/rauchg/blog/blob/main/app/theme-effect.ts
Answer
@Standard Chinchilla I've written about static personalization earlier, this pattern lets you have theming but keep the page static: https://www.smashingmagazine.com/2022/07/new-pattern-jamstack-segmented-rendering/
to sum it up I am opting for a cookie + URL rewrite in a middleware to change a static param
This is a tad radical though, the client-side example shared above is awesome, I've also liked this package in the past: https://github.com/pacocoursey/next-themes
The big advantage of the client-side solution is that it can use "window.matchMedia("(prefers-color-scheme: dark)").matches"
I don't think this information would be available in headers/cookies
which is the limit of a server-only approach