How do I change a class on the html
tag from the server side?
#473
-
I want to set the class |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 2 replies
-
Hey @italodeandra, I don't know how to directly set classes on the html element, but you could maybe simulate what you're trying to accomplish by adding the styles directly on to every html element via a css file added in like in this discussion: #492 (comment) |
Beta Was this translation helpful? Give feedback.
-
This isn't currently supported as far as I can tell. The If this is something that could be supported I'm happy to make a PR for this (adding |
Beta Was this translation helpful? Give feedback.
-
One way is to exploit the islands design patter to get a bit of JS to add the dark class to the root element. For example, you could create a dark/light toggle button component in the islands directory: This way, the useEffect and onClick will run in the browser, where you have access to /** @jsx h */
import { h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { tw } from "@twind";
export default function LightDarkToggle(props: { class?: string }) {
// dark mode
const [darkMode, setDarkMode] = useState(true);
useEffect(() => {
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (
localStorage.theme === "dark" ||
(!("theme" in localStorage) &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
) {
document.documentElement.classList.add("dark");
setDarkMode(true);
} else {
document.documentElement.classList.remove("dark");
setDarkMode(false);
}
}, []);
return (
<button
title="Toggle Dark Mode"
class={tw`focus:outline-none`}
onClick={() => {
if (document.documentElement.classList.contains("dark")) {
document.documentElement.classList.remove("dark");
localStorage.theme = "light";
setDarkMode(false);
} else {
document.documentElement.classList.add("dark");
localStorage.theme = "dark";
setDarkMode(true);
}
}}
>
{darkMode ? <p {...props}>toggle light mode</p> : <p {...props}>toggle dark mode</p>}
</button>
);
} If all you want to do is set dark... (and never change it), you could probably create an island like this (note: I did not test this one.): /** @jsx h */
import { h } from "preact";
import { useEffect } from "preact/hooks";
import { tw } from "@twind";
export default function AddDark() {
useEffect(() => {
document.documentElement.classList.add("dark");
}, []);
return <div class={tw`w-0 h-0`} />;
} |
Beta Was this translation helpful? Give feedback.
-
@leo6liu unfortunately this will result in a flicker (from light -> dark) when the browser detects a user's dark mode preference after pageload. Ideally, |
Beta Was this translation helpful? Give feedback.
-
Update: I opened a PR for this here: #538. |
Beta Was this translation helpful? Give feedback.
-
Here is how I solved it, took the javascript code from tailwind's docs: index.jsx import { tw } from "@twind";
import { Head } from "$fresh/runtime.ts";
const Home = () => {
return (
<>
<Head>
<title>Home</title>
<script
dangerouslySetInnerHTML={{
__html: `
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
// Whenever the user explicitly chooses light mode
localStorage.theme = 'light'
// Whenever the user explicitly chooses dark mode
localStorage.theme = 'dark'
// Whenever the user explicitly chooses to respect the OS preference
localStorage.removeItem('theme')
`
}}
/>
</Head>
<header>header</header>
<main>main</main>
<footer>footer</footer>
</>
);
};
export default Home; You could of course refactor the whole Head component (or just the script tag) out into its own component, so you can reuse it on every route. |
Beta Was this translation helpful? Give feedback.
-
This will be solved by #1617 which will land in Fresh 1.4 |
Beta Was this translation helpful? Give feedback.
This will be solved by #1617 which will land in Fresh 1.4