dioxus_style 0.5.3

Scoped CSS/SCSS styling system for Dioxus components with compile-time processing and SCSS support
Documentation

🎨 Dioxus Style

The Ultimate Styling Solution for Dioxus
Type-Safe. Compile-Time. SCSS-Powered.

Crates.io Documentation License


🧐 Why Dioxus Style?

Writing CSS in Rust often feels like a compromise. You either have to use loose strings (class: "btn primary") which hides typos until runtime, or use heavy runtime libraries that slow down your app.

Dioxus Style changes the game:

  1. 🛡️ Zero Runtime Cost (Almost): Your SCSS is compiled to CSS during the build. The browser just loads a static CSS string.
  2. ✅ Type Safety: Your CSS classes become Rust Constants. If you type style::buttn instead of style::button, your code won't compile. No more UI bugs because of a typo!
  3. 💪 SCSS Built-In: Use variables, nesting, and mixins right out of the box. No external build tools needed.
  4. ⚡ Hot Reload Friendly: Change your .scss file, and the app updates instantly.

📦 Installation

Add this to your Cargo.toml.

[dependencies]

dioxus_style = "0.5.3"

Note: SCSS support is enabled by default. If you only want CSS, you can disable default features.


🚀 Step-by-Step Guide

1. Create your SCSS file

Create a standard SCSS file anywhere in your project (e.g., src/button.scss).

// src/button.scss
$primary: #6200ea;

.container {
    display: flex;
    gap: 10px;
}

.btn {
    background-color: $primary;
    color: white;
    padding: 8px 16px;
    border-radius: 4px;

    &:hover {
        opacity: 0.9;
    }
    
    // Defines a modifier class
    &.outlined {
        background: transparent;
        border: 2px solid $primary;
        color: $primary;
    }
}

2. Connect it to your Component

Use the #[with_css] macro to load the file. This does two things:

  1. Compiles the SCSS to Scoped CSS.
  2. Creates a Rust module (named style in the example below) containing your classes.
use dioxus::prelude::*;
use dioxus_style::with_css;

// usage: #[with_css(MODULE_NAME, "PATH_TO_FILE")]
#[with_css(style, "src/button.scss")]
fn ButtonComponent() -> Element {
    // ...
}

3. Use Type-Safe Classes

Now, instead of typing strings, you use the module you just created!

#[with_css(style, "src/button.scss")]
fn ButtonComponent() -> Element {
    rsx! {
        div {
            // style::container is a constant derived from your SCSS file!
            class: style::container, 

            button {
                class: style::btn,
                "Primary Button"
            }

            button {
                // ✨ MAGIC: Combine classes using the '+' operator
                class: style::btn + style::outlined,
                "Outlined Button"
            }
        }
    }
}

🧠 Deep Dive: How it works

The Magic of style::btn

When you write .btn { ... } in your SCSS, the macro generates Rust code that looks like this:

// Generated automatically by the macro
mod style {
    pub const btn: CssClass = CssClass::new("sc_X7z9_btn");
    pub const outlined: CssClass = CssClass::new("sc_X7z9_outlined");
    // ...
}

This means:

  • Autocomplete: Your IDE knows exactly what classes exist.
  • Refactoring: Rename a class in SCSS? The compiler tells you where you need to update your Rust code.

Automatic Scoping

To prevent styles from leaking (e.g., a .container in one component affecting another), dioxus_style generates unique hashes.

  • Input: .btn
  • Output: .sc_a1b2_btn

You never have to worry about class name collisions again.


🛠️ Advanced Usage

Multiple Stylesheets

If you have a complex component that needs styles from multiple files (e.g., a shared theme and specific component styles), use component_with_css!.

use dioxus_style::component_with_css;

component_with_css! {
    // Import multiple files into different namespaces
    layout: "src/styles/layout.scss",
    theme: "src/styles/theme.scss",

    fn Dashboard() -> Element {
        rsx! {
            div {
                class: layout::grid, // From layout.scss
                
                div {
                    // Combine classes from different files!
                    class: layout::card + theme::dark_mode,
                    "Multi-styled Component"
                }
            }
        }
    }
}

Manual/Inline Scoping

For one-off styles where you don't want a separate file.

use dioxus_style::scoped_style;

fn InlineExample() -> Element {
    // Compiles SCSS string immediately
    scoped_style!(css, "
        .text { color: red; font-weight: bold; }
    ");

    rsx! {
        p { class: css::text, "I am styled inline!" }
    }
}

❓ Frequently Asked Questions

Q: Does this work with Tailwind?
A: Yes, you can use both. dioxus_style is great for custom complex components where Tailwind strings get too long, or for utilizing SCSS features.

Q: Where do I put my SCSS files?
A: Anywhere! Paths are relative to your Cargo.toml. Common patterns are src/components/MyComponent.scss or a dedicated assets/ folder.

Q: I don't see my styles?
A: Make sure you have style { dangerous_inner_html: "{inject_styles()}" } in your root App component if you are NOT using the #[with_css] macro on the root. (Note: #[with_css] handles injection for you automatically in the component usage, but global styles usually need a root injector).


📜 License

This project is dual-licensed under MIT and Apache 2.0.