#css-class #css #dioxus #wasm-binary #wasm #gui #jss

css-in-rs

用于管理Rust中组件级CSS的库

6个版本

0.2.0 2024年1月23日
0.1.4 2024年1月19日

#17 in #css-class

Download history 12/week @ 2024-03-30 6/week @ 2024-04-06

每月下载 56

MIT 协议

25KB
259

css-in-rs

用于在Rust (wasm) 中嵌入动态CSS的库;受 cssinjs/jss 启发

此crate旨在框架无关。目前它为 Dioxus 提供集成,默认情况下是禁用的。

用例

此crate允许开发可重用的网页组件,这些组件包含自己的样式。由于Rust的dead-code-analysis,只有实际使用的样式会被包含在最终的wasm二进制文件中。

功能

  • 一个procmacro make_styles!,可以直接在Rust中编写CSS
  • 一个运行时,可以按需注入样式。如果未使用样式,则它们不会被包含在最终的二进制文件中
  • 样式只会挂载一次,即使多次请求也是如此
  • 动态创建的类名以避免冲突。您可以选择像 active 这样的通用名称,而不用担心多个组件的问题
  • 编译时检查:如果您的样式中定义的类名未使用,Rust会警告您。如果它们不存在,您将得到一个错误

基本思想

您可以使用 make_styles! procmacro将CSS代码嵌入您的选择中。它将为使用的CSS类的最终运行时名称生成一个新的Rust struct。对于您的样式中的每个CSS类,结构中将有一个 classname: String 成员。有关 make_styles! 的详细信息,请参阅文档。

以这种方式生成的样式可以挂载。在第一次挂载时,类名将在运行时生成以避免冲突,并返回由procmacro创建的结构体。因此,您可以使用结构体访问创建的类名。由于结构体的类型是在编译时生成的,因此如果使用未定义的CSS类,编译器将报错,并警告您有关未使用的类。

样式只挂载一次。您可以尝试多次执行此操作,但它将不会产生任何效果。您将获得第一次创建的类名结构的引用。因此,您可以在许多组件中重用创建的样式,而无需担心过多地挂载它们。

示例(Dioxus)

#![allow(non_snake_case)]

use css_in_rs::{Classes, EmptyTheme, make_styles, use_style_provider_quickstart};
use dioxus::prelude::*;

// Will create a new struct `MyClasses` with three members:
//  `red_text`, `primary` and `disabled`
make_styles! {
    (_theme: EmptyTheme) -> MyClasses {
        red_text {          // defines a new css class: `red_text`
            color: "red",
            margin: "5px",
        },
        "button" {          // does not define any new css classes
            margin: "5px",
            padding: "5px",
            width: "10em",
        },
        "button.primary" {  // defines a new css class: `primary`
            border: "2px solid red",
        },
        "button.disabled" { // Shows a rust warning: "field never read"
            disabled: true,
        },
    }
}

fn Demo(cx: Scope) -> Element {
    let classes: &MyClasses = MyClasses::use_style(cx);

    render! {
        div {
            class: &classes.red_text as &str,
            "This text is supposed to be red.",
        }
        button {
            class: &classes.primary as &str,
            "Click me",
        }
    }
}

fn App(cx: Scope) -> Element {
    use_style_provider_quickstart(cx, || EmptyTheme);

    cx.render(rsx! {
        Demo {}
    })
}

fn main() {
    // launch the web app
    dioxus_web::launch(App);
}

依赖项

~8–10MB
~200K SLoC