switch image based on light and dark mode doesn't work well ?

here i need to swap between 2 images based on theme mode like if it light i need logo-1 but if it dark i need it to be logo-2 with using this code from below but no luck import { unstable_getImgProps as getImgProps } from 'next/image' export function Logo() { const common = { alt: 'logo', width: 40, height: 30 } const { props: { srcSet: dark } } = getImgProps({ ...common, src: '/images/logo/logo.webp' }) const { props: { srcSet: light , ...rest } } = getImgProps({ ...common, src: '/images/logo/logo-2.webp' }) return ( <picture> <source media="(prefers-color-scheme: dark)" srcSet={dark} /> <source media="(prefers-color-scheme: light )" srcSet={light} /> <img {...rest} /> </picture> ) } it's working on dark mode if i swap between 2 images it just worked fine but no luck with light mode it doesn't update at all if i switching between light and dark does anyone has similar issue and how i can fix it ?
22 Replies
Christoph
Christoph17mo ago
On first glance, I only notice an extra space between light and ) but that's probably not the issue. Best to debug it in the browser. What's the resulting HTML?
ahmedqaram
ahmedqaramOP17mo ago
nothing and i confirm that toggling working corectly by debuging if theme is light or dark on the other hand i was suspicious about (prefers-color-scheme ) but i make it working by adding this lines export function Logos() { const { setTheme, theme } = useTheme() const common = { alt: 'logo' } const { props: { srcSet: dark } } = getImgProps({ ...common, src: '/images/logo/logos.webp' }) const { props: { srcSet: light, ...rest } } = getImgProps({ ...common, src: '/images/logo/logos-2.webp' }) return ( <picture> <source srcSet={theme === 'dark'? dark : light} />
<img {...rest} width={0} height={0} sizes="100vw" style={{ width: "100%", height: "auto" }} /> </picture> ) } but it's not working corectly in first mount for a component and that's wrong i believe i'ts not ment to working like so if i need it to work then i should trigger toggle mode and hence will be working fine i guess in first mound of site it can't know what is theme or what but it's take much time and no one help me for bad to solve it
Christoph
Christoph17mo ago
I've never used unstable_getImgProps. So you'll have to show me the resulting HTML in the browser for me to be of any help. As an alternative: You can always go back and simply use two next/image elements and switch them with CSS.
ahmedqaram
ahmedqaramOP17mo ago
No description
ahmedqaram
ahmedqaramOP17mo ago
the resulting html "use two next/image elements and switch them with CSS." i see this approach do u have an example to do so
Christoph
Christoph17mo ago
Well, basically like that: #image-b { display: none; } @media (prefers-color-scheme: dark) { #image-a { display: none; } #image-b { display: inline; } } The difference between your first code and your second code is that in the first version you let HTML handle which image should be displayed. In the second version you let JavaScript make that determination. Hence, the first version is definitely perferable.
ahmedqaram
ahmedqaramOP17mo ago
it dosen't work either in global.css : .image-b { display: none; } @media (prefers-color-scheme: dark) { .image-a { display: none; } .image-b { display: inline; } } in my component : <> <Image src="/images/logo/logo.webp" alt='logo' width = {40} height={30} className=" image-b " />
<Image src="/images/logo/logo.webp" alt='logo' width = {40} height={30} className="image-a" /> </>
Christoph
Christoph17mo ago
Just the toggle doesn't work, right? How do you toggle the color scheme? In your browser's developer tools? You're currently using the same src. So when you toggle, you see the same image again.
ahmedqaram
ahmedqaramOP17mo ago
i'm using next/theme export function ThemeToggle() { const { setTheme, theme } = useTheme() return ( <Button variant="ghost" size="icon" onClick={() => setTheme(theme === "light" ? "dark" : "light")} > <Icons.sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" aria-hidden="true" /> <Icons.moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" aria-hidden="true" /> <span className="sr-only">Toggle theme</span> </Button> ) } and wrap my html with <Providers attribute="class" defaultTheme="system" enableSystem> here is provider component import { ThemeProvider as NextThemesProvider } from "next-themes" import { type ThemeProviderProps } from "next-themes/dist/types" import { TooltipProvider } from "@/components/ui/tooltip" export function Providers({ children, ...props }: ThemeProviderProps) { return ( <NextThemesProvider {...props}> <TooltipProvider>{children}</TooltipProvider> </NextThemesProvider> ) } and here is my tailwind config for that specific part darkMode: ["class", '[data-mode="dark"]'], you mean i should do this <Image src="/images/logo/logo.webp" alt='logo' width = {40} height={30} className=" image-b " />
<Image src="/images/logo/logo-2.webp" alt='logo' width = {40} height={30} className="image-a" /> yeah i did but i change it for something to test
ahmedqaram
ahmedqaramOP17mo ago
No description
Christoph
Christoph17mo ago
Oh, I see. Then you're not basing your color-scheme on the user's color-scheme. next-themes seems to store the current theme in local storage. That's why prefers-color-scheme doesn't work. Because prefers-color-scheme is based on the user's OS color scheme setting. So you can't use prefers-color-scheme and have to use useTheme like in your second version. So either like in your second version, or like this: const { setTheme, theme } = useTheme() return theme === 'dark' ? ( <Image src="/images/logo/logo.webp" alt='logo' width = {40} height={30} /> ) : ( <Image src="/images/logo/logo-2.webp" alt='logo' width = {40} height={30} /> )
ahmedqaram
ahmedqaramOP17mo ago
yeah that what i think about in first time prefers-color-scheme not working
Christoph
Christoph17mo ago
Yes, because prefers-color-scheme is based on the user's OS color scheme. next-themes' color scheme is based on its current value in local storage.
ahmedqaram
ahmedqaramOP17mo ago
where i can read about that also this approach same as srcSet={theme === 'dark'? dark : light} and in first rendring it can never tell if i'm in dark or light
Christoph
Christoph17mo ago
What exactly is unclear? You can check out next-themes source code. prefers-color-scheme is explained here: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
prefers-color-scheme - CSS: Cascading Style Sheets | MDN
The prefers-color-scheme CSS media feature is used to detect if a user has requested light or dark color themes. A user indicates their preference through an operating system setting (e.g. light or dark mode) or a user agent setting.
ahmedqaram
ahmedqaramOP17mo ago
Yes, because prefers-color-scheme is based on the user's OS color scheme. i didn't get it right give me ur twitter user i need to follow u
Christoph
Christoph17mo ago
Also: It seems like you're using Tailwind's dark variant but don't have next-themes configured appropriately. https://github.com/pacocoursey/next-themes#with-tailwind Oh, nevermind You did My bad I'm a read-only Twitter user haha Feel free to message me here
ahmedqaram
ahmedqaramOP17mo ago
i'm using an open source project in generall so i just tweak it up and just use what i need from deleting the rest
ahmedqaram
ahmedqaramOP17mo ago
GitHub
GitHub - sadmann7/skateshop: An open source e-commerce skateshop bu...
An open source e-commerce skateshop build with everything new in Next.js 13. - GitHub - sadmann7/skateshop: An open source e-commerce skateshop build with everything new in Next.js 13.
ahmedqaram
ahmedqaramOP17mo ago
thanx mate really apperciate that help
Christoph
Christoph17mo ago
No problem. As mentioned, feel free to reach out if you have other questions.
ahmedqaram
ahmedqaramOP17mo ago
thanx and for u to know what the last soluation i came up is : let src switch (resolvedTheme) { case 'light': src = '/images/logo/logo-2.webp' break case 'dark': src = '/images/logo/logo.webp' break default: src = theme === 'light'? '/images/logo/logo-2.webp' : '/images/logo/logo.webp' break } return (
<Image src={src} alt='logo' width = {40} height={30} /> ) remove defaultTheme="system" enableSystem from <Providers attribute="class" defaultTheme="system" enableSystem>
Want results from more Discord servers?
Add your server