DioxusLabs / DioxusLabs/dioxus
#[css_module] creates FOUC on page load
- Dominant language
- Rust
- Stars
- 39.1k
- Forks
- 1.9k
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 4
Description
**Problem**
When using `#[css_module]` for styling reloading the app using `Strg + r` flashes the screen with unstyled html where after a second or so the styles get loaded. This also happens for when you use an ``-tag to redirect the user.
**Steps To Reproduce**
Steps to reproduce the behavior:
1. create a blank dioxus project using `dx new`
2. Use `#[css_module]` for styling all components
3. Start the app and reload the page.
This is the modified Bare-Bones example, created using `dx new test`
```rust
use dioxus::prelude::*;
#[derive(Debug, Clone, Routable, PartialEq)]
#[rustfmt::skip]
enum Route {
#[layout(Navbar)]
#[route("/")]
Home {},
#[route("/blog/:id")]
Blog { id: i32 },
}
#[css_module("/assets/main.css")]
pub struct Styles;
const FAVICON: Asset = asset!("/assets/favicon.ico");
//const MAIN_CSS: Asset = asset!("/assets/main.css");
const HEADER_SVG: Asset = asset!("/assets/header.svg");
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
rsx! {
document::Link { rel: "icon", href: FAVICON }
//document::Link { rel: "stylesheet", href: MAIN_CSS }
Router:: {}
}
}
#[component]
pub fn Hero() -> Element {
rsx! {
div {
class: Styles::hero,
img { src: HEADER_SVG, class: Styles::header }
div { class: Styles::links,
a { href: "https://dioxuslabs.com/learn/0.7/", "📚 Learn Dioxus" }
a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" }
a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" }
a { href: "https://github.com/DioxusLabs/sdk", "⚙️ Dioxus Development Kit" }
a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" }
a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" }
}
}
}
}
/// Home page
#[component]
fn Home() -> Element {
rsx! {
Hero {}
Echo {}
}
}
/// Blog page
#[component]
pub fn Blog(id: i32) -> Element {
rsx! {
div {
class: Styles::blog,
// Content
h1 { "This is blog #{id}!" }
p { "In blog #{id}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components." }
// Navigation links
Link {
to: Route::Blog { id: id - 1 },
"Previous"
}
span { " <---> " }
Link {
to: Route::Blog { id: id + 1 },
"Next"
}
}
}
}
/// Shared navbar component.
#[component]
fn Navbar() -> Element {
rsx! {
div {
class: Styles::navbar,
Link {
to: Route::Home {},
"Home"
}
Link {
to: Route::Blog { id: 1 },
"Blog"
}
}
Outlet:: {}
}
}
/// Echo component that demonstrates fullstack server functions.
#[component]
fn Echo() -> Element {
let mut response = use_signal(|| String::new());
rsx! {
div {
class: Styles::echo,
h4 { "ServerFn Echo" }
input {
placeholder: "Type here to echo...",
oninput: move |event| async move {
let data = echo_server(event.value()).await.unwrap();
response.set(data);
},
}
if !response().is_empty() {
p {
"Server echoed: "
i { "{response}" }
}
}
}
}
}
/// Echo the user input on the server.
#[post("/api/echo")]
async fn echo_server(input: String) -> Result {
Ok(input)
}
```
**Expected behavior**
The App should not flash with unstyled html but rather be already styled.
**Example**
https://github.com/user-attachments/assets/a15ceee4-e341-4527-8afb-110f081723df
**Environment:**
- Dioxus version: v0.7.9
- Rust version: rustc 1.95.0 (59807616e 2026-04-14)
- OS info: Archlinux
- App platform: Web (tested using Firefox and Chrome)
**Other interesting things**
Investigating this problem I found that making the `ASSET`, created by the `#[css_module]`, public and adding that to the dom, not relying on the `OnceCell` trick in deref fixes this issue entirely. My working theory is that when the user requests the app, it first delivers the html, then sees it needs to load the wasm (this might take some time) and only then the styles mount the css and therefore the css is only loaded then. That way even if the client has the css cached it will always wait on the wasm to mount that css into the dom head.
I found issue #3592 but ssg doesn't seem to fix this. I might have not done it correctly though.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the provided `dx new` reproduction and inspect the `#[css_module]` asset generation, especially the `OnceCell` dereference path and the public `ASSET` workaround described in the issue. Compare reloads and anchor navigation in the web target; done means the page is styled from its initial render without a flash of unstyled HTML.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, rust, wasm
- Domain
- frontend, performance, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100