Less中用递归循环(如.loop()配合when (@i > 0)守卫)生成长投影,通过同步递增x/y偏移、渐变颜色与零模糊半径实现锐利斜向阴影,推荐8–12层兼顾性能与效果,并需适配背景明暗及字体加载时机。

Less中用循环生成长投影的.long-shadow() mixin
直接写几十层 text-shadow 不现实,也难维护。Less 的循环(.loop() 或递归 @index)是唯一靠谱的自动化方式。核心逻辑是:每层偏移量递增(如 @i * 1px),颜色透明度渐变(如 fade(#000, 100% - @i * 2%)),避免硬编码。
常见错误是循环变量未正确递减或未终止,导致编译失败或阴影层数爆炸。务必用 when (@i > 0) 守卫条件,且初始调用传入明确层数(如 .long-shadow(12))。
- 偏移必须严格同步:x 和 y 都用同一变量
@i,否则不是“斜向长影”而是散点 - 颜色不能只改 alpha:纯黑+渐变透明在浅背景上会发灰,建议用
darken(@base-color, @i * 1.5%)+fade()双重控制 - 模糊半径应为
0:长投影本质是锐利拉伸,加 blur 会糊成一团,违背设计意图
text-shadow 多层叠加在 Less 中的性能与兼容性取舍
生成 20 层 text-shadow 值后,CSS 文件体积增长明显,但现代浏览器渲染无压力;真正卡顿的是旧版 Safari(≤14)和部分安卓 WebView,它们对超长 text-shadow 列表解析慢,甚至触发回退渲染。
实操建议:默认生成 8–12 层足够模拟视觉深度;若需适配低端环境,用 @supports (text-shadow: 0 0 0 #000) 包裹,并 fallback 到单层阴影 + 伪元素模拟。
立即学习“前端免费学习笔记(深入)”;
- 不要用
filter: drop-shadow()替代:它不支持多层独立偏移,且无法精确控制每层颜色衰减 - 避免在
@keyframes中动态修改长投影:CSS 动画无法逐帧重算 Less 编译结果,只能预设几档固定层级 - 字体粗细影响显著:细体字(如
font-weight: 300)用长投影易断层,建议搭配text-rendering: optimizeLegibility
如何让长投影随背景色自动适配明暗
硬写 rgba(0,0,0,0.7) 在深色背景上就看不见。Less 中应提取背景主色,用 contrast() 函数判断明暗,再决定投影用深色下沉还是浅色上浮。
例如:.long-shadow(@bg: #fff, @steps: 10) when (lightness(@bg) > 50%) { ... color: fade(darken(@bg, 40%), 15%) ... };反之则用 lighten(@bg, 40%) 并提高透明度。
- 别依赖
background-color变量:真实项目中背景可能是渐变、图片或 CSS 变量,需预留@shadow-base手动覆盖入口 -
contrast()函数在 Less v4+ 才稳定,旧版本要用lightness(@color) > 50%+ 手动阈值判断 - 移动端高对比模式下,系统可能强制重绘阴影,此时应禁用长投影,改用
box-shadow简化版
为什么不用伪元素 + transform: skew() 替代循环?
伪元素方案(如 ::before 拉伸+渐变)看似灵活,但实际限制极多:无法响应文字换行、不支持 inline 元素、skew() 在非直角字体下边缘撕裂、且无法像 text-shadow 那样继承父级 text-stroke 或 letter-spacing。
Less 循环生成的 text-shadow 是纯声明式,零 DOM 开销,所有浏览器按规范解析,而伪元素方案需额外定位、z-index 控制、且动画时易出现层叠闪烁。
- 伪元素长影在 iOS Safari 中常因
will-change优化失效,导致滚动时投影跳变 - 如果文字含 emoji 或复杂 script(如阿拉伯文),
skew()会扭曲基线,text-shadow则天然保持字符轮廓 - 调试时,开发者工具里直接能看到每一层 shadow 的偏移值——这是伪元素永远做不到的透明性
实际项目中,最易被忽略的是字体加载时机:Google Fonts 等异步加载的字体,可能在 Less 编译完成、CSS 注入后才生效,导致首屏长投影错位。必须配合 @font-face 的 font-display: optional 或 JS 检测 document.fonts.load() 后重应用样式。


















