这个 HTML 文件创建了一个视觉效果精美的宣传卡片,具有视差滚动和 3D 效果。
大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能解决问题,私信回复源码两字,我会发送完整的压缩包给你。
演示效果

HTML&CSS
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>关注公众号:前端Hardy</title>
<style>
:root {
--title: "Parallax Bake Shop Card";
--author: "Matt Cannon";
--contact: "[email protected]";
--description: "A whimsical bake shop card with a cupcake theme, parallax effects, dreamy text, and floating background layers.";
--keywords: "cupcake animation, sweet treats, parallax effect, css animation, javascript, food theme, codepenchallenge, bakery banner, interactive header, dessert ui, creative design";
--last-modified: "2025-05-27";
--content-language: "en";
--generator: "HTML5, CSS3, JavaScript, Web Animations API";
}
*,
*:after,
*:before {
box-sizing: border-box;
}
:root {
--x: 0;
--y: 0;
}
html {
color-scheme: light only;
}
body {
display: flex;
place-items: center;
justify-content: center;
min-height: 100svh;
touch-action: none;
font-family: "Rubik", sans-serif;
margin: 0;
padding: 0.5rem;
background: linear-gradient(to bottom, #e68d9f, #ffffff),
url("https://www.transparenttextures.com/patterns/asfalt-light.png");
background-blend-mode: overlay;
}
article {
width: 600px;
aspect-ratio: 2 / 1.1;
max-height: calc(100svh - 2rem);
position: relative;
overflow: hidden;
border-radius: 4em;
max-width: calc(100% - 2rem);
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.1));
}
@media (orientation: portrait) {
article {
min-height: 330px;
}
}
.assets {
position: absolute;
inset: 0;
border-radius: 4em;
overflow: hidden;
z-index: 0;
}
.assets>img {
position: absolute;
top: 0;
left: 50%;
translate: -50% 0;
height: 100%;
width: 660px;
object-fit: cover;
object-position: center 43%;
user-select: none;
pointer-events: none;
}
.assets>img:first-of-type {
filter: saturate(1.5) brightness(0.9);
object-position: calc(50% + (var(--x) * 30px)) calc(50% + (var(--y) * -20px));
}
.assets>img:last-of-type {
object-position: calc(50% + (var(--x) * 40px)) calc(50% + (var(--y) * 10px));
z-index: 99;
}
.assets h3 {
position: absolute;
left: 50%;
top: 8%;
margin: 0;
font-size: 8rem;
text-transform: uppercase;
font-family: "Bebas Neue", sans-serif;
color: white;
translate: calc(-50% + (var(--x) * -30px)) calc(var(--y) * -20px);
z-index: 4;
}
.content {
min-height: 32%;
position: absolute;
bottom: 0;
width: 100%;
color: white;
display: grid;
gap: 0.2rem;
place-items: center;
align-content: center;
padding-bottom: 0.5rem;
z-index: 3;
}
.content svg {
width: 20px;
}
.content p {
margin: 0;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 1.2rem;
position: relative;
}
.content p:first-of-type::after {
content: "";
position: absolute;
bottom: calc(100% + 1rem);
left: 50%;
width: 20ch;
background: white;
height: 1px;
translate: -50% 0;
}
.content p:last-of-type {
opacity: 0.8;
font-size: 0.8rem
}
.blur {
--layers: 5;
position: absolute;
inset: 0;
z-index: 1;
}
.blur .layer {
--blur: calc(sin(((var(--layers) - var(--index)) / var(--layers)) * 90deg) * 5);
--stop: calc(sin(((var(--index)) / var(--layers)) * 90deg) * 25);
position: absolute;
inset: 0;
background: hsl(0 0% 60% / 0.015);
backdrop-filter: blur(min(calc(var(--blur) * 1px), 4px));
mask: radial-gradient(180% 160% at 45% 90%,
#fff 10%,
#0000 calc((10 + var(--stop)) * 1%));
z-index: 2;
}
</style>
</head>
<body>
<article>
<div class="assets">
<img src="http://mattcannon.games/codepen/sweet-treats/bg.webp" alt="Background clouds" />
<h3>CUPCAKES</h3>
<img src="http://mattcannon.games/codepen/sweet-treats/cup-cake.png" alt="Cupcake"
style="width: 200px; height: 250px;" />
</div>
<div class="blur">
<div class="layer" style="--index:1;"></div>
<div class="layer" style="--index:2;"></div>
<div class="layer" style="--index:3;"></div>
<div class="layer" style="--index:4;"></div>
<div class="layer" style="--index:5;"></div>
</div>
<div class="content">
<p>
<i class="fas fa-map-marker-alt"></i>
Sweet Dreams Bakery
</p>
<p><i>Los Angeles, CA</i></p>
</div>
</article>
<script>
const UPDATE = ({ x, y }) => {
const xNorm = (x / window.innerWidth - 0.5) * 2;
const yNorm = (y / window.innerHeight - 0.5) * 2;
document.documentElement.style.setProperty("--x", xNorm);
document.documentElement.style.setProperty("--y", yNorm);
};
window.addEventListener("mousemove", UPDATE);
const handleOrientation = ({ beta, gamma }) => {
const isLandscape = window.matchMedia("(orientation: landscape)").matches;
const xVal = Math.max(
-1,
Math.min(1, isLandscape ? (beta || 0) / 45 : (gamma || 0) / 45)
);
const yVal = Math.max(
-1,
Math.min(1, isLandscape ? Math.abs(gamma || 0) / 45 : (beta || 0) / 45)
);
document.documentElement.style.setProperty("--x", xVal);
document.documentElement.style.setProperty("--y", yVal);
};
const START = () => {
if (DeviceOrientationEvent?.requestPermission) {
DeviceOrientationEvent.requestPermission().then((result) => {
if (result === "granted") {
window.addEventListener("deviceorientation", handleOrientation);
}
});
} else {
window.addEventListener("deviceorientation", handleOrientation);
}
};
document.body.addEventListener("click", START, { once: true });
</script>
</body>
</html>
HTML 结构
- 整个页面以一个卡片为中心,使用 article 标签作为主要容器。
- 卡片内部有三个主要部分:.assets、.blur 和.content。
- .assets 部分包含两张背景图片和标题文字。
- .blur 部分使用多个层创建模糊渐变效果。
- .content 部分显示店铺名称和位置信息。
CSS 关键部分
- 视差效果:通过--x 和--y 变量控制不同元素的移动速度,实现 3D 视差效果。
- 背景处理:使用多层背景图片叠加,结合 object-position 和 CSS 变量实现动态效果。
- 模糊渐变:.blur 类中的多个层使用 backdrop-filter: blur()和 mask 属性创建从中心到边缘的渐变模糊效果。
- 响应式设计:使用媒体查询处理不同屏幕方向的显示效果,确保在移动设备上也能良好展示。
- 变量定义:使用 CSS 变量存储视差位移值,方便 JavaScript 控制。
JavaScript 功能
- 鼠标跟踪:通过 mousemove 事件监听鼠标位置,计算并更新 CSS 变量--x 和--y。
- 设备方向支持:通过 deviceorientation 事件检测设备倾斜,实现移动设备上的视差效果。
- 权限处理:在 iOS 设备上,通过 DeviceOrientationEvent.requestPermission()方法请求设备方向权限。
- 归一化处理:将鼠标位置和设备方向数据归一化为 - 1 到 1 之间的值,确保视差效果在不同设备上的一致性。
各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!