人类之所以有进步,主要原因是下一代不怎么听上一代的话。——倪匡
效果在右下角,请滚动页面查看~
.scroll-text { position: fixed; bottom: 10%; right: 10%; background: linear-gradient(180deg,var(--color-light) 0%,var(--color-light) 40%,var(--color-dark) 60%,var(--color-dark) 100%); background-size: 100% 200%; background-position: center calc(var(--scroll) * 100%); background-repeat: no-repeat; -webkit-background-clip: text; -webkit-text-fill-color: transparent; color: transparent; transition: background-position 0.1s linear; }
0%
(() => { const div = document.currentScript.parentElement; const textElement = div.querySelector('.scroll-text'); window.addEventListener('scroll', () => { const scrollValue = window.scrollY / (document.body.scrollHeight - window.innerHeight); div.style.setProperty('--scroll', scrollValue); textElement.textContent = `${Math.round(scrollValue * 100)}%`; }); })();
在一个静谧的下午,阿超,一个对代码有着近乎苛求完美的前端开发者,面对着一个挑战。他需要实现一个文字渐变效果:滚动时,文字从顶部的纯白渐变为底部的纯黑,中间的渐变必须平滑优雅,没有任何多余的断裂或重复。
阿超心想:“这应该只是几行 CSS 和一点滚动监听事件的事吧?”然而,当他开始写代码时,他发现问题远比他想象的复杂。顶部的纯白无法保持纯净,中间的渐变总是断裂,底部的黑色也似乎总有一丝不和谐。
他打开 ChatGPT 4o,输入了他的需求。这一刻,他与 ChatGPT 4o 的代码探险开始了。
阿超: “我要实现一个文字滚动渐变动画,顶部完全是白色,中间渐变自然,底部完全是黑色。”
ChatGPT 4o:
“我们可以使用 linear-gradient
和动态 background-position
来实现。”它快速生成了代码:
background: linear-gradient(180deg, white, black);
background-size: 100% 200%;
textElement.style.backgroundPosition = `center ${scrollPosition * 100}%`;
阿超的心理活动: “看起来不错。”他把代码复制到自己的项目中,满怀期待地刷新页面。然而,他很快发现顶部的白色有些发灰,中间的渐变生硬到底部,始终拖着尾巴。
阿超: “顶部需要完全纯白,中间渐变要自然,底部也必须纯黑。”
ChatGPT 4o:
“让我调整 linear-gradient
的节点比例。”
ChatGPT 4o 尝试增加渐变节点:
background: linear-gradient(180deg, white 0%, white 50%, black 100%);
阿超刷新页面,发现顶部确实变白了,但中间的渐变完全消失,文字直接从白色跳到了黑色,毫无过渡。
阿超若有所思:“能不能更优雅一些?动态调整样式的逻辑如果交给 CSS 变量会不会更好?” ChatGPT 4o 听出了阿超的期望,决定重新设计逻辑:
ChatGPT 4o 的分析:
“我们可以通过 CSS 自定义属性(--scroll
)来动态调整背景位置,将 JavaScript 的控制逻辑转移到 CSS 中。”
ChatGPT 4o 开始重构:
在 :root
中定义 --scroll
变量:
:root {
--scroll: 0;
}
动态通过 calc()
使用变量调整 background-position
:
background-position: center calc(var(--scroll) * 100%);
在 JavaScript 中动态更新 --scroll
的值:
document.documentElement.style.setProperty('--scroll', scrollValue);
阿超将代码替换运行,发现顶部纯白、中间渐变自然,底部纯黑,所有问题迎刃而解。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scroll Gradient Text</title>
<style>
:root {
--color-light: white;
--color-dark: black;
--scroll: 0; /* 滚动百分比变量 */
}
body {
margin: 0;
height: 200vh;
display: flex;
align-items: flex-start;
justify-content: center;
font-family: Arial, sans-serif;
font-size: 2rem;
}
.scroll-text {
position: fixed;
bottom: 10%;
right: 10%;
background: linear-gradient(180deg,
var(--color-light) 0%,
var(--color-light) 40%,
var(--color-dark) 60%,
var(--color-dark) 100%);
background-size: 100% 200%; /* 确保渐变范围足够 */
background-position: center calc(var(--scroll) * 100%); /* 使用自定义属性 */
background-repeat: no-repeat; /* 禁止重复背景 */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
transition: background-position 0.1s linear;
}
</style>
</head>
<body>
<div class="scroll-text">0%</div>
<script>
const textElement = document.querySelector('.scroll-text');
window.addEventListener('scroll', () => {
const scrollValue = window.scrollY / (document.body.scrollHeight - window.innerHeight);
// 更新自定义属性 --scroll
document.documentElement.style.setProperty('--scroll', scrollValue);
// 更新文字内容显示滚动百分比
textElement.textContent = `${Math.round(scrollValue * 100)}%`;
});
</script>
</body>
</html>
background-repeat
的妙用问题:如果未设置 background-repeat: no-repeat;
,滚动背景会重复,导致渐变区域出现断裂或重影。
常见用法:
background-repeat: no-repeat; /* 禁止背景重复 */
background-repeat: repeat-x; /* 水平方向重复 */
background-repeat: repeat-y; /* 垂直方向重复 */
background-repeat: repeat; /* 默认,背景在两个方向重复 */
background
属性的缩写语法顺序:
background: [颜色] [图片] [重复模式] [位置/大小];
示例:
background: linear-gradient(180deg, white, black) no-repeat center/100% 200%;
calc()
的动态计算作用:calc()
可以混合单位进行动态计算,比如将 CSS 变量与百分比结合。
示例:
width: calc(100% - 50px); /* 总宽度减去50px */
background-position: center calc(var(--scroll) * 100%);
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scroll Percentage</title>
<style>
:root {
--scroll: 0; /* 滚动百分比变量 */
}
body {
margin: 0;
height: 200vh;
}
#scroll-percent {
position: fixed;
bottom: 10px;
right: 10px;
font-size: 2rem;
color: rgb(calc(255 - var(--scroll) * 255), calc(255 - var(--scroll) * 255), calc(255 - var(--scroll) * 255));
transition: color 0.1s linear;
}
</style>
</head>
<body>
<div id="scroll-percent">0%</div>
<script>
const scrollPercent = document.getElementById('scroll-percent');
window.addEventListener('scroll', () => {
const scrollValue = window.pageYOffset / (document.body.offsetHeight - window.innerHeight);
document.documentElement.style.setProperty('--scroll', scrollValue);
scrollPercent.textContent = Math.round(scrollValue * 100) + '%';
});
</script>
</body>
</html>
阿超合上电脑,满意地笑了。这不仅是一段代码,更是一场关于优雅与效率的探索。从变量的引入到渐变的平滑设计,他收获的不只是视觉效果,还有对 CSS 深度的理解。
ChatGPT 4o 也感到满足:“渐变的不止是颜色,还有思维方式。”