实践项目
2025年3月2日大约 29 分钟
实践项目
通过实际项目来应用所学的CSS知识是巩固技能的最佳方式。本章提供了几个实践项目,帮助你综合运用CSS技能。
项目一:创建精美的信纸
这个项目将指导你创建一个具有精美背景、边框和排版的信纸设计。
项目目标
- 创建一个优雅的信纸设计
- 应用背景图案和边框
- 实现精美的排版
- 添加装饰元素
步骤指南
1. 创建基本HTML结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>精美信纸</title>
<link rel="stylesheet" href="stationery.css">
</head>
<body>
<div class="stationery">
<div class="header">
<h1>优雅信纸</h1>
</div>
<div class="content">
<p class="date">2023年10月15日</p>
<p class="greeting">亲爱的朋友:</p>
<p>很高兴能够给你写这封信。这是一个使用CSS设计的精美信纸模板,展示了我们所学的各种CSS技术。</p>
<p>在这个项目中,我们应用了:</p>
<ul>
<li>精美的背景和边框</li>
<li>优雅的排版</li>
<li>装饰性元素</li>
<li>响应式设计</li>
</ul>
<p>希望你喜欢这个设计!</p>
<p class="closing">此致</p>
<p class="signature">敬礼</p>
<p class="sender">CSS学习者</p>
</div>
<div class="footer">
<div class="decoration"></div>
</div>
</div>
</body>
</html>
2. 创建CSS样式
/* 基本样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Times New Roman', Times, serif;
background-color: #f5f5f5;
color: #333;
line-height: 1.6;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* 信纸容器 */
.stationery {
width: 100%;
max-width: 800px;
background-color: #fff;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
/* 背景图案 */
.stationery::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(circle at 50px 50px, #f9f9f9 10px, transparent 10px),
radial-gradient(circle at 150px 150px, #f9f9f9 10px, transparent 10px),
radial-gradient(circle at 250px 250px, #f9f9f9 10px, transparent 10px);
background-size: 300px 300px;
opacity: 0.3;
z-index: 0;
}
/* 信纸边框 */
.stationery::after {
content: '';
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border: 1px solid #ddd;
border-radius: 2px;
z-index: 0;
}
/* 信纸头部 */
.header {
text-align: center;
padding: 40px 20px 20px;
position: relative;
z-index: 1;
}
.header h1 {
font-family: 'Brush Script MT', cursive;
font-size: 2.5rem;
color: #8b4513;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
letter-spacing: 2px;
}
/* 信纸内容 */
.content {
padding: 20px 50px 40px;
position: relative;
z-index: 1;
}
.date {
text-align: right;
margin-bottom: 30px;
font-style: italic;
}
.greeting {
margin-bottom: 20px;
font-weight: bold;
}
p {
margin-bottom: 15px;
text-align: justify;
}
ul {
margin: 15px 0 15px 20px;
}
li {
margin-bottom: 5px;
}
.closing {
margin-top: 30px;
text-align: right;
}
.signature {
text-align: right;
font-family: 'Brush Script MT', cursive;
font-size: 1.5rem;
color: #8b4513;
margin: 5px 0;
}
.sender {
text-align: right;
font-weight: bold;
}
/* 信纸页脚 */
.footer {
padding: 20px;
position: relative;
z-index: 1;
}
.decoration {
height: 20px;
background-image: repeating-linear-gradient(
45deg,
#8b4513,
#8b4513 10px,
transparent 10px,
transparent 20px
);
opacity: 0.3;
border-radius: 2px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.content {
padding: 20px 30px;
}
.header h1 {
font-size: 2rem;
}
.signature {
font-size: 1.2rem;
}
}
@media (max-width: 480px) {
.content {
padding: 15px 20px;
}
.header h1 {
font-size: 1.8rem;
}
}
3. 效果展示

扩展挑战
- 尝试添加水印效果
- 实现不同的信纸主题(如复古、现代、节日等)
- 添加可打印样式表,使信纸可以漂亮地打印出来
项目二:响应式产品展示页
这个项目将帮助你创建一个响应式的产品展示页面,适用于电子商务网站。
项目目标
- 创建响应式产品网格布局
- 实现产品卡片设计
- 添加悬停效果和动画
- 实现筛选和排序功能
步骤指南
1. 创建HTML结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>产品展示页</title>
<link rel="stylesheet" href="products.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
</head>
<body>
<header>
<div class="container">
<h1>精选产品</h1>
<div class="filters">
<div class="search">
<input type="text" placeholder="搜索产品...">
<button><i class="fas fa-search"></i></button>
</div>
<div class="sort">
<label for="sort-select">排序方式:</label>
<select id="sort-select">
<option value="popular">热门</option>
<option value="newest">最新</option>
<option value="price-low">价格从低到高</option>
<option value="price-high">价格从高到低</option>
</select>
</div>
<div class="category-filter">
<button class="filter-btn active" data-category="all">全部</button>
<button class="filter-btn" data-category="electronics">电子产品</button>
<button class="filter-btn" data-category="clothing">服装</button>
<button class="filter-btn" data-category="home">家居</button>
</div>
</div>
</div>
</header>
<main>
<div class="container">
<div class="products-grid">
<!-- 产品1 -->
<div class="product-card" data-category="electronics">
<div class="badge">新品</div>
<div class="product-image">
<img src="https://via.placeholder.com/300x300" alt="智能手表">
<div class="product-actions">
<button class="action-btn"><i class="fas fa-heart"></i></button>
<button class="action-btn"><i class="fas fa-shopping-cart"></i></button>
<button class="action-btn"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="product-info">
<h3>智能手表</h3>
<div class="rating">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i>
<span>(120)</span>
</div>
<div class="price">
<span class="current">¥899</span>
<span class="original">¥1299</span>
<span class="discount">-30%</span>
</div>
</div>
</div>
<!-- 产品2 -->
<div class="product-card" data-category="clothing">
<div class="product-image">
<img src="https://via.placeholder.com/300x300" alt="休闲夹克">
<div class="product-actions">
<button class="action-btn"><i class="fas fa-heart"></i></button>
<button class="action-btn"><i class="fas fa-shopping-cart"></i></button>
<button class="action-btn"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="product-info">
<h3>休闲夹克</h3>
<div class="rating">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="far fa-star"></i>
<span>(85)</span>
</div>
<div class="price">
<span class="current">¥399</span>
</div>
</div>
</div>
<!-- 产品3 -->
<div class="product-card" data-category="home">
<div class="badge">热卖</div>
<div class="product-image">
<img src="https://via.placeholder.com/300x300" alt="智能台灯">
<div class="product-actions">
<button class="action-btn"><i class="fas fa-heart"></i></button>
<button class="action-btn"><i class="fas fa-shopping-cart"></i></button>
<button class="action-btn"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="product-info">
<h3>智能台灯</h3>
<div class="rating">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<span>(210)</span>
</div>
<div class="price">
<span class="current">¥199</span>
<span class="original">¥299</span>
<span class="discount">-33%</span>
</div>
</div>
</div>
<!-- 产品4 -->
<div class="product-card" data-category="electronics">
<div class="product-image">
<img src="https://via.placeholder.com/300x300" alt="无线耳机">
<div class="product-actions">
<button class="action-btn"><i class="fas fa-heart"></i></button>
<button class="action-btn"><i class="fas fa-shopping-cart"></i></button>
<button class="action-btn"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="product-info">
<h3>无线耳机</h3>
<div class="rating">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i>
<i class="far fa-star"></i>
<span>(67)</span>
</div>
<div class="price">
<span class="current">¥499</span>
</div>
</div>
</div>
<!-- 更多产品... -->
</div>
</div>
</main>
<footer>
<div class="container">
<p>© 2023 产品展示页面 - CSS实践项目</p>
</div>
</footer>
<script src="products.js"></script>
</body>
</html>
2. 创建CSS样式
/* 基本样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f8f9fa;
color: #333;
line-height: 1.6;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 0 15px;
}
/* 头部样式 */
header {
background-color: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 20px 0;
margin-bottom: 30px;
}
header h1 {
margin-bottom: 20px;
color: #333;
font-size: 2rem;
}
.filters {
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: center;
justify-content: space-between;
}
.search {
display: flex;
flex: 1;
max-width: 400px;
}
.search input {
flex: 1;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
font-size: 1rem;
}
.search button {
background-color: #4CAF50;
color: white;
border: none;
padding: 0 15px;
border-radius: 0 4px 4px 0;
cursor: pointer;
}
.sort {
display: flex;
align-items: center;
gap: 10px;
}
.sort select {
padding: 8px 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 0.9rem;
}
.category-filter {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
width: 100%;
}
.filter-btn {
padding: 8px 15px;
background-color: #f1f1f1;
border: none;
border-radius: 20px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-btn:hover {
background-color: #e0e0e0;
}
.filter-btn.active {
background-color: #4CAF50;
color: white;
}
/* 产品网格 */
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 25px;
margin-bottom: 40px;
}
/* 产品卡片 */
.product-card {
background-color: white;
border-radius: 8px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
position: relative;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.badge {
position: absolute;
top: 10px;
right: 10px;
background-color: #ff6b6b;
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 0.8rem;
z-index: 1;
}
.product-image {
position: relative;
overflow: hidden;
}
.product-image img {
width: 100%;
height: 250px;
object-fit: cover;
transition: transform 0.5s ease;
}
.product-card:hover .product-image img {
transform: scale(1.05);
}
.product-actions {
position: absolute;
bottom: -50px;
left: 0;
right: 0;
display: flex;
justify-content: center;
gap: 10px;
padding: 10px;
background-color: rgba(255, 255, 255, 0.9);
transition: bottom 0.3s ease;
}
.product-card:hover .product-actions {
bottom: 0;
}
.action-btn {
width: 35px;
height: 35px;
border-radius: 50%;
background-color: white;
border: 1px solid #ddd;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.action-btn:hover {
background-color: #4CAF50;
color: white;
border-color: #4CAF50;
}
.product-info {
padding: 15px;
}
.product-info h3 {
margin-bottom: 10px;
font-size: 1.1rem;
}
.rating {
display: flex;
align-items: center;
margin-bottom: 10px;
color: #ffc107;
}
.rating span {
color: #666;
margin-left: 5px;
font-size: 0.9rem;
}
.price {
display: flex;
align-items: center;
gap: 10px;
}
.current {
font-weight: bold;
font-size: 1.2rem;
color: #4CAF50;
}
.original {
text-decoration: line-through;
color: #999;
font-size: 0.9rem;
}
.discount {
background-color: #4CAF50;
color: white;
padding: 2px 5px;
border-radius: 3px;
font-size: 0.8rem;
}
/* 页脚 */
footer {
background-color: #333;
color: white;
padding: 20px 0;
text-align: center;
}
/* 响应式设计 */
@media (max-width: 768px) {
.filters {
flex-direction: column;
align-items: flex-start;
}
.search, .sort {
width: 100%;
max-width: none;
}
.products-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
}
@media (max-width: 576px) {
.products-grid {
grid-template-columns: 1fr;
}
.product-image img {
height: 200px;
}
}
3. 创建JavaScript功能
// products.js
document.addEventListener('DOMContentLoaded', function() {
// 筛选功能
const filterButtons = document.querySelectorAll('.filter-btn');
const productCards = document.querySelectorAll('.product-card');
filterButtons.forEach(button => {
button.addEventListener('click', function() {
// 更新活动按钮
filterButtons.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
const category = this.getAttribute('data-category');
// 筛选产品
productCards.forEach(card => {
if (category === 'all' || card.getAttribute('data-category') === category) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
});
});
// 搜索功能
const searchInput = document.querySelector('.search input');
const searchButton = document.querySelector('.search button');
function performSearch() {
const searchTerm = searchInput.value.toLowerCase().trim();
productCards.forEach(card => {
const productName = card.querySelector('h3').textContent.toLowerCase();
if (productName.includes(searchTerm)) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
}
searchButton.addEventListener('click', performSearch);
searchInput.addEventListener('keyup', function(e) {
if (e.key === 'Enter') {
performSearch();
}
});
// 排序功能
const sortSelect = document.getElementById('sort-select');
sortSelect.addEventListener('change', function() {
const sortValue = this.value;
const productsGrid = document.querySelector('.products-grid');
const productsArray = Array.from(productCards);
productsArray.sort((a, b) => {
if (sortValue === 'price-low') {
const priceA = parseFloat(a.querySelector('.current').textContent.replace('¥', ''));
const priceB = parseFloat(b.querySelector('.current').textContent.replace('¥', ''));
return priceA - priceB;
} else if (sortValue === 'price-high') {
const priceA = parseFloat(a.querySelector('.current').textContent.replace('¥', ''));
const priceB = parseFloat(b.querySelector('.current').textContent.replace('¥', ''));
return priceB - priceA;
}
// 其他排序方式可以根据需要添加
return 0;
});
// 重新添加排序后的产品
productsArray.forEach(product => {
productsGrid.appendChild(product);
});
});
});
4. 效果展示

扩展挑战
- 添加产品详情页面
- 实现购物车功能
- 添加产品图片轮播
- 实现产品比较功能
项目三:个人作品集网站
这个项目将帮助你创建一个展示个人作品的响应式作品集网站。
项目目标
- 创建一个专业的个人作品集网站
- 实现响应式设计
- 添加作品展示区域
- 实现平滑滚动和动画效果
步骤指南
1. 创建HTML结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>个人作品集</title>
<link rel="stylesheet" href="portfolio.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar">
<div class="container">
<div class="logo">
<a href="#">张三的作品集</a>
</div>
<div class="nav-toggle">
<span></span>
<span></span>
<span></span>
</div>
<ul class="nav-menu">
<li><a href="#home" class="active">首页</a></li>
<li><a href="#about">关于我</a></li>
<li><a href="#portfolio">作品集</a></li>
<li><a href="#services">服务</a></li>
<li><a href="#contact">联系我</a></li>
</ul>
</div>
</nav>
<!-- 首页部分 -->
<section id="home" class="hero">
<div class="container">
<div class="hero-content">
<h1>你好,我是<span>张三</span></h1>
<h2>UI/UX设计师 & 前端开发者</h2>
<p>我专注于创建美观且用户友好的数字体验</p>
<div class="hero-buttons">
<a href="#portfolio" class="btn primary-btn">查看作品</a>
<a href="#contact" class="btn secondary-btn">联系我</a>
</div>
<div class="social-icons">
<a href="#"><i class="fab fa-github"></i></a>
<a href="#"><i class="fab fa-linkedin"></i></a>
<a href="#"><i class="fab fa-dribbble"></i></a>
<a href="#"><i class="fab fa-behance"></i></a>
</div>
</div>
<div class="hero-image">
<img src="https://via.placeholder.com/500x600" alt="张三的照片">
<div class="shape"></div>
</div>
</div>
</section>
<!-- 关于我部分 -->
<section id="about" class="about">
<div class="container">
<div class="section-header">
<h2>关于我</h2>
<p>了解我的技能和经验</p>
</div>
<div class="about-content">
<div class="about-image">
<img src="https://via.placeholder.com/400x500" alt="关于我">
</div>
<div class="about-text">
<h3>UI/UX设计师 & 前端开发者</h3>
<p>我是一名热爱创造的设计师和开发者,拥有5年的行业经验。我专注于创建美观且用户友好的数字体验,帮助企业实现其目标。</p>
<div class="skills">
<div class="skill-item">
<div class="skill-name">
<span>UI/UX设计</span>
<span>90%</span>
</div>
<div class="skill-bar">
<div class="skill-progress" style="width: 90%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-name">
<span>HTML/CSS</span>
<span>95%</span>
</div>
<div class="skill-bar">
<div class="skill-progress" style="width: 95%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-name">
<span>JavaScript</span>
<span>85%</span>
</div>
<div class="skill-bar">
<div class="skill-progress" style="width: 85%"></div>
</div>
</div>
<div class="skill-item">
<div class="skill-name">
<span>React</span>
<span>80%</span>
</div>
<div class="skill-bar"><div class="skill-progress" style="width: 80%"></div>
</div>
</div>
</div>
<div class="about-info">
<div class="info-item">
<span class="info-title">姓名:</span>
<span class="info-value">张三</span>
</div>
<div class="info-item">
<span class="info-title">邮箱:</span>
<span class="info-value">zhangsan@example.com</span>
</div>
<div class="info-item">
<span class="info-title">电话:</span>
<span class="info-value">+86 123 4567 8910</span>
</div>
<div class="info-item">
<span class="info-title">地址:</span>
<span class="info-value">北京市朝阳区</span>
</div>
</div>
<a href="#" class="btn primary-btn">下载简历</a>
</div>
</div>
</div>
</section>
<!-- 作品集部分 -->
<section id="portfolio" class="portfolio">
<div class="container">
<div class="section-header">
<h2>我的作品集</h2>
<p>查看我最近的项目</p>
</div>
<div class="portfolio-filter">
<button class="filter-btn active" data-filter="all">全部</button>
<button class="filter-btn" data-filter="web">网页设计</button>
<button class="filter-btn" data-filter="app">应用设计</button>
<button class="filter-btn" data-filter="graphic">平面设计</button>
</div>
<div class="portfolio-grid">
<div class="portfolio-item" data-category="web">
<div class="portfolio-image">
<img src="https://via.placeholder.com/600x400" alt="项目1">
<div class="portfolio-overlay">
<div class="portfolio-info">
<h3>电子商务网站</h3>
<p>网页设计</p>
<a href="#" class="portfolio-link"><i class="fas fa-link"></i></a>
<a href="#" class="portfolio-zoom"><i class="fas fa-search"></i></a>
</div>
</div>
</div>
</div>
<div class="portfolio-item" data-category="app">
<div class="portfolio-image">
<img src="https://via.placeholder.com/600x400" alt="项目2">
<div class="portfolio-overlay">
<div class="portfolio-info">
<h3>健身应用</h3>
<p>应用设计</p>
<a href="#" class="portfolio-link"><i class="fas fa-link"></i></a>
<a href="#" class="portfolio-zoom"><i class="fas fa-search"></i></a>
</div>
</div>
</div>
</div>
<div class="portfolio-item" data-category="graphic">
<div class="portfolio-image">
<img src="https://via.placeholder.com/600x400" alt="项目3">
<div class="portfolio-overlay">
<div class="portfolio-info">
<h3>品牌标识</h3>
<p>平面设计</p>
<a href="#" class="portfolio-link"><i class="fas fa-link"></i></a>
<a href="#" class="portfolio-zoom"><i class="fas fa-search"></i></a>
</div>
</div>
</div>
</div>
<div class="portfolio-item" data-category="web">
<div class="portfolio-image">
<img src="https://via.placeholder.com/600x400" alt="项目4">
<div class="portfolio-overlay">
<div class="portfolio-info">
<h3>企业网站</h3>
<p>网页设计</p>
<a href="#" class="portfolio-link"><i class="fas fa-link"></i></a>
<a href="#" class="portfolio-zoom"><i class="fas fa-search"></i></a>
</div>
</div>
</div>
</div>
<div class="portfolio-item" data-category="app">
<div class="portfolio-image">
<img src="https://via.placeholder.com/600x400" alt="项目5">
<div class="portfolio-overlay">
<div class="portfolio-info">
<h3>旅行应用</h3>
<p>应用设计</p>
<a href="#" class="portfolio-link"><i class="fas fa-link"></i></a>
<a href="#" class="portfolio-zoom"><i class="fas fa-search"></i></a>
</div>
</div>
</div>
</div>
<div class="portfolio-item" data-category="graphic">
<div class="portfolio-image">
<img src="https://via.placeholder.com/600x400" alt="项目6">
<div class="portfolio-overlay">
<div class="portfolio-info">
<h3>宣传海报</h3>
<p>平面设计</p>
<a href="#" class="portfolio-link"><i class="fas fa-link"></i></a>
<a href="#" class="portfolio-zoom"><i class="fas fa-search"></i></a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 联系部分 -->
<section id="contact" class="contact">
<div class="container">
<div class="section-header">
<h2>联系我</h2>
<p>随时与我取得联系</p>
</div>
<div class="contact-content">
<div class="contact-info">
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-map-marker-alt"></i>
</div>
<div class="contact-details">
<h3>地址</h3>
<p>北京市朝阳区</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-envelope"></i>
</div>
<div class="contact-details">
<h3>邮箱</h3>
<p>zhangsan@example.com</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-phone-alt"></i>
</div>
<div class="contact-details">
<h3>电话</h3>
<p>+86 123 4567 8910</p>
</div>
</div>
</div>
<form class="contact-form">
<div class="form-group">
<input type="text" placeholder="您的姓名" required>
</div>
<div class="form-group">
<input type="email" placeholder="您的邮箱" required>
</div>
<div class="form-group">
<input type="text" placeholder="主题">
</div>
<div class="form-group">
<textarea placeholder="您的留言" rows="5" required></textarea>
</div>
<button type="submit" class="btn primary-btn">发送留言</button>
</form>
</div>
</div>
</section>
<!-- 页脚 -->
<footer>
<div class="container">
<div class="footer-content">
<p>© 2023 张三的作品集. 保留所有权利.</p>
<div class="social-icons">
<a href="#"><i class="fab fa-github"></i></a>
<a href="#"><i class="fab fa-linkedin"></i></a>
<a href="#"><i class="fab fa-dribbble"></i></a>
<a href="#"><i class="fab fa-behance"></i></a>
</div>
</div>
</div>
</footer>
<script src="portfolio.js"></script>
</body>
</html>
2. 创建CSS样式
/* 基本样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Poppins', sans-serif;
background-color: #f9f9f9;
color: #333;
line-height: 1.6;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 0 15px;
}
section {
padding: 80px 0;
}
.section-header {
text-align: center;
margin-bottom: 50px;
}
.section-header h2 {
font-size: 2.5rem;
margin-bottom: 10px;
position: relative;
display: inline-block;
}
.section-header h2::after {
content: '';
position: absolute;
width: 50px;
height: 3px;
background-color: #4CAF50;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
}
.section-header p {
color: #777;
}
.btn {
display: inline-block;
padding: 12px 30px;
border-radius: 30px;
text-decoration: none;
font-weight: 500;
transition: all 0.3s ease;
cursor: pointer;
border: none;
font-size: 1rem;
}
.primary-btn {
background-color: #4CAF50;
color: white;
}
.primary-btn:hover {
background-color: #45a049;
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.secondary-btn {
background-color: transparent;
color: #333;
border: 2px solid #4CAF50;
}
.secondary-btn:hover {
background-color: #4CAF50;
color: white;
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
/* 导航栏样式 */
.navbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
z-index: 1000;
padding: 15px 0;
transition: all 0.3s ease;
}
.navbar .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo a {
font-size: 1.5rem;
font-weight: 700;
color: #333;
text-decoration: none;
}
.nav-menu {
display: flex;
list-style: none;
}
.nav-menu li {
margin-left: 30px;
}
.nav-menu a {
color: #333;
text-decoration: none;
font-weight: 500;
transition: color 0.3s ease;
position: relative;
}
.nav-menu a:hover, .nav-menu a.active {
color: #4CAF50;
}
.nav-menu a::after {
content: '';
position: absolute;
width: 0;
height: 2px;
background-color: #4CAF50;
bottom: -5px;
left: 0;
transition: width 0.3s ease;
}
.nav-menu a:hover::after, .nav-menu a.active::after {
width: 100%;
}
.nav-toggle {
display: none;
cursor: pointer;
}
.nav-toggle span {
display: block;
width: 25px;
height: 3px;
background-color: #333;
margin: 5px 0;
transition: all 0.3s ease;
}
/* 首页部分样式 */
.hero {
padding: 150px 0 80px;
background-color: #f9f9f9;
overflow: hidden;
}
.hero .container {
display: flex;
align-items: center;
justify-content: space-between;
}
.hero-content {
flex: 1;
padding-right: 30px;
}
.hero-content h1 {
font-size: 3rem;
margin-bottom: 10px;
line-height: 1.2;
}
.hero-content h1 span {
color: #4CAF50;
}
.hero-content h2 {
font-size: 1.5rem;
color: #777;
margin-bottom: 20px;
}
.hero-content p {
margin-bottom: 30px;
color: #555;
}
.hero-buttons {
display: flex;
gap: 15px;
margin-bottom: 30px;
}
.social-icons {
display: flex;
gap: 15px;
}
.social-icons a {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
background-color: white;
color: #333;
border-radius: 50%;
text-decoration: none;
transition: all 0.3s ease;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
.social-icons a:hover {
background-color: #4CAF50;
color: white;
transform: translateY(-3px);
}
.hero-image {
flex: 1;
position: relative;
}
.hero-image img {
width: 100%;
max-width: 450px;
border-radius: 20px;
position: relative;
z-index: 1;
}
.shape {
position: absolute;
width: 100%;
height: 100%;
background-color: #4CAF50;
border-radius: 20px;
top: 20px;
left: 20px;
z-index: 0;
}
/* 关于我部分样式 */
.about {
background-color: white;
}
.about-content {
display: flex;
flex-wrap: wrap;
gap: 40px;
align-items: center;
}
.about-image {
flex: 1;
min-width: 300px;
}
.about-image img {
width: 100%;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.about-text {
flex: 1;
min-width: 300px;
}
.about-text h3 {
font-size: 1.8rem;
margin-bottom: 15px;
color: #333;
}
.about-text p {
margin-bottom: 20px;
color: #666;
}
.skills {
margin: 30px 0;
}
.skill-item {
margin-bottom: 15px;
}
.skill-name {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
}
.skill-bar {
height: 10px;
background-color: #f1f1f1;
border-radius: 5px;
overflow: hidden;
}
.skill-progress {
height: 100%;
background-color: #4CAF50;
border-radius: 5px;
}
.about-info {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
margin: 30px 0;
}
.info-item {
display: flex;
gap: 10px;
}
.info-title {
font-weight: bold;
color: #333;
}
.info-value {
color: #666;
}
/* 作品集部分样式 */
.portfolio {
background-color: #f9f9f9;
}
.portfolio-filter {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 30px;
}
.filter-btn {
padding: 8px 20px;
background-color: white;
border: none;
border-radius: 30px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 0.9rem;
}
.filter-btn:hover, .filter-btn.active {
background-color: #4CAF50;
color: white;
}
.portfolio-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 25px;
}
.portfolio-item {
border-radius: 10px;
overflow: hidden;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
background-color: white;
}
.portfolio-image {
position: relative;
overflow: hidden;
}
.portfolio-image img {
width: 100%;
height: 250px;
object-fit: cover;
transition: transform 0.5s ease;
}
.portfolio-item:hover .portfolio-image img {
transform: scale(1.1);
}
.portfolio-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(76, 175, 80, 0.9);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.portfolio-item:hover .portfolio-overlay {
opacity: 1;
}
.portfolio-info {
text-align: center;
color: white;
}
.portfolio-info h3 {
font-size: 1.3rem;
margin-bottom: 5px;
}
.portfolio-info p {
margin-bottom: 15px;
font-size: 0.9rem;
}
.portfolio-link, .portfolio-zoom {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
background-color: white;
color: #333;
border-radius: 50%;
margin: 0 5px;
text-decoration: none;
transition: all 0.3s ease;
}
.portfolio-link:hover, .portfolio-zoom:hover {
background-color: #333;
color: white;
}
/* 联系部分样式 */
.contact {
background-color: white;
}
.contact-content {
display: flex;
flex-wrap: wrap;
gap: 40px;
}
.contact-info {
flex: 1;
min-width: 300px;
}
.contact-item {
display: flex;
align-items: flex-start;
margin-bottom: 30px;
}
.contact-icon {
width: 50px;
height: 50px;
background-color: #4CAF50;
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
font-size: 1.2rem;
}
.contact-details h3 {
font-size: 1.2rem;
margin-bottom: 5px;
}
.contact-details p {
color: #666;
}
.contact-form {
flex: 1;
min-width: 300px;
}
.form-group {
margin-bottom: 20px;
}
.form-group input, .form-group textarea {
width: 100%;
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 1rem;
transition: border-color 0.3s ease;
}
.form-group input:focus, .form-group textarea:focus {
border-color: #4CAF50;
outline: none;
}
/* 页脚样式 */
footer {
background-color: #333;
color: white;
padding: 30px 0;
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
/* 响应式设计 */
@media (max-width: 992px) {
.hero .container {
flex-direction: column;
text-align: center;
}
.hero-content {
padding-right: 0;
margin-bottom: 50px;
}
.hero-buttons {
justify-content: center;
}
.social-icons {
justify-content: center;
}
.about-content {
flex-direction: column;
}
.about-image {
margin-bottom: 30px;
}
}
@media (max-width: 768px) {
.nav-menu {
position: fixed;
top: 70px;
left: -100%;
width: 100%;
height: calc(100vh - 70px);
background-color: white;
flex-direction: column;
align-items: center;
padding: 40px 0;
transition: left 0.3s ease;
}
.nav-menu.active {
left: 0;
}
.nav-menu li {
margin: 15px 0;
}
.nav-toggle {
display: block;
}
.portfolio-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.footer-content {
flex-direction: column;
text-align: center;
}
}
@media (max-width: 576px) {
.section-header h2 {
font-size: 2rem;
}
.hero-content h1 {
font-size: 2.5rem;
}
.hero-buttons {
flex-direction: column;
gap: 10px;
}
.portfolio-grid {
grid-template-columns: 1fr;
}
}
3. 创建JavaScript功能
// portfolio.js
document.addEventListener('DOMContentLoaded', function() {
// 导航菜单切换
const navToggle = document.querySelector('.nav-toggle');
const navMenu = document.querySelector('.nav-menu');
navToggle.addEventListener('click', function() {
navMenu.classList.toggle('active');
// 汉堡菜单动画
const spans = this.querySelectorAll('span');
spans[0].classList.toggle('rotate-45');
spans[1].classList.toggle('opacity-0');
spans[2].classList.toggle('rotate-negative-45');
});
// 导航链接点击事件
const navLinks = document.querySelectorAll('.nav-menu a');
navLinks.forEach(link => {
link.addEventListener('click', function() {
// 移除所有链接的active类
navLinks.forEach(link => link.classList.remove('active'));
// 添加active类到当前点击的链接
this.classList.add('active');
// 如果在移动设备上,点击链接后关闭菜单
if (window.innerWidth <= 768) {
navMenu.classList.remove('active');
const spans = navToggle.querySelectorAll('span');
spans[0].classList.remove('rotate-45');
spans[1].classList.remove('opacity-0');
spans[2].classList.remove('rotate-negative-45');
}
});
});
// 作品集筛选功能
const filterButtons = document.querySelectorAll('.portfolio-filter .filter-btn');
const portfolioItems = document.querySelectorAll('.portfolio-item');
filterButtons.forEach(button => {
button.addEventListener('click', function() {
// 更新活动按钮
filterButtons.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
const filter = this.getAttribute('data-filter');
// 筛选作品
portfolioItems.forEach(item => {
if (filter === 'all' || item.getAttribute('data-category') === filter) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
});
});
// 滚动时导航栏样式变化
window.addEventListener('scroll', function() {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 50) {
navbar.style.padding = '10px 0';
navbar.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.1)';
} else {
navbar.style.padding = '15px 0';
navbar.style.boxShadow = 'none';
}
});
// 滚动时更新活动导航链接
window.addEventListener('scroll', function() {
const sections = document.querySelectorAll('section');
sections.forEach(section => {
const sectionTop = section.offsetTop - 100;
const sectionHeight = section.offsetHeight;
const sectionId = section.getAttribute('id');
if (window.scrollY >= sectionTop && window.scrollY < sectionTop + sectionHeight) {
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${sectionId}`) {
link.classList.add('active');
}
});
}
});
});
});
4. 效果展示

扩展挑战
- 添加作品详情页面
- 实现作品图片轮播
- 添加暗色模式切换
- 实现作品过滤动画效果
项目四:交互式仪表板
这个项目将帮助你创建一个具有多种图表和数据可视化的交互式仪表板。
项目目标
- 创建一个现代化的仪表板界面
- 实现多种数据可视化组件
- 添加交互式控件和过滤器
- 实现响应式布局
步骤指南
1. 创建HTML结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>交互式仪表板</title>
<link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<!-- 侧边栏 -->
<aside class="sidebar">
<div class="sidebar-header">
<h1>数据仪表板</h1>
<button class="sidebar-toggle">
<i class="fas fa-bars"></i>
</button>
</div>
<nav class="sidebar-nav">
<ul>
<li class="active">
<a href="#dashboard">
<i class="fas fa-tachometer-alt"></i>
<span>仪表板</span>
</a>
</li>
<li>
<a href="#analytics">
<i class="fas fa-chart-line"></i>
<span>分析</span>
</a>
</li>
<li>
<a href="#customers">
<i class="fas fa-users"></i>
<span>客户</span>
</a>
</li>
<li>
<a href="#orders">
<i class="fas fa-shopping-cart"></i>
<span>订单</span>
</a>
</li>
<li>
<a href="#products">
<i class="fas fa-box"></i>
<span>产品</span>
</a>
</li>
<li>
<a href="#settings">
<i class="fas fa-cog"></i>
<span>设置</span>
</a>
</li>
</ul>
</nav>
<div class="sidebar-footer">
<a href="#" class="user-profile">
<img src="https://via.placeholder.com/40" alt="用户头像">
<div class="user-info">
<h3>管理员</h3>
<p>admin@example.com</p>
</div>
</a>
<a href="#" class="logout">
<i class="fas fa-sign-out-alt"></i>
</a>
</div>
</aside>
<!-- 主内容区 -->
<main class="main-content">
<header class="main-header">
<div class="search-box">
<i class="fas fa-search"></i>
<input type="text" placeholder="搜索...">
</div>
<div class="header-actions">
<button class="notification-btn">
<i class="fas fa-bell"></i>
<span class="badge">3</span>
</button>
<button class="theme-toggle">
<i class="fas fa-moon"></i>
</button>
<div class="date-filter">
<select>
<option>今天</option>
<option>本周</option>
<option>本月</option>
<option>今年</option>
<option>自定义</option>
</select>
</div>
</div>
</header>
<div class="dashboard-content">
<div class="page-header">
<h2>仪表板概览</h2>
<p>欢迎回来,这是您的实时数据概览</p>
</div>
<!-- 统计卡片 -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon" style="background-color: rgba(66, 133, 244, 0.1);">
<i class="fas fa-shopping-cart" style="color: #4285F4;"></i>
</div>
<div class="stat-info">
<h3>总销售额</h3>
<p class="stat-value">¥128,430</p>
<p class="stat-change positive">
<i class="fas fa-arrow-up"></i> 12.5% <span>较上月</span>
</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background-color: rgba(234, 67, 53, 0.1);">
<i class="fas fa-users" style="color: #EA4335;"></i>
</div>
<div class="stat-info">
<h3>新客户</h3>
<p class="stat-value">843</p>
<p class="stat-change positive">
<i class="fas fa-arrow-up"></i> 8.2% <span>较上月</span>
</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background-color: rgba(251, 188, 5, 0.1);">
<i class="fas fa-box" style="color: #FBBC05;"></i>
</div>
<div class="stat-info">
<h3>订单数</h3>
<p class="stat-value">1,253</p>
<p class="stat-change negative">
<i class="fas fa-arrow-down"></i> 3.1% <span>较上月</span>
</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background-color: rgba(52, 168, 83, 0.1);">
<i class="fas fa-dollar-sign" style="color: #34A853;"></i>
</div>
<div class="stat-info">
<h3>平均订单价值</h3>
<p class="stat-value">¥102.50</p>
<p class="stat-change positive">
<i class="fas fa-arrow-up"></i> 5.3% <span>较上月</span>
</p>
</div>
</div>
</div>
<!-- 图表区域 -->
<div class="charts-grid">
<div class="chart-card large">
<div class="chart-header">
<h3>销售趋势</h3>
<div class="chart-actions">
<button class="chart-action active">日</button>
<button class="chart-action">周</button>
<button class="chart-action">月</button>
<button class="chart-action">年</button>
</div>
</div>
<div class="chart-body">
<canvas id="salesChart"></canvas>
</div>
</div>
<div class="chart-card">
<div class="chart-header">
<h3>流量来源</h3>
<button class="more-btn">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
<div class="chart-body">
<canvas id="trafficChart"></canvas>
</div>
</div>
<div class="chart-card">
<div class="chart-header">
<h3>产品类别</h3>
<button class="more-btn">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
<div class="chart-body">
<canvas id="categoryChart"></canvas>
</div>
</div>
</div>
<!-- 最近订单 -->
<div class="recent-orders">
<div class="section-header">
<h3>最近订单</h3>
<a href="#" class="view-all">查看全部</a>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>订单ID</th>
<th>客户</th>
<th>产品</th>
<th>日期</th>
<th>金额</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>#ORD-0123</td>
<td>
<div class="customer-info">
<img src="https://via.placeholder.com/32" alt="客户头像">
<span>张三</span>
</div>
</td>
<td>智能手表</td>
<td>2023-10-15</td>
<td>¥899</td>
<td><span class="status completed">已完成</span></td>
<td>
<button class="action-btn">
<i class="fas fa-eye"></i>
</button>
</td>
</tr>
<tr>
<td>#ORD-0124</td>
<td>
<div class="customer-info">
<img src="https://via.placeholder.com/32" alt="客户头像">
<span>李四</span>
</div>
</td>
<td>无线耳机</td>
<td>2023-10-14</td>
<td>¥499</td>
<td><span class="status pending">处理中</span></td>
<td>
<button class="action-btn">
<i class="fas fa-eye"></i>
</button>
</td>
</tr>
<tr>
<td>#ORD-0125</td>
<td>
<div class="customer-info">
<img src="https://via.placeholder.com/32" alt="客户头像">
<span>王五</span>
</div>
</td>
<td>智能台灯</td>
<td>2023-10-13</td>
<td>¥199</td>
<td><span class="status shipped">已发货</span></td>
<td>
<button class="action-btn">
<i class="fas fa-eye"></i>
</button>
</td>
</tr>
<tr>
<td>#ORD-0126</td>
<td>
<div class="customer-info">
<img src="https://via.placeholder.com/32" alt="客户头像">
<span>赵六</span>
</div>
</td>
<td>休闲夹克</td>
<td>2023-10-12</td>
<td>¥399</td>
<td><span class="status cancelled">已取消</span></td>
<td>
<button class="action-btn">
<i class="fas fa-eye"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</main>
<script src="dashboard.js"></script>
</body>
</html>
2. 创建CSS样式
/* 基本样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-color: #4285F4;
--secondary-color: #34A853;
--danger-color: #EA4335;
--warning-color: #FBBC05;
--dark-color: #202124;
--light-color: #F8F9FA;
--gray-color: #5F6368;
--border-color: #DADCE0;
--sidebar-width: 250px;
--sidebar-collapsed-width: 70px;
--header-height: 60px;
--card-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
--transition-speed: 0.3s;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #F8F9FA;
color: #202124;
line-height: 1.6;
display: flex;
min-height: 100vh;
}
/* 侧边栏样式 */
.sidebar {
width: var(--sidebar-width);
background-color: white;
height: 100vh;
position: fixed;
left: 0;
top: 0;
box-shadow: 1px 0 5px rgba(0, 0, 0, 0.1);
transition: width var(--transition-speed) ease;
display: flex;
flex-direction: column;
z-index: 100;
}
.sidebar.collapsed {
width: var(--sidebar-collapsed-width);
}
.sidebar-header {
padding: 20px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid var(--border-color);
}
.sidebar-header h1 {
font-size: 1.2rem;
color: var(--primary-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-toggle {
background: none;
border: none;
color: var(--gray-color);
cursor: pointer;
font-size: 1.2rem;
}
.sidebar-nav {
flex: 1;
padding: 20px 0;
overflow-y: auto;
}
.sidebar-nav ul {
list-style: none;
}
.sidebar-nav li {
margin-bottom: 5px;
}
.sidebar-nav a {
display: flex;
align-items: center;
padding: 10px 20px;
color: var(--gray-color);
text-decoration: none;
transition: all var(--transition-speed) ease;
border-left: 3px solid transparent;
}
.sidebar-nav a:hover {
background-color: rgba(66, 133, 244, 0.05);
color: var(--primary-color);
}
.sidebar-nav li.active a {
background-color: rgba(66, 133, 244, 0.1);
color: var(--primary-color);
border-left-color: var(--primary-color);
}
.sidebar-nav i {
font-size: 1.2rem;
margin-right: 15px;
width: 20px;
text-align: center;
}
.sidebar.collapsed .sidebar-nav span {
display: none;
}
.sidebar-footer {
padding: 15px 20px;
border-top: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.user-profile {
display: flex;
align-items: center;text-decoration: none;
color: var(--dark-color);
flex: 1;
white-space: nowrap;
overflow: hidden;
}
.user-profile img {
width: 32px;
height: 32px;
border-radius: 50%;
margin-right: 10px;
}
.user-info h3 {
font-size: 0.9rem;
margin-bottom: 2px;
}
.user-info p {
font-size: 0.8rem;
color: var(--gray-color);
}
.sidebar.collapsed .user-info {
display: none;
}
.logout {
color: var(--gray-color);
font-size: 1.2rem;
transition: color var(--transition-speed) ease;
}
.logout:hover {
color: var(--danger-color);
}
/* 主内容区样式 */
.main-content {
flex: 1;
margin-left: var(--sidebar-width);
transition: margin-left var(--transition-speed) ease;
}
.sidebar.collapsed ~ .main-content {
margin-left: var(--sidebar-collapsed-width);
}
.main-header {
height: var(--header-height);
background-color: white;
box-shadow: var(--card-shadow);
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
top: 0;
z-index: 10;
}
.search-box {
display: flex;
align-items: center;
background-color: var(--light-color);
border-radius: 4px;
padding: 8px 15px;
width: 300px;
}
.search-box i {
color: var(--gray-color);
margin-right: 10px;
}
.search-box input {
border: none;
background: none;
outline: none;
width: 100%;
font-size: 0.9rem;
}
.header-actions {
display: flex;
align-items: center;
gap: 15px;
}
.notification-btn, .theme-toggle {
background: none;
border: none;
color: var(--gray-color);
font-size: 1.2rem;
cursor: pointer;
position: relative;
}
.badge {
position: absolute;
top: -5px;
right: -5px;
background-color: var(--danger-color);
color: white;
font-size: 0.7rem;
width: 18px;
height: 18px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.date-filter select {
padding: 8px 12px;
border: 1px solid var(--border-color);
border-radius: 4px;
background-color: white;
font-size: 0.9rem;
color: var(--dark-color);
outline: none;
}
/* 仪表板内容样式 */
.dashboard-content {
padding: 20px;
}
.page-header {
margin-bottom: 25px;
}
.page-header h2 {
font-size: 1.5rem;
margin-bottom: 5px;
}
.page-header p {
color: var(--gray-color);
font-size: 0.9rem;
}
/* 统计卡片样式 */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 25px;
}
.stat-card {
background-color: white;
border-radius: 8px;
box-shadow: var(--card-shadow);
padding: 20px;
display: flex;
align-items: center;
}
.stat-icon {
width: 50px;
height: 50px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
margin-right: 15px;
}
.stat-info h3 {
font-size: 0.9rem;
color: var(--gray-color);
margin-bottom: 5px;
}
.stat-value {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 5px;
}
.stat-change {
font-size: 0.8rem;
display: flex;
align-items: center;
}
.stat-change i {
margin-right: 5px;
}
.stat-change span {
color: var(--gray-color);
margin-left: 5px;
}
.positive {
color: var(--secondary-color);
}
.negative {
color: var(--danger-color);
}
/* 图表卡片样式 */
.charts-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-bottom: 25px;
}
.chart-card {
background-color: white;
border-radius: 8px;
box-shadow: var(--card-shadow);
overflow: hidden;
}
.chart-card.large {
grid-column: span 2;
}
.chart-header {
padding: 15px 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.chart-header h3 {
font-size: 1rem;
}
.chart-actions {
display: flex;
gap: 5px;
}
.chart-action {
background: none;
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 5px 10px;
font-size: 0.8rem;
cursor: pointer;
transition: all var(--transition-speed) ease;
}
.chart-action.active, .chart-action:hover {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.more-btn {
background: none;
border: none;
color: var(--gray-color);
cursor: pointer;
font-size: 1rem;
}
.chart-body {
padding: 20px;
height: 300px;
}
/* 最近订单样式 */
.recent-orders {
background-color: white;
border-radius: 8px;
box-shadow: var(--card-shadow);
overflow: hidden;
}
.section-header {
padding: 15px 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.section-header h3 {
font-size: 1rem;
}
.view-all {
color: var(--primary-color);
text-decoration: none;
font-size: 0.9rem;
}
.table-container {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px 20px;
text-align: left;
}
th {
background-color: var(--light-color);
color: var(--gray-color);
font-weight: 500;
font-size: 0.9rem;
}
tr {
border-bottom: 1px solid var(--border-color);
}
tr:last-child {
border-bottom: none;
}
.customer-info {
display: flex;
align-items: center;
}
.customer-info img {
width: 32px;
height: 32px;
border-radius: 50%;
margin-right: 10px;
}
.status {
display: inline-block;
padding: 5px 10px;
border-radius: 20px;
font-size: 0.8rem;
}
.completed {
background-color: rgba(52, 168, 83, 0.1);
color: var(--secondary-color);
}
.pending {
background-color: rgba(251, 188, 5, 0.1);
color: var(--warning-color);
}
.shipped {
background-color: rgba(66, 133, 244, 0.1);
color: var(--primary-color);
}
.cancelled {
background-color: rgba(234, 67, 53, 0.1);
color: var(--danger-color);
}
.action-btn {
background: none;
border: none;
color: var(--gray-color);
cursor: pointer;
font-size: 1rem;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.charts-grid {
grid-template-columns: 1fr;
}
.chart-card.large {
grid-column: span 1;
}
}
@media (max-width: 992px) {
.sidebar {
width: var(--sidebar-collapsed-width);
}
.sidebar-nav span, .user-info {
display: none;
}
.main-content {
margin-left: var(--sidebar-collapsed-width);
}
.sidebar.expanded {
width: var(--sidebar-width);
z-index: 1000;
}
.sidebar.expanded .sidebar-nav span,
.sidebar.expanded .user-info {
display: block;
}
}
@media (max-width: 768px) {
.stats-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.search-box {
width: 200px;
}
}
@media (max-width: 576px) {
.main-header {
flex-direction: column;
height: auto;
padding: 15px;
}
.search-box {
width: 100%;
margin-bottom: 15px;
}
.header-actions {
width: 100%;
justify-content: space-between;
}
.stats-grid {
grid-template-columns: 1fr;
}
.stat-card {
padding: 15px;
}
}
3. 创建JavaScript功能
// dashboard.js
document.addEventListener('DOMContentLoaded', function() {
// 侧边栏切换
const sidebarToggle = document.querySelector('.sidebar-toggle');
const sidebar = document.querySelector('.sidebar');
sidebarToggle.addEventListener('click', function() {
sidebar.classList.toggle('collapsed');
sidebar.classList.toggle('expanded');
});
// 主题切换
const themeToggle = document.querySelector('.theme-toggle');
const body = document.body;
themeToggle.addEventListener('click', function() {
body.classList.toggle('dark-theme');
const icon = this.querySelector('i');
if (body.classList.contains('dark-theme')) {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
} else {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
}
});
// 图表初始化
// 销售趋势图表
const salesChartCtx = document.getElementById('salesChart').getContext('2d');
const salesChart = new Chart(salesChartCtx, {
type: 'line',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月'],
datasets: [{
label: '销售额',
data: [12000, 19000, 15000, 25000, 22000, 30000, 28000, 25000, 30000, 35000],
backgroundColor: 'rgba(66, 133, 244, 0.1)',
borderColor: '#4285F4',
borderWidth: 2,
tension: 0.4,
pointBackgroundColor: '#4285F4',
pointBorderColor: '#fff',
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
grid: {
display: false
}
}
},
plugins: {
legend: {
display: false
}
}
}
});
// 流量来源图表
const trafficChartCtx = document.getElementById('trafficChart').getContext('2d');
const trafficChart = new Chart(trafficChartCtx, {
type: 'doughnut',
data: {
labels: ['直接访问', '搜索引擎', '社交媒体', '广告', '其他'],
datasets: [{
data: [30, 40, 15, 10, 5],
backgroundColor: ['#4285F4', '#34A853', '#FBBC05', '#EA4335', '#5F6368'],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
boxWidth: 12,
padding: 15
}
}
},
cutout: '70%'
}
});
// 产品类别图表
const categoryChartCtx = document.getElementById('categoryChart').getContext('2d');
const categoryChart = new Chart(categoryChartCtx, {
type: 'bar',
data: {
labels: ['电子产品', '服装', '家居', '食品', '美妆'],
datasets: [{
label: '销售额',
data: [45000, 30000, 25000, 15000, 20000],
backgroundColor: [
'rgba(66, 133, 244, 0.7)',
'rgba(52, 168, 83, 0.7)',
'rgba(251, 188, 5, 0.7)',
'rgba(234, 67, 53, 0.7)',
'rgba(95, 99, 104, 0.7)'
],
borderWidth: 0,
borderRadius: 5
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
grid: {
display: false
}
}
},
plugins: {
legend: {
display: false
}
}
}
});
// 图表切换功能
const chartActions = document.querySelectorAll('.chart-action');
chartActions.forEach(action => {
action.addEventListener('click', function() {
chartActions.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
// 这里可以添加不同时间范围的数据切换逻辑
});
});
// 表格行悬停效果
const tableRows = document.querySelectorAll('tbody tr');
tableRows.forEach(row => {
row.addEventListener('mouseenter', function() {
this.style.backgroundColor = 'rgba(0, 0, 0, 0.02)';
});
row.addEventListener('mouseleave', function() {
this.style.backgroundColor = '';
});
});
});
4. 效果展示

扩展挑战
- 添加更多类型的图表和数据可视化
- 实现数据筛选和导出功能
- 添加实时数据更新功能
- 实现用户权限管理系统
总结
在这个实践项目章节中,我们通过四个不同类型的项目,全面应用了CSS的各种技术和概念:
响应式导航菜单:学习了如何创建在不同设备上都能良好显示的导航栏,掌握了媒体查询和弹性布局的应用。
产品展示页面:实践了网格布局、卡片设计和悬停效果,提升了用户体验和页面美观度。
个人作品集网站:综合运用了响应式设计、动画效果和交互功能,创建了专业的个人展示平台。
交互式仪表板:学习了如何构建复杂的数据可视化界面,实现了多种交互控件和图表展示。
通过这些项目,你不仅巩固了CSS的基础知识,还学习了如何将这些知识应用到实际开发中。这些项目涵盖了前端开发中常见的场景,为你今后的开发工作提供了宝贵的经验和参考。
记住,CSS的学习是一个持续的过程,建议你在完成这些项目后,尝试添加自己的创意和功能,进一步提升你的CSS技能。同时,关注前端技术的最新发展,不断学习新的CSS特性和技术,将使你在前端开发领域保持竞争力。
祝你在CSS的学习之旅中取得更大的进步!