DEV Community

tengxgfyrz67s
tengxgfyrz67s

Posted on

CSS-Styling-Deep-Dive

CSS Styling Deep Dive

Project Code:https://github.com/euv-dev/euv

Styling is a critical part of any frontend application, and euv provides a powerful set of tools for applying CSS to your components. This article takes an in-depth look at the class! macro, CSS variables, the var! macro, and how to create sophisticated styling patterns in your euv applications.

The class! Macro

The class! macro is euv's primary mechanism for applying CSS classes to elements. It goes far beyond simple class name strings — it supports pseudo-classes, media queries, conditional classes, and animations.

Basic CSS Classes

At its simplest, the class! macro generates a CSS class string that you can apply to elements:

use euv::*;

fn app() -> VirtualNode {
    html! {
        div {
            class: class!("container"),
            p { class: class!("text-large"), "Hello, World!" }
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

The class! macro takes one or more class names and returns a string that can be used as the class attribute on any element.

Multiple Classes

You can combine multiple classes by passing multiple arguments:

html! {
    div {
        class: class!("container", "shadow", "rounded"),
        "Multiple classes applied"
    }
}
Enter fullscreen mode Exit fullscreen mode

Conditional Classes

One of the most powerful features of the class! macro is its support for conditional classes. You can use expressions to determine which classes are applied:

use euv::*;

fn app() -> VirtualNode {
    let count: Signal<i32> = use_signal(|| 0);

    html! {
        div {
            class: class!(
                "base-style",
                if count.get() > 0 { "positive" } else { "non-positive" }
            ),
            "Count: " {count}
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Here, the class list dynamically changes based on the value of the count signal. When the signal updates, euv automatically re-evaluates the class expression.

Combining class! with Reactive Signals

The class! macro integrates seamlessly with euv's reactive system. You can embed signals directly in class expressions:

use euv::*;

fn app() -> VirtualNode {
    let is_active: Signal<bool> = use_signal(|| true);

    html! {
        div {
            class: class!(
                "panel",
                if is_active.get() { "active" } else { "inactive" }
            ),
            "Panel Content"
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Pseudo-classes and Nested Selectors

The class! macro supports CSS pseudo-classes and nested selector patterns:

let hover_style = class!(
    "button",
    ":hover { background-color: blue; }",
    ":active { background-color: darkblue; }"
);
Enter fullscreen mode Exit fullscreen mode

This generates CSS rules for hover and active states, which are scoped to elements with the button class.

Media Queries

Responsive design is straightforward with the class! macro's media query support:

let responsive_style = class!(
    "container",
    "@media (max-width: 768px) { flex-direction: column; }",
    "@media (min-width: 1200px) { max-width: 1140px; }"
);
Enter fullscreen mode Exit fullscreen mode

This applies different CSS rules based on the viewport width, enabling fully responsive layouts.

Animations with class!

The class! macro supports CSS animations through keyframe definitions:

let animated_style = class!(
    "fade-in",
    "@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }",
    "animation: fadeIn 0.3s ease-in;"
);
Enter fullscreen mode Exit fullscreen mode

You can combine this with euv's built-in animation and transition features for rich interactive experiences.

CSS Variables and the var! Macro

euv provides first-class support for CSS custom properties (variables) through the css-vars! and var! macros.

Defining CSS Variables

Use the css-vars! macro to define CSS custom properties:

use euv::*;

fn app() -> VirtualNode {
    css-vars!(
        "--primary-color", "#3498db",
        "--secondary-color", "#2ecc71",
        "--font-size-base", "16px"
    );

    html! {
        div {
            h1 { "Styled with CSS Variables" }
            p { "This text uses CSS custom properties." }
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Using the var! Macro

Reference CSS variables in your styles using the var! macro:

use euv::*;

fn app() -> VirtualNode {
    html! {
        div {
            style: "color: var(--primary-color); font-size: var(--font-size-base);",
            "Styled text"
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Dynamic CSS Variables

CSS variables can be made reactive by combining them with signals:

use euv::*;

fn app() -> VirtualNode {
    let hue: Signal<i32> = use_signal(|| 200);

    css-vars!(
        "--dynamic-color", format!("hsl({}, 70%, 60%)", hue.get())
    );

    html! {
        div {
            style: "background-color: var(--dynamic-color);",
            "Dynamic color background"
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Styling Patterns

Pattern 1: Theme Variables

Define a set of CSS variables for your application's theme:

fn apply_theme() {
    css-vars!(
        "--color-bg", "#ffffff",
        "--color-text", "#333333",
        "--color-primary", "#3498db",
        "--color-success", "#2ecc71",
        "--color-danger", "#e74c3c",
        "--spacing-sm", "8px",
        "--spacing-md", "16px",
        "--spacing-lg", "24px",
        "--border-radius", "4px"
    );
}
Enter fullscreen mode Exit fullscreen mode

Pattern 2: Conditional Styling Based on State

Combine signals with the class! macro for state-driven styling:

use euv::*;

fn todo_item(text: &str, done: bool) -> VirtualNode {
    html! {
        li {
            class: class!(
                "todo-item",
                if done { "completed" } else { "pending" }
            ),
            text
        }
    }
}

fn app() -> VirtualNode {
    html! {
        ul {
            {todo_item("Learn euv", true)}
            {todo_item("Build an app", false)}
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Pattern 3: Responsive Grid Layout

Use media queries in the class! macro for responsive layouts:

fn app() -> VirtualNode {
    html! {
        div {
            class: class!(
                "grid",
                "@media (min-width: 768px) { grid-template-columns: repeat(2, 1fr); }",
                "@media (min-width: 1024px) { grid-template-columns: repeat(3, 1fr); }"
            ),
            div { class: class!("grid-item"), "Item 1" }
            div { class: class!("grid-item"), "Item 2" }
            div { class: class!("grid-item"), "Item 3" }
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Styling and the html! Macro

The html! macro supports inline styles through the style attribute:

html! {
    div {
        style: "color: red; font-size: 14px;",
        "Inline styled text"
    }
}
Enter fullscreen mode Exit fullscreen mode

However, for maintainability, prefer using the class! macro for most styling needs. Reserve inline styles for truly dynamic values that can't be expressed in CSS:

use euv::*;

fn app() -> VirtualNode {
    let progress: Signal<f64> = use_signal(|| 0.5);

    html! {
        div {
            class: class!("progress-bar"),
            div {
                class: class!("progress-fill"),
                style: format!("width: {}%;", progress.get() * 100.0),
                ""
            }
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Transitions

CSS transitions work naturally with euv's reactive system. Define the transition in your CSS:

let transition_style = class!(
    "panel",
    "transition: all 0.3s ease;"
);
Enter fullscreen mode Exit fullscreen mode

When the state changes and the class updates, the browser automatically animates the transition:

use euv::*;

fn app() -> VirtualNode {
    let expanded: Signal<bool> = use_signal(|| false);

    html! {
        div {
            class: class!(
                "panel",
                "transition: all 0.3s ease;",
                if expanded.get() { "expanded" } else { "collapsed" }
            ),
            button {
                onclick: move || { expanded.set(!expanded.get()); }
                "Toggle"
            }
        }
    }
}

mount("#app", app);
Enter fullscreen mode Exit fullscreen mode

Summary

euv provides a comprehensive set of styling tools through the class! macro, css-vars! macro, and var! macro. The class! macro supports conditional classes, pseudo-classes, media queries, and animations. CSS variables enable theming and dynamic styling. By combining these tools with euv's reactive signals, you can create sophisticated, responsive, and maintainable styles for your applications.


Project Code:https://github.com/euv-dev/euv

Top comments (0)