使用 class! 宏进行样式设计
class! 宏简介
class! 宏是 euv 在 Rust 代码中直接编写 CSS 的解决方案。无需在 .rs 和 .css 文件之间切换,你可以在 class! 宏中使用类似 CSS 的语法定义样式。该宏会将你的样式编译为 CSS 并在运行时注入到页面中,提供作用域样式而无需单独的构建步骤。
基本 CSS 类定义
class! 宏让你使用熟悉的语法定义 CSS 类。每个类用一个名称和一组属性-值对来声明:
class! {
pub c_card {
display: "flex";
padding: "10px";
}
}
在这个示例中,c_card 是一个公开 CSS 类,设置 display 为 flex,padding 为 10px。pub 关键字使类可以在组件中访问。
多个类
你可以在一个 class! 块中定义多个类:
class! {
pub c_card {
display: "flex";
padding: "10px";
}
pub c_header {
font-size: "24px";
font-weight: "bold";
}
pub c_body {
font-size: "14px";
color: "#666";
}
}
伪类和嵌套选择器
class! 宏使用嵌套块来支持伪类。伪类以 : 为前缀,定义在所属的类内部:
class! {
pub c_card_hover {
":hover" {
background: "#4338ca";
}
}
}
这会为 .c_card_hover:hover 生成一个 CSS 规则,背景色为 #4338ca。你可以使用任何 CSS 伪类,如 :hover、:focus、:active、:first-child、:last-child 等。
多个伪类
一个类可以有多个伪类:
class! {
pub c_button {
padding: "8px 16px";
border: "none";
cursor: "pointer";
":hover" {
background: "#4338ca";
}
":active" {
background: "#3730a3";
}
":focus" {
outline: "2px solid #818cf8";
}
}
}
在组件中使用类
要在组件中使用 class! 定义的类,在 html! 宏中引用它:
class! {
pub c_card {
display: "flex";
padding: "10px";
}
}
fn app() -> VirtualNode {
html! {
div {
class: c_card
h3 { "Card Title" }
p { "Card content goes here." }
}
}
}
class: c_card 属性将 c_card CSS 类应用到 div 元素上。
内置动画
euv 提供了一组预定义的 CSS 关键帧动画,可以直接使用:
| 动画 | 描述 |
|---|---|
euv-spin | 将元素旋转 360 度 |
euv-fade-in | 将元素从透明渐变到不透明 |
euv-scale-in | 将元素从小缩放到正常大小 |
euv-pulse | 创建脉冲透明度效果 |
euv-slide-up | 将元素从下方滑入视图 |
euv-slide-left | 将元素从左侧滑入视图 |
euv-fade-in-up | 结合淡入和上滑效果 |
euv-progress | 创建进度条动画 |
euv-shimmer | 创建闪烁加载效果 |
要使用这些动画,只需将其作为类应用:
html! {
div {
class: euv-fade-in
p { "This element fades in when it appears." }
}
}
自定义关键帧动画
如果内置动画不满足需求,你可以使用 Css::inject_css() 创建自定义关键帧动画:
// 注入自定义 CSS 关键帧
Css::inject_css(r#"
@keyframes my-custom-animation {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.my-custom-class {
animation: my-custom-animation 0.5s ease-out;
}
"#);
这让你可以完全控制动画效果,同时保持 CSS-in-Rust 的方式。
CSS 过渡
除了关键帧动画,你还可以使用 CSS 过渡来实现平滑的属性变化。在 class! 块中定义过渡:
class! {
pub c_transition_box {
background: "#f0f0f0";
transition: "background 0.3s ease";
":hover" {
background: "#4338ca";
}
}
}
这在悬停时创建一个平滑的颜色过渡效果。
完整样式示例
下面是一个完整的示例,展示了各种样式特性:
use euv::*;
class! {
pub c_app_container {
display: "flex";
flex-direction: "column";
align-items: "center";
padding: "20px";
}
pub c_title {
font-size: "28px";
font-weight: "bold";
margin-bottom: "16px";
}
pub c_card {
display: "flex";
flex-direction: "column";
padding: "16px";
border: "1px solid #e5e7eb";
border-radius: "8px";
max-width: "400px";
transition: "box-shadow 0.2s ease";
":hover" {
box-shadow: "0 4px 12px rgba(0, 0, 0, 0.1)";
}
}
pub c_button {
padding: "10px 20px";
background: "#4338ca";
color: "#ffffff";
border: "none";
border-radius: "6px";
cursor: "pointer";
transition: "background 0.2s ease";
":hover" {
background: "#3730a3";
}
}
}
fn app() -> VirtualNode {
html! {
div {
class: c_app_container
h1 {
class: c_title
"euv Styling Demo"
}
div {
class: c_card
p { "This card uses the class! macro for styling." }
}
div {
class: euv-fade-in
p { "This element uses a built-in animation." }
}
}
}
}
mount("#app", app);
总结
class! 宏提供了一种强大且便捷的方式来管理 euv 中的样式:
- CSS 类定义:使用
pub class_name { property: "value"; }定义类 - 伪类:使用嵌套块如
":hover" { ... }实现交互状态 - 内置动画:使用
euv-spin、euv-fade-in、euv-scale-in、euv-pulse、euv-slide-up、euv-slide-left、euv-fade-in-up、euv-progress、euv-shimmer - 自定义动画:通过
Css::inject_css()创建自定义关键帧 - CSS 过渡:在类定义中添加平滑的属性过渡
- 在模板中使用:在
html!宏中通过class: class_name应用类
通过 class! 宏,你可以将样式与组件保持在一起,使 UI 外观的维护和推理变得更加容易。