8 releases

new 0.2.0 Jan 14, 2025
0.1.10 Sep 21, 2024

#169 in WebAssembly

MIT license

34KB
571 lines

wasm-css

Ergonomic WASM-CSS framework

Description

Provides a simple API to implement dynamic CSS styling in WASM environments.

Requirements

  • Rust

  • WASM Pack for testing: cargo install wasm-pack

Installation

cargo add wasm-css

Usage

You can create a Style via Style::new, style! or named_style!. Each Style, unless given a identity will generate a UUID using the Crypto module, and use that as the <style> elements ID as well as the definitions class name.

When a Style is mutated; it will update the corresponding DOM <style> node.

If a Style is bound to a class name, or a ID, you can use Style::identity to get the identity to apply to the HTML node through the class or ID attribute.

Example: Basic Usage

use wasm_css::{error::WasmCssError, extend_style_from_css, style};

fn main() -> Result<(), WasmCssError> {
    // Construct a new `Style`
    let mut style = style!(
        "
            font-size: {}rem;
            
            &:hover {{
                cursor: pointer;
                text-decoration: underline;
            }}

            @media (max-width: 800px) {{
                font-size: {}rem;
            }}
        ",
        1,
        0.75
    )?;

    // "z2a55dca-3efe-4061-b1e9-ae7dffb567b8"
    style.identity();

    // Removing current keys
    style
        .remove_keys(vec!["font-size", "@media (max-width: 800px)"])
        .unwrap();

    // Extend the `Style` with new css
    style.extend_from_css("color: blue;").unwrap();
    extend_style_from_css!(&mut style, "color: {};", "blue").unwrap();

    // Extend the `Style` with another `Style`
    let template_style = style!("gap: 0.rem; display: flex; flex-direction: column;").unwrap();
    style.extend_from_style(&template_style).unwrap();

    // Remove the `Style` element
    style.delete().unwrap();

    Ok(())
}

Example: Global styling

Often, we want to define styles to use on multiple elements, or we want to target all elements by a global identifier, to accomplish this, we can provide a css_name to Style::new or use the named_style! macro.

use wasm_css::{error::WasmCssError, named_style};

fn main() -> Result<(), WasmCssError> {
    // Construct a new `Style` with a css ID
    let style = named_style!("#myID", "font-size: {}px;", 16).unwrap();

    // "myID"
    style.identity();

    // Construct a new `Style` with a class name
    let style = named_style!(".myClass", "font-size: {}px;", 16).unwrap();

    // "myClass"
    style.identity();

    // Construct a new `Style` with a global target
    let style = named_style!("label", "font-size: {}px;", 16).unwrap();

    // "label"
    style.identity();

    Ok(())
}

Please see Full crate documentation can be found here at docs.rs for all available functionality.

Errors

Errors can happen constructing and updating Style if:

  • No Head Object

  • No Window Object

  • No Document Object

  • No Crypto Object when trying to generate class names automatically

Roadmap

Planned improvements:

  • Support nested effects, I.E.: @media (max-width: 800px) { &:hover { } }

Potential improvements:

  • Change to proc-macro CSS parsing for interpreter validation and defined keys/values

Contributing

Open to contributions, please just create a PR/issue or reach out to me to discuss what you would like to add/change.

Testing can be done by:

  • wasm-pack test --chrome

  • Go to the listed URI to run the test suite

License

MIT License

Copyright (c) 2024 Robert Lopez

See LICENSE.md

Dependencies

~7.5–10MB
~182K SLoC