过去一周,我仅用CSS(其中有一个用了点HTML,但大部分都是纯CSS)编写了一系列光学错觉效果。我在CodePen上建了个合集,放了40个,接下来几周可能还会加新的。
很多都玩转色彩效果,有些是动画的,不少都应该有(也确实加了)动态提示……不过可能我还得多加几个。编其中几个的时候,我自己都看得头晕眼花😬
下面是合集里我最喜欢的几个:
这个是动画效果的(在窄屏或宽屏上看效果更好)。玩法是:先盯着红点看,注意它们上下移动;然后盯住任意一个黑色十字……突然红点就开始波浪式移动了!
/* 光学错觉
看红点:它们走直线。现在盯住任意黑十字,红点就会像沿着曲线而非直线移动。
*/
@keyframes ball {
0% { transform: translate(0, 0); }
100% { transform: translate(0, -92%); }
}
body {
margin: 0;
height: 100vh;
overflow: hidden;
font-size: 0.8vw;
background:
linear-gradient(#000 0 0) 50% 50% / 0.4em 2em,
linear-gradient(#000 0 0) 50% 50% / 2em 0.4em,
linear-gradient(#000 0 0) 50% 3em / 0.4em 2em,
linear-gradient(#000 0 0) 50% 3.8em / 2em 0.4em,
linear-gradient(#000 0 0) 50% calc(100% - 3em) / 0.4em 2em,
linear-gradient(#000 0 0) 50% calc(100% - 3.8em) / 2em 0.4em,
#777;
background-repeat: no-repeat;
&::before {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
translate: -50% -50%;
--mask:
radial-gradient(7.75em at calc(100% + 5.25em) 50%,#0000 calc(99% - 1em),#000 calc(101% - 1em) 99%,#0000 101%) calc(50% - 5em + .5px) calc(50% - 10em)/ 10em 20em,
radial-gradient(7.75em at -5.25em 50%,#0000 calc(99% - 1em),#000 calc(101% - 1em) 99%,#0000 101%) calc(50% + 5em) 50%/10em 20em;
-webkit-mask: var(--mask);
mask: var(--mask);
background: #fff;
clip-path: polygon(5% 0, 45% 0, 45% 100%, 55% 100%, 55% 0, 95% 0, 95% 100%, 5% 100%);
clip-path: polygon(0% 0, 45% 0, 45% 100%, 55% 100%, 55% 0, 100% 0, 100% 100%, 0% 100%)
}
&::after {
--color: #f00;
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
translate: -50% -50%;
background:
radial-gradient(circle at 50% 96%, red 2em, #0000 0) 50% 50% / 8% 100%
;
animation: ball 3s linear alternate infinite;
clip-path: polygon(0% 0, 45% 0, 45% 100%, 55% 100%, 55% 0, 100% 0, 100% 100%, 0% 100%)
}
}
这个(和下一个)我用的是超巧妙的波浪形状生成器。
这几组曲线几乎一样:唯一区别是颜色。从拐点画到拐点,或从波峰画到波峰,会让它们看起来完全不同——甚至其中一个看着都不太像波浪了!(小屏上看效果更好)

/* 视觉效果:
一组线看着更直(上),另一组更圆润(下)……但两组波纹程度一样,唯一区别是着色方式。鼠标悬停可揭晓
*/
@property --c {
syntax: '<color>';
initial-value: #fff;
inherits: true;
}
body {
/* 改编自Temani Afif在CSS Tricks的代码:https://css-tricks.com/how-to-create-wavy-shapes-patterns-in-css/ */
--s: 60px;
--c: #fff;
--c1: radial-gradient(68.08px at 50% calc(100% + 60px),#0000 calc(99% - 2px),#000 calc(101% - 2px) 99%,#0000 101%);
--c2: radial-gradient(68.08px at 50% -60px,#0000 calc(99% - 2px),#000 calc(101% - 2px) 99%,#0000 101%);
--s1: 120px 32px repeat-x;
--mask:
var(--c1) 0 calc(50% - 16px + .5px) / var(--s1),
var(--c2) var(--s) calc(50% + 16px) / var(--s1),
var(--c1) 0 calc(50% - 6px + .5px) / var(--s1),
var(--c2) var(--s) calc(50% + 26px) / var(--s1),
var(--c1) 0 calc(50% + 20px + .5px) / var(--s1),
var(--c2) var(--s) calc(50% + 52px) / var(--s1),
var(--c1) 0 calc(50% + 30px + .5px) / var(--s1),
var(--c2) var(--s) calc(50% + 62px) / var(--s1);
background: #aaa;
margin: 0;
height: 100vh;
transition: --c 1s;
overflow: hidden;
&:hover {
--c: #000;
}
&::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(90deg, #000 50%, var(--c) 0) 0 0 / calc(var(--s) * 2) 100%;
mask: var(--mask);
translate: 0 -100px;
}
&::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(90deg, #000 50%, var(--c) 0) calc(var(--s) / -2) 0 / calc(var(--s) * 2) 100%;
translate: 0 100px;
mask: var(--mask);
}
}你看到红、蓝、绿的圆球了吗?要是我告诉你它们都是灰色的呢?(真的!鼠标悬停在演示上就能看到本色)但在上面叠了些原色后,大脑会用看到的颜色“填补”圆圈。一开始我把线条画太高,效果就看不出来了。我喜欢最终效果。

/* 光学错觉
三个“圆球”颜色相同,但叠加图层后看着像绿的、红的、蓝的。鼠标悬停揭晓;
*/
body {
--size: 1em;
--line-size: calc(var(--size) / 3);
font-size: 10px;
margin: 0;
height: 100vh;
overflow: hidden;
&::after {
content: "";
width: calc(var(--size) * 30);
height: calc(var(--size) * 30);
position: absolute;
top: calc(var(--size) * 20);
left: 50%;
translate: -50% -33.333%;
background:
radial-gradient(farthest-side circle, #fff 0%, #bbb 66.66%, #0000 calc(66.66% + 1px)) 0 0 / 33.333% 100%;
background:
radial-gradient(farthest-side circle at 45% 45%, #0000 60%, #0004) 0 0 / 33.333% 33.333%,
radial-gradient(farthest-side circle at 33% 33%, #fffc 0%, #fff0) 0 0 / 33.333% 33.333%,
radial-gradient(farthest-side circle at 20% 20%, #0000 0%, #0004) 0 0 / 33.333% 33.333%,
#ba9;
mask:
radial-gradient(farthest-side circle, #fff 66.66%, #0000 calc(66.66% + 1px)) 0 0 / 33.333% 33.333% intersect,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 0 0 / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 50% calc(var(--size) / 3) / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 100% calc(var(--size) / 3 * 2) / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 0 calc(50% + var(--size) / 3) / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 50% calc(50% + var(--size) / 3 * 2) / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 100% 50% / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 0 calc(100% + var(--size) / 3 * 2) / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 50% 100% / 33.333% 33.333% no-repeat,
repeating-linear-gradient(#000 0 calc(var(--size) / 3 * 2), #0000 0 var(--size)) 100% calc(100% + var(--size) / 3) / 33.333% 33.333% no-repeat;
}
&::before {
content: "";
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
background:
linear-gradient(#00f 33.33%, #0f0 0 66.66%, #f00 0) 0 0 / var(--size) var(--size);
transition: height 1s;
}
&:hover {
&::before {
height: 0;
}
}
}两侧竖条和中间横线都是同一种平涂灰色——没错,单一灰度。唯一的渐变是背景,线条本身没有。我喜欢这个演示,容易看清也容易编。

/* 视觉效果
中间的横线看着像从浅灰到深灰的渐变,但其实全是同色。这和屏幕两侧的竖条颜色一样,尽管一边看着比另一边暗。
*/
body {
height: 100vh;
margin: 0;
background:
linear-gradient(#aaa 0 0) 0 0 / 5vw 100%,
linear-gradient(#aaa 0 0) 100% 0 / 5vw 100%,
linear-gradient(#aaa 0 0) 50% 50% / 70% 7.5vw,
linear-gradient(90deg, #666, #eee);
background-repeat: no-repeat;
}
另一个动画效果的,得去CodePen看。蓝色方块看似在脉动或呼吸,依次变大变小……但其实它是同一个方块,大小没变,只是在旋转。鼠标悬停就能看清。
/* 光学错觉
背景里的方块看似在像呼吸或心跳一样胀缩。其实它只是旋转,大小一直不变。鼠标悬停揭晓。
*/
@keyframes spin {
0% { rotate: 0; }
100% { rotate: 360deg; }
}
body {
&::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
background: blue;
width: 40vmin;
aspect-ratio: 1;
animation: spin 4.5s linear infinite;
}
&::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
background: conic-gradient(at 80% 80%, #0000 75%, #097 0) 0 0 / 55.5% 55.5%;
width: 80vmin;
aspect-ratio: 1;
scale: 1;
transition: scale 1s;
}
&:hover {
&::after {
scale: 8;
}
}
}接下来几周北京心玥软件公司还会继续加新的。