使用css的@property规则注册自定义属性结合deepseek完成渐变色融合过渡效果

107 阅读8分钟

在这里插入图片描述

@property 是一个新特性,支持主流浏览器,它允许开发者显式地定义他们的CSS 自定义属性, 允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承,通过一个简单的案例为大家介绍一下@property规则的用法,详细的介绍文档可以点击链接查看。 developer.mozilla.org/zh-CN/docs/…

在这里插入图片描述

前言

上图是UnoCSS文档内一个比较酷的效果,背景采用了线性渐变,文字和背景的渐变呼应,页面中所有的按钮基于渐变的主色调,效果还是比较酷的,大家感兴趣可以去UnoCSS官方文档查看这个效果。 unocss.dev/

这个效果采用的是纯css完成的,结合了animation动画、@keyframes定义关键帧、--css自定义属性、linear-gradient()线性渐变等知识模块。

源码实现起来比较复杂,主要是对@keyframes定义关键帧太过复杂,然后让animation按照这个动画进行轮播,给大家贴一下他的关键帧定义,如果你要是按照他的方法定义,应该会把你给直接劝退。 在这里插入图片描述 源码内,关键帧是0%一直定义到100%,每间隔1.25定义一下颜色,如果不配合一些自动化工具或者AI协助,那工作量相当庞大,而且配出来的颜色还不一定好看。

所以我一直尝试,有没有更加渐变的方法实现这个效果,下面是我开发的项目,大家可以微信小程序搜索“鸡汤来喽”小程序,就可以看到我简化后的效果,如图所示:

在这里插入图片描述

下面就一步步的给大家介绍,我是如何实现的。

一、自定义属性,AI按需生成关键帧配色

在CSS中通过--标识符定义自定义属性(CSS变量),通过var()函数引用,如下代码示例:

:root {
  --main-color: #3498db;  /* 定义全局变量 */
}
.element {
  --font-size: 16px;      /* 定义局部变量(仅作用于该元素及其子元素) */
}

.element {
  color: var(--main-color);          /* 直接引用 */
  font-size: var(--font-size, 14px); /* 设置默认值(当变量未定义时生效) */
}

1.给deepseek AI提示词生成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组配色,当然生成之后,不能满足你的需求,你可以简单的进行微调。

@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属性,让动画动起来

: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);  
}

如上代码:

  1. 给全局:root设置自定义属性--color1和--color2的默认颜色;

  2. 然后设置自定义属性--background-gradient设置线性渐变linear-gradient,线性渐变倾斜45度,第一个颜色是color1,第二个颜色是color2;

  3. 设置animation动画,指定关键帧是上面定义的colorChange,花费8秒钟跑完0%-100%的关键帧,匀速的重复循环播放;

  4. 给要展示的DOM设置背景色,即为刚刚定义的全局属性--background-gradient。

你可以以为这样就实现,可惜效果如下图所示,根本没有颜色融合,而是一帧帧的生硬播放。 在这里插入图片描述

这就很奇怪了,如果你使用过animation肯定知道,animation动画是可以对颜色进行融合的,如下图代码演示一下,动画对颜色的融合。

@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;
}

在这里插入图片描述

然后将单色改成线性渐变,测试下过,如下代码所示:

@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注册自定义属性

@property --property-name {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0ffee;
}

一个有效的 @property 规则代表一项自定义属性的注册,使用自定义属性名作为规则内代码序列的序部。

@property 规则中 syntax 和 inherits 描述符是必需的; 如果其中任何一项缺失,整条规则都将失效并且会被忽略。 initial-value 描述符仅在 syntax 描述符为通用 syntax 定义时是可选的,否则initial-value也是必需的——如果此时该描述符缺失,整条规则都将失效且被忽略。 详情文档:developer.mozilla.org/zh-CN/docs/…

syntax该属性所允许的语法结构

syntax: "<color>"; /* 接收一个颜色值 */
syntax: "<length> | <percentage>"; /* 接收长度或百分比参数,但是二者之间不进行计算合并 */
syntax: "small | medium | large"; /* 接收这些参数值之一作为自定义标识符 */
syntax: "*"; /* 任何有效字符 */

inherits自定义属性注册是否默认继承

true 该属性默认继承。

false 该属性默认不继承。

initial-value为属性设置初始值

initial-value: #c0ffee;

通过上面对@property规则的说明,可以将我们定义的自定义属性--color1和--color2增加@property规则,代码如下:

@property --color1 {
  syntax: "<color>";
  inherits: true;
  initial-value: #ff0000;
}

@property --color2 {
  syntax: "<color>";
  inherits: true;
  initial-value: #ffd700;
}

然后,可以设置当前元素的模糊度,还可以给文本设置同样的渐变要过,如果觉得颜色太亮,可以使用filter: brightness(70%)滤镜,压一下暗色,给p标签制定单一的颜色--color1,最终的效果及完整的源码如下: 在这里插入图片描述

<!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>