☰
阳光穿透树叶的丁达尔光斑动效:纯 CSS 径向渐变与混合模式叠加实战
2026/10/11 2:21:41 网站建设 项目流程

在日语中,有一个极其唯美的专有词汇叫作“木漏れ日(Komorebi)”,专门用来指代“阳光穿透树叶的缝隙,在地面与墙面上洒下的摇曳光斑与丁达尔光柱”。

每当秋日微风拂过银杏树冠,金黄的枝叶随风轻轻晃动,原本均匀的日光被破碎的叶缝切割成一道道清晰可见的光束(丁达尔效应,Tyndall Effect);地面上的光斑忽大忽小、明暗流转,宛如无数只金色的蝴蝶在林间翩翩起舞。这种细腻的光影律动,往往能瞬间平复人内心的浮躁,带来一种置身于大自然深处的沉浸感。

然而,在前端界面的动效还原中,很多开发者在尝试复刻这一视觉奇观时,常常陷入误区:

  1. 沉重的视频/动图方案:引入一段十几兆循环播放的 WebM/MP4 视频或高清 GIF。这不仅严重拖慢首屏加载速度,而且在移动端经常面临黑屏、自动播放受阻或循环衔接突兀等顽疾;
  2. 复杂的 Canvas 光线追踪(Ray Marching)方案:在主线程使用 CPU 或着色器进行体素光照计算。虽然物理精确,但对于个人手账或封面背景这类装饰性组件而言,往往杀鸡用牛刀,白白消耗用户的电池与 GPU 算力。

如何用最轻量、纯原生的 CSS 代码,在网页上画出流动、通透、且如同呼吸般自然的丁达尔光柱与摇曳光斑?

本文将带大家深入剖析CSS 多层渐变矩阵(Linear & Radial Gradients)与现代混合模式(mix-blend-mode: screen)的物理级拟真协同,打造一套纯 CSS 驱动的“秋日木漏之光”治愈系动效。


一、物理光学拆解:如何用 CSS 捕捉阳光的形状?

在光学物理学中,“木漏之光”其实由两个互相叠加的光学图层交织而成:

[空气中的散射光束:丁达尔光柱层 (Tyndall Light Shafts)] └── 倾斜 60 度的半透明白色/暖金锥形平行光束,表现悬浮微尘的反光 │ ▼ [物体表面接收的焦点光斑:树影斑驳层 (Komorebi Dappled Spots)] └── 地面或相纸上圆形、椭圆形的非均质高斯发光点,边缘羽化,互相重叠 │ ▼ [秋日风景底图 / 手账画板底板 (Base Photo / Canvas)]

关键混合模式:mix-blend-mode: screen(滤色)

在真实世界中,光线是“加色混合(Additive Mixing)”。两个光斑重叠的地方,亮度不会变暗,而是会产生更明亮的高光。
在 CSS 中,mix-blend-mode: screen的数学公式为:
$$\text{Result} = 1 - (1 - \text{Base}) \times (1 - \text{Blend})$$
这使得纯黑色背景($0$)变为完全透明,而半透明的暖金色光斑在叠加后色度呈几何级数提亮,中心相交处自动泛出宛如阳光直射镜头一般的璀璨高光,完全不需要编写任何复杂的着色器!


二、架构设计:纯 CSS 渐变光照合成器

我们将这套纯 CSS 光影系统分解为三层结构:

  1. 光束层(Light Beams):利用多重重叠的线性渐变(linear-gradient),设定微小的透明度色标差,构成从左上方 60 度倾斜刺入的半透明光柱群;
  2. 光斑透镜层(Bokeh Spots):利用径向渐变(radial-gradient)在不同坐标位置点缀数十个大小不一的软边缘发光圆斑;
  3. 风动摇曳驱动(Wind Drift Animation):通过两组互质周期(Prime Durations)的@keyframes动画,分别控制光斑微弱的坐标抖动与明暗呼吸,模拟微风吹拂树梢时光斑的无序摇晃。

三、纯 CSS 核心工程实现代码

下面是完整的组件代码,HTML 结构保持极致的语义化与简洁,所有的光影渲染完全交给 CSS 引擎:

<div class="komorebi-viewport"> <!-- 底层手账相册插画 --> <div class="scenery-base"> <div class="autumn-leaves-canopy"></div> <div class="journal-card-preview"> <h3>🍂 银杏大道漫步记</h3> <p>阳光穿透树叶,落满了整个深秋。</p> </div> </div> <!-- 纯 CSS 丁达尔光影覆盖层 --> <div class="sunlight-overlay"> <!-- 倾斜光柱束 --> <div class="tyndall-shafts"></div> <!-- 摇曳发光光斑群 --> <div class="dappled-spots"></div> </div> </div>

精密调校的纯 CSS 样式表

/* 容器视口 */ .komorebi-viewport { position: relative; width: 480px; height: 340px; border-radius: 16px; overflow: hidden; background: #3B2A1E; box-shadow: 0 16px 36px rgba(0, 0, 0, 0.25); } /* 底层场景 */ .scenery-base { width: 100%; height: 100%; background: linear-gradient(135deg, #A86234 0%, #E0A94F 50%, #4A3525 100%); position: relative; display: flex; align-items: center; justify-content: center; } .journal-card-preview { background: rgba(254, 250, 242, 0.92); padding: 24px 32px; border-radius: 10px; box-shadow: 0 8px 24px rgba(60, 40, 20, 0.15); text-align: center; color: #3D2C1F; } .journal-card-preview h3 { margin: 0 0 8px 0; font-size: 20px; } .journal-card-preview p { margin: 0; font-size: 13px; color: #7D6352; } /* 核心光影覆盖层:开启滤色混合模式 */ .sunlight-overlay { position: absolute; inset: 0; pointer-events: none; mix-blend-mode: screen; /* 核心加色滤色混合 */ overflow: hidden; } /* 1. 纯 CSS 模拟倾斜 60 度的丁达尔光束 */ .tyndall-shafts { position: absolute; inset: -50px; background: repeating-linear-gradient( 65deg, rgba(255, 245, 200, 0) 0px, rgba(255, 245, 200, 0) 40px, rgba(255, 245, 200, 0.18) 70px, rgba(255, 248, 220, 0.32) 90px, rgba(255, 245, 200, 0.12) 110px, rgba(255, 245, 200, 0) 140px ); filter: blur(12px); /* 产生空气悬浮散射感 */ animation: shaftBreathing 6.5s ease-in-out infinite alternate; transform-origin: top left; } /* 2. 纯 CSS 多重径向渐变模拟地面摇曳斑驳光斑 */ .dappled-spots { position: absolute; inset: -20px; background-image: /* 大号核心暖金发光斑 */ radial-gradient(circle at 35% 30%, rgba(255, 235, 170, 0.6) 0%, rgba(255, 235, 170, 0) 35%), /* 中号散落光斑 */ radial-gradient(circle at 65% 45%, rgba(255, 240, 190, 0.5) 0%, rgba(255, 240, 190, 0) 25%), radial-gradient(circle at 25% 70%, rgba(255, 230, 160, 0.45) 0%, rgba(255, 230, 160, 0) 30%), radial-gradient(circle at 80% 25%, rgba(255, 245, 210, 0.4) 0%, rgba(255, 245, 210, 0) 20%), /* 细碎微小灵动光斑 */ radial-gradient(circle at 50% 60%, rgba(255, 250, 220, 0.7) 0%, rgba(255, 250, 220, 0) 15%), radial-gradient(circle at 40% 80%, rgba(255, 240, 180, 0.5) 0%, rgba(255, 240, 180, 0) 18%), radial-gradient(circle at 75% 75%, rgba(255, 245, 195, 0.55) 0%, rgba(255, 245, 195, 0) 22%); filter: blur(8px); animation: windDrift 4.8s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite alternate; } /* 光束随日照强度微弱明暗呼吸 */ @keyframes shaftBreathing { 0% { opacity: 0.65; transform: scale(0.98) rotate(0deg); } 50% { opacity: 0.95; transform: scale(1.02) rotate(1deg); } 100% { opacity: 0.75; transform: scale(1.0) rotate(-0.5deg); } } /* 光斑模拟微风吹拂树叶时的有机微弱位移 */ @keyframes windDrift { 0% { transform: translate(0, 0) scale(1); } 35% { transform: translate(-8px, 6px) scale(1.03); } 70% { transform: translate(6px, -5px) scale(0.97); } 100% { transform: translate(4px, 7px) scale(1.02); } }

四、GPU 硬件加速与图层渲染性能分析

很多同学在使用filter: blur()与复杂的linear-gradient时会担心性能卡顿。在这个设计中,我们采用了极其严密的GPU 合成隔离策略:

  1. 绝对脱离文档流:
    .sunlight-overlay使用position: absolute并配合pointer-events: none,完全脱离标准文档流,其尺寸变化与动画绝对不会引起外层 HTML 任何文本的重排(Reflow);
  2. 纯 Transform 驱动矩阵合成:
    动画关键帧只修改了transform: translate()与opacity,现代浏览器(Blink、WebKit、Gecko)会直接在独立的 Compositor 线程调用显卡的顶点着色器完成纹理平移与淡入淡出,完全不占用 CPU 主线程 JavaScript 时间片,即使在低配笔记本或手机浏览器上,依然能够坚挺稳定在满帧 60fps。

五、结语

前端动效的最高境界,并不是用复杂的代码去堆砌冷冰冰的几何图形,而是懂得如何用现代浏览器的光学引擎,去捕捉大自然中最深情的那一抹微光。

没有引入任何大型动画库,仅靠几组纯粹的 CSS 渐变与滤色混合,便能在用户的屏幕上,重现秋日午后银杏树下那片温暖、静谧而又充满生机的摇曳树影。技术在此刻隐去,留下的唯有直抵人心的纯净诗意。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询