网页预览
你可以先想象一下这个网页的样子:

(图片来源网络,侵删)
- 顶部:有一个导航栏,包含网站标题、菜单链接和一个购物车图标。
- 主体:
- 一个引人注目的英雄区域,展示主打甜品和一句欢迎语。
- 一个“精选甜品”部分,以卡片形式展示多种甜品,每个卡片都有图片、名称、描述、价格和“加入购物车”按钮。
- 一个“关于我们”部分,介绍甜品店的特色。
- 交互:点击“加入购物车”按钮,右上角的购物车图标会更新数量,并弹出提示。
- 底部:一个简单的页脚。
最终代码 (HTML, CSS, JS)
你可以直接复制以下所有代码,保存为一个 .html 文件(desserts.html),然后用浏览器打开它,就能看到完整效果了。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">甜蜜时刻 - 您的专属甜品天堂</title>
<style>
/* --- 全局样式和变量 --- */
:root {
--primary-color: #ff6b81;
--secondary-color: #ffd166;
--dark-color: #2d3436;
--light-color: #f8f9fa;
--text-color: #636e72;
--shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
color: var(--text-color);
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
h1, h2, h3 {
color: var(--dark-color);
margin-bottom: 1rem;
}
a {
text-decoration: none;
color: var(--primary-color);
}
img {
max-width: 100%;
height: auto;
display: block;
}
.btn {
display: inline-block;
background: var(--primary-color);
color: white;
padding: 12px 24px;
border: none;
border-radius: 50px;
cursor: pointer;
font-size: 1rem;
transition: all 0.3s ease;
text-align: center;
}
.btn:hover {
background: #ff5268;
transform: translateY(-2px);
box-shadow: var(--shadow);
}
/* --- 导航栏 --- */
.navbar {
background: white;
padding: 1rem 0;
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
box-shadow: var(--shadow);
}
.navbar .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.navbar .logo {
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
}
.navbar .nav-links {
list-style: none;
display: flex;
}
.navbar .nav-links li {
margin-left: 20px;
}
.navbar .nav-links a {
color: var(--dark-color);
font-weight: 500;
}
.cart-icon {
position: relative;
font-size: 1.5rem;
cursor: pointer;
}
.cart-count {
position: absolute;
top: -8px;
right: -8px;
background: var(--primary-color);
color: white;
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
font-weight: bold;
}
/* --- 主要内容区域 --- */
main {
margin-top: 80px; /* 为固定导航栏留出空间 */
}
/* --- 英雄区域 --- */
.hero {
background: linear-gradient(rgba(255, 107, 129, 0.8), rgba(255, 107, 129, 0.8)), url('https://images.unsplash.com/photo-1553279768-865429fa0078?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80') no-repeat center center/cover;
color: white;
text-align: center;
padding: 100px 20px;
}
.hero h1 {
font-size: 3rem;
margin-bottom: 1rem;
}
.hero p {
font-size: 1.2rem;
max-width: 600px;
margin: 0 auto 2rem;
}
/* --- 精选甜品 --- */
.desserts {
padding: 60px 0;
background: #f8f9fa;
}
.section-title {
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
}
.desserts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
}
.dessert-card {
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: var(--shadow);
transition: transform 0.3s ease;
}
.dessert-card:hover {
transform: translateY(-10px);
}
.dessert-card img {
height: 250px;
object-fit: cover;
}
.dessert-info {
padding: 20px;
}
.dessert-info h3 {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.dessert-info p {
color: var(--text-color);
margin-bottom: 1rem;
}
.dessert-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.price {
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
}
/* --- 关于我们 --- */
.about {
padding: 60px 0;
text-align: center;
}
.about p {
max-width: 800px;
margin: 0 auto 2rem;
font-size: 1.1rem;
}
/* --- 页脚 --- */
footer {
background: var(--dark-color);
color: white;
text-align: center;
padding: 20px;
}
/* --- 提示信息 --- */
.toast {
position: fixed;
bottom: 30px;
right: 30px;
background: var(--primary-color);
color: white;
padding: 15px 25px;
border-radius: 50px;
box-shadow: var(--shadow);
transform: translateY(100px);
opacity: 0;
transition: all 0.3s ease;
}
.toast.show {
transform: translateY(0);
opacity: 1;
}
/* --- 响应式设计 --- */
@media (max-width: 768px) {
.navbar .container {
flex-direction: column;
}
.navbar .nav-links {
margin-top: 1rem;
}
.hero h1 {
font-size: 2rem;
}
.desserts-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar">
<div class="container">
<a href="#" class="logo">🍰 甜蜜时刻</a>
<ul class="nav-links">
<li><a href="#home">首页</a></li>
<li><a href="#desserts">甜品</a></li>
<li><a href="#about">关于我们</a></li>
<li><a href="#contact">联系我们</a></li>
</ul>
<div class="cart-icon">
🛒
<span class="cart-count" id="cart-count">0</span>
</div>
</div>
</nav>
<main>
<!-- 英雄区域 -->
<section id="home" class="hero">
<div class="container">
<h1>每一口,都是幸福的味道</h1>
<p>我们用心烘焙,为您带来最新鲜、最美味的甜品,点亮您的每一天。</p>
<a href="#desserts" class="btn">探索甜品</a>
</div>
</section>
<!-- 精选甜品 -->
<section id="desserts" class="desserts">
<div class="container">
<h2 class="section-title">精选甜品</h2>
<div class="desserts-grid" id="desserts-grid">
<!-- 甜品卡片将通过JS动态生成 -->
</div>
</div>
</section>
<!-- 关于我们 -->
<section id="about" class="about">
<div class="container">
<h2 class="section-title">关于我们</h2>
<p>
甜蜜时刻始于2025年,由一位热爱烘焙的糕点师创立,我们相信,甜品不仅仅是食物,
它更是情感的传递和美好的回忆,我们坚持使用最优质的天然原料,
从源头把控品质,只为给您带来最纯粹、最安心的甜蜜体验。
</p>
<a href="#" class="btn">了解更多</a>
</div>
</section>
</main>
<!-- 页脚 -->
<footer>
<div class="container">
<p>© 2025 甜蜜时刻. All rights reserved. | Made with ❤️</p>
</div>
</footer>
<!-- 提示信息 -->
<div class="toast" id="toast">已加入购物车!</div>
<script>
// --- 甜品数据 ---
const desserts = [
{
id: 1,
name: '草莓芝士蛋糕',
description: '新鲜草莓与浓郁芝士的完美融合,酸甜可口,入口即化。',
price: 38,
image: 'https://images.unsplash.com/photo-1488477181946-6428a0291777?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80'
},
{
id: 2,
name: '巧克力熔岩蛋糕',
description: '温热的巧克力蛋糕,切开时中心如熔岩般流淌,是巧克力爱好者的终极梦想。',
price: 42,
image: 'https://images.unsplash.com/photo-1567620905732-2d1ec7ab7445?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80'
},
{
id: 3,
name: '提拉米苏',
description: '经典意式甜品,咖啡的微苦与马斯卡彭奶酪的醇厚交织,层次丰富。',
price: 45,
image: 'https://images.unsplash.com/photo-1505252585461-04db1eb84625?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80'
},
{
id: 4,
name: '芒果千层蛋糕',
description: '层层叠叠的薄饼与香甜的芒果奶油,热带风情,清新不腻。',
price: 48,
image: 'https://images.unsplash.com/photo-1559056199-641a0ac8b55e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80'
},
{
id: 5,
name: '抹茶红豆千层',
description: '日式经典,抹茶的微苦与红豆的香甜,带来宁静而满足的味蕾体验。',
price: 40,
image: 'https://images.unsplash.com/photo-1576107616104-496e48092fac?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80'
},
{
id: 6,
name: '法式马卡龙礼盒',
description: '色彩缤纷的法式小圆饼,酥脆外壳,柔软内馅,是精致的午后茶点。',
price: 68,
image: 'https://images.unsplash.com/photo-1603133872878-684f208fb84b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80'
}
];
// --- 购物车状态 ---
let cart = [];
// --- DOM 元素 ---
const dessertsGrid = document.getElementById('desserts-grid');
const cartCountElement = document.getElementById('cart-count');
const toast = document.getElementById('toast');
// --- 渲染甜品列表 ---
function renderDesserts() {
dessertsGrid.innerHTML = desserts.map(dessert => `
<div class="dessert-card">
<img src="${dessert.image}" alt="${dessert.name}">
<div class="dessert-info">
<h3>${dessert.name}</h3>
<p>${dessert.description}</p>
<div class="dessert-footer">
<span class="price">¥${dessert.price}</span>
<button class="btn add-to-cart-btn" data-id="${dessert.id}">加入购物车</button>
</div>
</div>
</div>
`).join('');
// 为所有“加入购物车”按钮添加点击事件
document.querySelectorAll('.add-to-cart-btn').forEach(button => {
button.addEventListener('click', (e) => {
const dessertId = parseInt(e.target.getAttribute('data-id'));
addToCart(dessertId);
});
});
}
// --- 添加到购物车 ---
function addToCart(dessertId) {
const dessert = desserts.find(d => d.id === dessertId);
if (dessert) {
cart.push(dessert);
updateCartCount();
showToast(`${dessert.name} 已加入购物车!`);
}
}
// --- 更新购物车数量 ---
function updateCartCount() {
cartCountElement.textContent = cart.length;
}
// --- 显示提示信息 ---
function showToast(message) {
toast.textContent = message;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, 3000); // 3秒后自动隐藏
}
// --- 初始化页面 ---
renderDesserts();
</script>
</body>
</html>
代码结构解析
-
HTML 结构 (
<body>部分)<nav>: 导航栏,包含Logo、菜单链接和购物车图标,购物车图标里有一个<span>用于显示商品数量。<main>: 网页的主体内容。<section class="hero">: 首页的欢迎横幅。<section class="desserts">: 展示甜品的核心区域,里面的<div class="desserts-grid">是一个容器,我们通过JS动态地把甜品卡片放进去。<section class="about">: 关于我们的介绍。
<footer>: 页脚。<div class="toast">: 用于显示“已加入购物车”等提示信息,默认是隐藏的。
-
CSS 样式 (
<style>部分)root: 定义了全局的CSS变量,方便统一管理颜色、阴影等,修改起来非常方便。.navbar: 导航栏的样式,设置了position: fixed让它固定在页面顶部。.hero: 英雄区域的样式,使用了background: linear-gradient和background-image创建了一个带图片和遮罩的背景。.desserts-grid: 使用了display: grid布局,这是一个非常现代和强大的布局工具。repeat(auto-fit, minmax(300px, 1fr))的意思是让卡片自动换行,并且每个卡片的宽度至少为300px,最大可以占据一整行,这使得页面在不同屏幕尺寸下都能很好地自适应。.dessert-card: 单个甜品卡片的样式,添加了box-shadow和hover效果,让卡片看起来更立体,鼠标悬停时有轻微上浮的动画。.toast: 提示信息的样式,通过transform和opacity实现了滑入滑出的动画效果。@media (max-width: 768px): 媒体查询,当屏幕宽度小于768px(如手机)时,应用这里的样式,比如让导航栏和甜品网格变为单列布局,以获得更好的移动端体验。
-
JavaScript 交互 (
<script>部分)desserts数组: 存储了所有甜品的数据,包括ID、名称、描述、价格和图片链接,这样做的好处是数据和表现分离,以后想修改或增加甜品,只需要修改这个数组即可。cart数组: 用来存储已经加入购物车的商品。renderDesserts()函数: 这个函数是核心,它遍历desserts数组,为每个甜品生成一个HTML卡片字符串,然后把这些字符串拼接起来,最后通过innerHTML放到desserts-grid容器里,它还为每个“加入购物车”按钮绑定了点击事件。addToCart(dessertId)函数: 当点击“加入购物车”按钮时触发,它根据ID找到对应的甜品,将其添加到cart数组中,然后调用updateCartCount()更新购物车图标上的数字,并调用showToast()显示提示。updateCartCount()和showToast(): 这两个是辅助函数,分别用于更新UI上的购物车数量和显示提示信息。renderDesserts(): 在页面加载时调用一次,负责初始化甜品列表。
这个例子从零开始,为你构建了一个功能完整、视觉美观的甜品网页,并详细解释了每一部分的作用,你可以基于这个代码进行修改和扩展,比如添加真正的购物车结算页面、筛选功能等。
