dioxus_style
Scoped CSS/SCSS styling for Dioxus components - Write CSS or SCSS that's automatically scoped to your components, preventing style conflicts and maintaining clean, modular code.
✨ Features
- 🎨 SCSS/SASS Support - Variables, nesting, mixins, and all SCSS features (NEW in v0.3.0!)
- 🎯 Automatic CSS Scoping - Classes, IDs, and elements are automatically scoped
- 🏷️ Element Scoping - Element selectors (
div,span) use data attributes for isolation - 📦 File or Inline Styles - Load from
.css/.scssfiles or write inline - ⚡ Zero Runtime Overhead - All processing happens at compile time
- 🔥 Hot Reload Support - CSS/SCSS changes are tracked via
include_str! - 🎨 Multiple Macro Options - Choose the syntax that fits your style
- 🚀 Performance Optimized - Fast hashing (xxHash), efficient parsing, and minification in release builds
- 💾 Global Style Registry - Automatic deduplication and insertion order preservation
Quick Start
Add to your Cargo.toml:
[]
= "0.3.0" # SCSS enabled by default
# Or explicitly enable SCSS
= { = "0.3.0", = ["scss"] }
# Or use without SCSS (smaller dependencies)
= { = "0.3.0", = false }
🆕 SCSS Support (v0.3.0+)
Write modern, maintainable styles with SCSS! All compilation happens at build time.
SCSS Example
button.scss:
$primary-color: #3498db;
$padding: 10px 20px;
.btn {
background: $primary-color;
color: white;
padding: $padding;
border-radius: 5px;
&:hover {
background: darken($primary-color, 10%);
transform: scale(1.05);
}
&:active {
transform: scale(0.98);
}
}
Component:
use *;
use with_css;
Inline SCSS
use scoped_style;
Usage Examples
1. Attribute Macro with Auto-Injection (Recommended)
The simplest way - styles are automatically injected:
use *;
use with_css;
// or "button.scss"
button.css (or button.scss):
}
}
}
2. Manual Style Management
For more control over when styles are injected:
use *;
use ;
3. Inline CSS/SCSS
No external file needed:
use *;
use css;
4. Function-like Component Macro
Alternative syntax for defining styled components:
use *;
use component_with_css;
component_with_css!
How It Works
Compile-Time Processing
let css = scoped_style!;
// 1. Compiles SCSS to CSS (if .scss file)
// 2. Scopes all selectors
// 3. Generates: "sc_a1b2c3d4"
Input SCSS:
$primary: red;
.btn {
color: $primary;
&:hover {
color: blue;
}
}
div {
margin: 10px;
}
#header {
font-size: 24px;
}
After SCSS Compilation:
}
}
}
}
After Scoping:
}
}
}
}
Usage in Components
// Use the scoped class name and data-scope attribute
button
// Renders: <button data-scope="sc_a1b2c3d4" class="sc_a1b2c3d4_btn">Click</button>
SCSS Features Supported
All standard SCSS features are supported:
- ✅ Variables:
$primary: #3498db; - ✅ Nesting: Parent-child selector relationships
- ✅ Parent Selector:
&for modifiers and pseudo-classes - ✅ Mixins:
@mixinand@include - ✅ Functions:
darken(),lighten(),rgba(), etc. - ✅ Imports:
@importand@use - ✅ Extends:
@extend - ✅ Operators:
+,-,*,/,% - ✅ Interpolation:
#{$variable} - ✅ Control Directives:
@if,@for,@each,@while - ✅ Maps and Lists: Complex data structures
- ✅ Built-in Functions: All SCSS built-in functions
SCSS Examples
Variables and Operations:
$base-spacing: 1rem;
.container {
padding: $base-spacing * 2;
margin: $base-spacing / 2;
}
Nesting:
.card {
background: white;
.title {
font-size: 1.5rem;
}
.content {
color: #666;
}
}
Mixins:
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.container {
@include flex-center;
}
Parent Selector:
.button {
background: blue;
&:hover {
background: darkblue;
}
&--large {
padding: 1rem 2rem;
}
}
Scoping Behavior
What Gets Scoped
| Selector Type | Input | Output | Usage |
|---|---|---|---|
| Class | .btn |
.sc_xxx_btn |
class: "{css}_btn" |
| ID | #header |
#sc_xxx_header |
id: "{css}_header" |
| Element | div |
div[data-scope="sc_xxx"] |
"data-scope": "{css}" |
| Pseudo-class | .btn:hover |
.sc_xxx_btn:hover |
(automatic) |
| Complex | .card > .title |
.sc_xxx_card > .sc_xxx_title |
(automatic) |
Element Scoping
Elements are scoped using data-scope attributes:
// SCSS
$spacing: 20px;
div
span.highlight
// Component
rsx!
Style Injection Strategies
Auto-Injection (Recommended for Simple Cases)
Manual Injection (Recommended for Root Component)
Advanced Features
CSS File Path Resolution
The library searches for CSS/SCSS files in multiple locations:
scoped_style!
// Searches:
// 1. ./button.scss
// 2. ../button.scss
// 3. ../../button.scss
// 4. src/button.scss
Automatic File Type Detection
// ✅ SCSS file - automatically compiled
// ✅ CSS file - scoped only
Complex Selectors
All complex selectors are fully supported in both CSS and SCSS:
// SCSS with nesting
.parent {
> .child {
color: blue;
}
}
// Compiles to: .sc_xxx_parent > .sc_xxx_child { color: blue; }
// Adjacent sibling
.card + .card {
margin-top: 20px;
}
// Output: .sc_xxx_card + .sc_xxx_card { margin-top: 20px; }
// Mixed selectors with SCSS
div.container {
> span#label {
font-weight: bold;
}
}
// Output: div[data-scope="sc_xxx"].sc_xxx_container > span[data-scope="sc_xxx"]#sc_xxx_label
Minification
In release builds, CSS is automatically minified:
// Debug: Preserves formatting for readability
// Release: Removes whitespace and comments for smaller bundles
Hash Generation
Uses xxHash (XXH3) for fast, collision-resistant hashing:
// Hash includes file path + content for uniqueness
// Format: "sc_" + base62(hash)
// Example: "sc_3xK9mP2"
Performance Characteristics
- Compile-time SCSS compilation: Zero runtime SCSS parsing
- Compile-time CSS scoping: Zero runtime CSS transformation
- O(1) style lookups: HashMap-based registry
- Deduplication: Identical styles registered only once
- Fast hashing: xxHash3 is one of the fastest non-cryptographic hashes
- Efficient scoping: Single-pass CSS transformation with optimized state machine
Architecture
┌───────────────────────────────────┐
│ Your Component (compile time) │
│ scoped_style!("button.scss") │
└──────────────┬────────────────────┘
↓
┌───────────────────────────────────┐
│ SCSS Compiler (if .scss) │
│ • Compile SCSS to CSS │
│ • Variables, nesting, mixins │
│ • Functions and operations │
└──────────────┬────────────────────┘
↓
┌───────────────────────────────────┐
│ Procedural Macro │
│ • Read CSS/SCSS file │
│ • Generate hash (xxHash3) │
│ • Scope selectors: │
│ - .btn → .sc_xxx_btn │
│ - #id → #sc_xxx_id │
│ - div → div[data-scope="..."] │
│ • Minify (release builds) │
└──────────────┬────────────────────┘
↓
┌───────────────────────────────────┐
│ Runtime Registry (lazy_static) │
│ • Store scoped CSS │
│ • Deduplicate by hash │
│ • Preserve insertion order │
└──────────────┬────────────────────┘
↓
┌───────────────────────────────────┐
│ inject_styles() → <style> tag │
│ • Inject into DOM │
│ • All styles in single tag │
└───────────────────────────────────┘
Examples
Complete App Structure with SCSS
use *;
use ;
header.scss:
$header-bg: #2c3e50;
.header {
background: $header-bg;
padding: 1rem;
h1 {
color: white;
margin: 0;
}
}
Scoping Rules Summary
✅ Automatically Scoped
- Classes:
.button→.sc_xxx_button - IDs:
#header→#sc_xxx_header - Elements:
div→div[data-scope="sc_xxx"](requiresdata-scopeattribute) - Pseudo-classes:
:hover,:focus,:active, etc. - Pseudo-elements:
::before,::after - Attribute selectors:
[type="text"](passed through, element gets scoped) - Complex selectors: All combinators (
>,+,~, space)
❌ Not Scoped (Global)
- Universal selector:
* - :root: CSS variables at root level
- @keyframes: Animation definitions (use unique names)
- @media, @supports: Query blocks (contents are scoped)
Migration Guides
From v0.2.0 to v0.3.0 (SCSS Support)
Good News: This is a NON-BREAKING release! All v0.2.0 code works without changes.
To Use SCSS:
- Rename
.cssfiles to.scss(optional) - Start using SCSS features
- Or keep using plain CSS - both work!
Cargo.toml:
# Before (v0.2.0)
[]
= "0.2.0"
# After (v0.3.0) - SCSS enabled by default
[]
= "0.3.0"
# Or without SCSS
= { = "0.3.0", = false }
From v0.1.0 to v0.2.0+ (Element Scoping)
Breaking Changes:
-
Element selectors now require
data-scope:// OLD (v0.1.0) rsx! // NEW (v0.2.0+) rsx! -
Class selector output format changed:
- Old:
.sc_xxx.button - New:
.sc_xxx_button
- Old:
-
ID selector output format changed:
- Old:
#sc_xxx.header - New:
#sc_xxx_header
- Old:
Troubleshooting
SCSS compilation error
error: SCSS compilation error in 'button.scss': Undefined variable
Solution: Check that all SCSS variables are defined:
// ❌ Wrong
.button { color: $undefined; }
// ✅ Correct
$primary: blue;
.button { color: $primary; }
SCSS feature not available
error: SCSS support is not enabled
Solution: Enable SCSS in Cargo.toml:
[]
= { = "0.3.0", = ["scss"] }
CSS/SCSS file not found
// ❌ Error: Failed to find file 'button.scss'
scoped_style!
// ✅ Solution: Use relative path from Cargo.toml location
scoped_style!
Styles not appearing
// ❌ Forgot to inject styles
// ✅ Add inject_styles() to root component
Element styles not working
// ❌ Missing data-scope attribute
div
// ✅ Add data-scope for element scoping
div
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. See CONTRIBUTING.md for guidelines.
License
This project is licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Credits
Built for the Dioxus framework.
SCSS compilation powered by grass.
Changelog
See CHANGELOG.md for detailed version history.
Made with ❤️ for the Dioxus community