DioxusLabs / DioxusLabs/dioxus

#[css_module] creates FOUC on page load

Open
#5,644 7 comments 3 reactions 0 assignees View on GitHub
bug
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.