散景光斑

柔和的失焦光斑在内容后面飘动、呼吸,像透过镜头看到的城市灯光。

  • CSS
  • 背景
  • 循环
  • 收录于

夜间特刊

AI 提示词

用纯 CSS 制作散景光斑背景。放置约十个绝对定位的圆形,通过内联 CSS 自定义属性设置随机的尺寸(30–110px)、位置和暖色调。每个圆用渐变到透明的 radial-gradient 填充,加上 filter: blur(6px) 和 mix-blend-mode: screen,让重叠的光斑更亮。每个光斑运行一个 keyframe:translate 漂移 ±20px,scale 在 0.85 到 1.1 之间变化,opacity 在 0.35 到 0.8 之间呼吸;使用 alternate infinite,每个光斑的时长不同(8–16s)并设置负延迟,确保它们永远不同步。离开屏幕时暂停动画。在 prefers-reduced-motion 下光斑保持静止。标题为“夜间特刊”。

源代码

Demo.tsx
'use client'

import { useEffect, useRef } from 'react'
import s from './demo.module.css'

// Fixed values so server and client render the same markup.
const ORBS = [
  [8, 20, 70, 40, 9], [22, 70, 40, 60, 12], [35, 30, 100, 30, 14], [48, 80, 55, 70, 10], [60, 15, 80, 50, 16],
  [72, 60, 110, 25, 11], [85, 30, 45, 80, 13], [92, 75, 65, 45, 8], [15, 50, 35, 90, 15], [55, 45, 30, 20, 9],
]

export default function Bokeh({ labels }: { labels: Record<string, string> }) {
  const ref = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const el = ref.current
    if (!el) return
    const io = new IntersectionObserver(([e]) => el.toggleAttribute('data-paused', !e.isIntersecting))
    io.observe(el)
    return () => io.disconnect()
  }, [])

  return (
    <div ref={ref} className={s.scene}>
      {ORBS.map(([x, y, size, hue, dur], i) => (
        <span
          key={i}
          className={s.orb}
          aria-hidden="true"
          style={{ '--x': `${x}%`, '--y': `${y}%`, '--size': `${size}px`, '--hue': hue, '--dur': `${dur}s`, '--delay': `${-i * 1.7}s` } as React.CSSProperties}
        />
      ))}
      <p className={s.title}>{labels.title}</p>
    </div>
  )
}
demo.module.css
.scene {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 120%, oklch(28% 0.04 50), var(--stage-bg));
}

.orb {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--size);
  height: var(--size);
  margin: calc(var(--size) / -2) 0 0 calc(var(--size) / -2);
  border-radius: 50%;
  background: radial-gradient(circle, oklch(80% 0.13 var(--hue)) 0 40%, transparent 70%);
  filter: blur(6px);
  mix-blend-mode: screen;
  opacity: 0.5;
  animation: drift var(--dur) ease-in-out var(--delay) infinite alternate;
}

.scene[data-paused] .orb { animation-play-state: paused; }

@keyframes drift {
  0% { transform: translate(-20px, 10px) scale(0.85); opacity: 0.35; }
  50% { opacity: 0.8; }
  100% { transform: translate(20px, -15px) scale(1.1); opacity: 0.45; }
}

.title {
  position: relative;
  margin: 0;
  font: 600 var(--text-2xl) / 1 var(--font-display);
  letter-spacing: -0.01em;
  color: var(--stage-ink);
}

@media (prefers-reduced-motion: reduce) {
  .orb { animation: none; }
}

投稿创意

看到想收录的动效或主题?简单描述一下,会打开一个预先填好的 GitHub Issue,确认后即可提交。

你想投稿的是?

需要 GitHub 账号,投稿内容会公开。