@property 是一个新特性,支持主流浏览器,它允许开发者显式地定义他们的CSS 自定义属性, 允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承,通过一个简单的案例为大家介绍一下@property规则的用法,详细的介绍文档可以点击链接查看。
https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property
前言
上图是UnoCSS文档内一个比较酷的效果,背景采用了线性渐变,文字和背景的渐变呼应,页面中所有的按钮基于渐变的主色调,效果还是比较酷的,大家感兴趣可以去UnoCSS官方文档查看这个效果。
https://unocss.dev/
这个效果采用的是纯css完成的,结合了animation动画、@keyframes定义关键帧、–css自定义属性、linear-gradient()线性渐变等知识模块。
源码实现起来比较复杂,主要是对@keyframes定义关键帧太过复杂,然后让animation按照这个动画进行轮播,给大家贴一下他的关键帧定义,如果你要是按照他的方法定义,应该会把你给直接劝退。
源码内,关键帧是0%一直定义到100%,每间隔1.25定义一下颜色,如果不配合一些自动化工具或者AI协助,那工作量相当庞大,而且配出来的颜色还不一定好看。
所以我一直尝试,有没有更加渐变的方法实现这个效果,下面是我开发的项目,大家可以微信小程序搜索“鸡汤来喽”小程序,就可以看到我简化后的效果,如图所示:
下面就一步步的给大家介绍,我是如何实现的。
一、自定义属性,AI按需生成关键帧配色
在CSS中通过–标识符定义自定义属性(CSS变量),通过var()函数引用,如下代码示例:
css">:root {--main-color: #3498db; /* 定义全局变量 */
}
.element {--font-size: 16px; /* 定义局部变量(仅作用于该元素及其子元素) */
}.element {color: var(--main-color); /* 直接引用 */font-size: var(--font-size, 14px); /* 设置默认值(当变量未定义时生效) */
}
css_38">1.给deepseek AI提示词生成css代码(仅作参考)
css">@keyframes colorChange {0% {--color1: 颜色1;--color2: 颜色2}
}
从0% - 100% 间隔10个为一组,要求color1生成明亮的漂亮的16进制颜色,要求color1的颜色范围广一些能够包含赤橙红绿青蓝紫,
color2根据color1生成邻近色,color2和color1在保持邻近色的同时,
color1和color2邻近色颜色差异调到最大,要求0%和100%能拼接起来,要求100%颜色和0%一样。
最终生成了如下代码,如果想要过渡更好看,可以将关键帧设置的再多一些,这里就生成了10组配色,当然生成之后,不能满足你的需求,你可以简单的进行微调。
css">@keyframes colorChange {0%, 100% {--color1: #ff0000; /* 红色 */--color2: #ff8000; /* 橙色 */}10% {--color1: #ff8000; /* 橙色 */--color2: #ffff00; /* 黄色 */}20% {--color1: #ffff00; /* 黄色 */--color2: #80ff00; /* 黄绿色 */}30% {--color1: #80ff00; /* 黄绿色 */--color2: #00ff00; /* 绿色 */}40% {--color1: #00ff00; /* 绿色 */--color2: #00ff80; /* 青绿色 */}50% {--color1: #00ff80; /* 青绿色 */--color2: #00ffff; /* 青色 */}60% {--color1: #00ffff; /* 青色 */--color2: #0080ff; /* 蓝色 */}70% {--color1: #0080ff; /* 蓝色 */--color2: #0000ff; /* 深蓝色 */}80% {--color1: #0000ff; /* 深蓝色 */--color2: #8000ff; /* 紫色 */}90% {--color1: #8000ff; /* 紫色 */--color2: #ff00ff; /* 紫红色 */}
}
2.设置animation属性,让动画动起来
css">:root{--color1: #ff0000;--color2: #ffd700;--background-gradient: linear-gradient(-45deg, var(--color1), var(--color2));animation: colorChange 8s linear infinite;
}
.element{width: 300px;height: 300px; background: var(--background-gradient);
}
如上代码:
-
给全局:root设置自定义属性–color1和–color2的默认颜色;
-
然后设置自定义属性–background-gradient设置线性渐变linear-gradient,线性渐变倾斜45度,第一个颜色是color1,第二个颜色是color2;
-
设置animation动画,指定关键帧是上面定义的colorChange,花费8秒钟跑完0%-100%的关键帧,匀速的重复循环播放;
-
给要展示的DOM设置背景色,即为刚刚定义的全局属性–background-gradient。
你可以以为这样就实现,可惜效果如下图所示,根本没有颜色融合,而是一帧帧的生硬播放。
这就很奇怪了,如果你使用过animation肯定知道,animation动画是可以对颜色进行融合的,如下图代码演示一下,动画对颜色的融合。
css">@keyframes boxColorChange{0%{background: #ff0000;}25%{background: #8000ff;}50%{background: #00ffff;}75%{background: #00ff00;}100%{background: #0000ff;}
}
.box{width: 360px;height: 360px;animation: boxColorChange 8s linear infinite;
}
然后将单色改成线性渐变,测试下过,如下代码所示:
css">@keyframes boxColorChange{0%{background: linear-gradient(#0000ff,#0080ff);}25%{background: linear-gradient(#00ff00,#00ff80)}50%{background: linear-gradient(#ff0000,#ff00ff);}75%{background: linear-gradient(#ff8000,#ffd700);}100%{background: linear-gradient(#ffff00,#00ff80);}
}
.box{width: 360px;height: 360px;animation: boxColorChange 8s linear infinite;
}
给背景设置单独颜色,帧动画是可以对颜色融合的,但是设置成渐变色之后将不会融合,知道问题之后就好办了。
第一种方案:
按照UnoCSS定义关键帧的方法,从0%按照递增1.25%的方式手动设置,这种方案显然是费事费力的,即使使用了AI给自动生成,结果需要分三次才能完整生成这个keyframes关键帧。
第二种方案:
使用实验性技术@property,这个规则比较新,但好在目前主流浏览器都支持这种写法。
3.@property注册自定义属性
css">@property --property-name {syntax: "<color>";inherits: false;initial-value: #c0ffee;
}
一个有效的 @property 规则代表一项自定义属性的注册,使用自定义属性名作为规则内代码序列的序部。
@property 规则中 syntax 和 inherits 描述符是必需的; 如果其中任何一项缺失,整条规则都将失效并且会被忽略。
initial-value 描述符仅在 syntax 描述符为通用 syntax
定义时是可选的,否则initial-value也是必需的——如果此时该描述符缺失,整条规则都将失效且被忽略。
详情文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property
syntax该属性所允许的语法结构
css">syntax: "<color>"; /* 接收一个颜色值 */
syntax: "<length> | <percentage>"; /* 接收长度或百分比参数,但是二者之间不进行计算合并 */
syntax: "small | medium | large"; /* 接收这些参数值之一作为自定义标识符 */
syntax: "*"; /* 任何有效字符 */
inherits自定义属性注册是否默认继承
true
该属性默认继承。
false
该属性默认不继承。
initial-value为属性设置初始值
initial-value: #c0ffee;
通过上面对@property规则的说明,可以将我们定义的自定义属性–color1和–color2增加@property规则,代码如下:
css">@property --color1 {syntax: "<color>";inherits: true;initial-value: #ff0000;
}@property --color2 {syntax: "<color>";inherits: true;initial-value: #ffd700;
}
然后,可以设置当前元素的模糊度,还可以给文本设置同样的渐变要过,如果觉得颜色太亮,可以使用filter: brightness(70%)滤镜,压一下暗色,给p标签制定单一的颜色–color1,最终的效果及完整的源码如下:
css"><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div class="container"><div class="element"></div><img src="https://cdn.qingnian8.com/project/chicken/chicken_color.png" class="logo"><h1>@property自定义属性规则</h1><p>有趣的css专题-咸虾米</p></div>
</body>
</html>
<style>
@keyframes colorChange {0%, 100% {--color1: #ff0000; /* 红色 */--color2: #ff8000; /* 橙色 */}10% {--color1: #ff8000; /* 橙色 */--color2: #ffff00; /* 黄色 */}20% {--color1: #ffff00; /* 黄色 */--color2: #80ff00; /* 黄绿色 */}30% {--color1: #80ff00; /* 黄绿色 */--color2: #00ff00; /* 绿色 */}40% {--color1: #00ff00; /* 绿色 */--color2: #00ff80; /* 青绿色 */}50% {--color1: #00ff80; /* 青绿色 */--color2: #00ffff; /* 青色 */}60% {--color1: #00ffff; /* 青色 */--color2: #0080ff; /* 蓝色 */}70% {--color1: #0080ff; /* 蓝色 */--color2: #0000ff; /* 深蓝色 */}80% {--color1: #0000ff; /* 深蓝色 */--color2: #8000ff; /* 紫色 */}90% {--color1: #8000ff; /* 紫色 */--color2: #ff00ff; /* 紫红色 */}
}@property --color1 {syntax: "<color>";inherits: true;initial-value: #ff0000;
}@property --color2 {syntax: "<color>";inherits: true;initial-value: #ffd700;
}:root{--color1: #ff0000;--color2: #ffd700;--background-gradient: linear-gradient(-45deg, var(--color1), var(--color2));animation: colorChange 20s linear infinite;
}.container{display: flex;flex-direction: column;align-items: center;margin: 60px auto;width: fit-content;position: relative;
}.element{width: 300px;height: 300px; background: var(--background-gradient);border-radius: 50%;filter: blur(60px);
}
.logo{position: absolute;width: 150px;top:100px;
}
h1{margin-top:60px;background: var(--background-gradient);background-clip: text;-webkit-background-clip: text;-webkit-text-fill-color: transparent;filter: brightness(70%);
}
p{margin:0;color:var(--color1);
}
</style>