class! 宏
定义 CSS 类
use euv_macros::*;
class! {
pub container {
max_width: "800px";
margin: "0 auto";
}
pub(crate) header {
font_size: "28px";
}
hidden {
display: "none";
}
}可见性修饰
| 修饰符 | 说明 | |
|---|---|---|
pub | 公开,生成公开的 CSS 类函数 | |
pub(crate) | crate 内可见 | |
| 无修饰 | 私有 |
参数化 CSS 类
class! 宏支持定义带参数的 CSS 类,样式值可动态计算:
class! {
pub dynamic_color(color: &str) {
color: {color};
padding: "8px 16px";
border_radius: "4px";
}
pub size_box(width: &str, height: &str) {
width: {width};
height: {height};
border: "1px solid #ccc";
}
}使用:
html! {
div {
class: dynamic_color("#4f46e5")
"Colored text"
}
div {
class: size_box("200px", "100px")
"Sized box"
}
}提示
参数化 CSS 类的样式值使用花括号 {param} 包裹动态表达式,静态值仍使用字符串字面量。框架会根据参数值生成唯一的类名(如 dynamic_color-4f46e5),避免样式冲突。
注意
参数化类返回 CssClass 实例(每次调用创建新实例),非参数化类返回 &'static CssClass(通过 OnceLock 单例缓存)。对于频繁使用的静态样式,优先使用非参数化形式以获得更好的性能。
继承(extends)
class! 宏支持类继承语法,一个类可以继承一个或多个父类的样式属性:
class! {
pub c_base {
padding: "8px 16px";
border_radius: "4px";
font_size: "14px";
}
pub c_primary {
background: "#4f46e5";
color: "white";
}
pub c_primary_button {
c_base();
c_primary();
cursor: "pointer";
hover {
background: "#4338ca";
}
}
}使用:
html! {
button {
class: c_primary_button()
"Primary Button"
}
}继承支持参数化类:
class! {
pub c_size(size: &str) {
padding: {size};
}
pub c_large_button {
c_size("12px 24px");
background: "#4f46e5";
color: "white";
}
}提示
继承语法 c_base(); 会将父类的所有样式属性合并到子类中,生成完整的 CSS 字符串。父类的样式放在子类样式之前,子类可以覆盖继承的属性。
在 HTML 宏中使用
html! {
div {
class: c_card()
h3 { "Card Title" }
p { "Card content" }
}
}提示
class! 宏会生成与类名同名的函数,返回 CssClass 实例,调用时需要加 ()。
配合 css_vars! 使用
class! 宏的样式值支持使用 var! 宏引用 CSS 自定义属性,实现主题化样式:
css_vars! {
pub c_theme_light {
bg-primary: "#f8f9fb";
text-primary: "#1a1a2e";
}
pub c_theme_dark {
bg-primary: "#1a1a2e";
text-primary: "#f1f5f9";
}
}
class! {
pub c_container {
background: var!(bg-primary);
color: var!(text-primary);
max_width: "800px";
margin: "0 auto";
}
}提示
var! 宏在 class! 内部会展开为 CSS var(--variable-name) 字符串,支持 kebab-case 标识符或字符串字面量。详细用法参见 css_vars! 和 var! 宏。
样式属性名
样式属性名使用 snake_case,自动转换为 kebab-case:
class! {
pub c_flex_row {
display: "flex";
flex_direction: "row"; // → flex-direction
align_items: "center"; // → align-items
justify_content: "center"; // → justify-content
gap: "10px";
}
}伪类/伪元素规则
class! 宏支持在类定义中嵌套伪类和伪元素规则块,使用关键字 + 花括号语法:
class! {
pub c_button {
padding: "10px 20px";
border_radius: "6px";
cursor: "pointer";
background: "#4f46e5";
color: "white";
hover {
background: "#4338ca";
box_shadow: "0 4px 12px rgba(67, 56, 202, 0.4)";
}
focus {
outline: "2px solid #818cf8";
outline_offset: "2px";
}
active {
background: "#3730a3";
transform: "scale(0.98)";
}
disabled {
opacity: "0.5";
cursor: "not-allowed";
}
before {
content: "\"→\"";
margin_right: "8px";
}
}
}支持的伪类关键字
| 关键字 | CSS 选择器 |
|---|---|
hover | :hover |
focus | :focus |
focus_within | :focus-within |
focus_visible | :focus-visible |
active | :active |
visited | :visited |
disabled | :disabled |
enabled | :enabled |
checked | :checked |
readonly | :read-only |
readwrite | :read-write |
required | :required |
optional | :optional |
valid | :valid |
invalid | :invalid |
in_range | :in-range |
out_of_range | :out-of-range |
placeholder_shown | :placeholder-shown |
first_child | :first-child |
last_child | :last-child |
only_child | :only-child |
first_of_type | :first-of-type |
last_of_type | :last-of-type |
only_of_type | :only-of-type |
root | :root |
empty | :empty |
target | :target |
link | :link |
any_link | :any-link |
支持的伪元素关键字
| 关键字 | CSS 选择器 |
|---|---|
before | ::before |
after | ::after |
first_line | ::first-line |
first_letter | ::first-letter |
selection | ::selection |
placeholder | ::placeholder |
backdrop | ::backdrop |
marker | ::marker |
spelling_error | ::spelling-error |
grammar_error | ::grammar-error |
nth-child 参数化伪类
nth_child 和 nth_last_child 支持参数化,括号内传入参数:
class! {
pub c_stripe_row {
padding: "8px 12px";
nth_child(2n+1) {
background: "rgba(0, 0, 0, 0.05)";
}
nth_last_child(1) {
border_bottom: "none";
}
}
}提示
nth_child 和 nth_last_child 的下划线会自动转换为 CSS 的 nth-child 和 nth-last-child。
媒体查询规则
class! 宏支持 media(...) 块,在类定义中定义响应式样式:
class! {
pub c_responsive_container {
max_width: "800px";
padding: "20px";
media("(max-width: 768px)") {
padding: "12px";
font_size: "14px";
}
media("(min-width: 1200px)") {
max_width: "1200px";
font_size: "18px";
}
}
}提示
媒体查询条件以字符串形式写在 media(...) 的括号内,生成的 CSS 为 @media (条件) { .class-name { ... } }。
CSS 注入机制
CSS 类首次使用时,框架会自动将样式注入 DOM 的 <style id="euv-css-injected"> 元素。注入规则如下:
- 基础样式:
.class-name { style } - 伪类/伪元素规则:
.class-name:selector { style } - 媒体查询规则:
@media (query) { .class-name { style } }
同时注入以下全局样式:
| 全局样式 | 说明 |
|---|---|
html, body, #app { height: 100%; margin: 0; ... } | 全局重置 |
@keyframes euv-spin | 旋转动画 |
@keyframes euv-fade-in | 淡入动画 |
@keyframes euv-scale-in | 缩放进入动画 |
@keyframes euv-pulse | 脉冲动画 |
@keyframes euv-slide-up | 上滑动画 |
@keyframes euv-slide-left | 左滑动画 |
@keyframes euv-fade-in-up | 上移淡入动画 |
提示
CSS 类首次使用时自动注入样式到 DOM,无需手动引入 CSS 文件。相同类名的样式只会注入一次。样式注入采用追加模式(appendChild),不会读取和重写整个 <style> 元素的内容,避免性能开销。