设计理念
这个页面的设计目标是成为一个“一站式解决方案”,帮助前端开发者在不同学习阶段(从入门到精通)找到合适的HTML5项目案例和开发工具。

(图片来源网络,侵删)
- 目标用户: 前端开发者、Web设计师、计算机专业学生、自学者。
- 核心功能:
- 清晰的分类: 按项目类型(如游戏、表单、动画)和开发阶段(入门、进阶)进行分类。
- 强大的搜索: 支持关键词搜索,并能根据评分、收藏状态进行排序。
- 丰富的信息展示: 每个软件/案例卡片都包含名称、简介、核心技术栈、难度、评分和收藏按钮。
- 响应式设计: 在桌面、平板和手机上都能提供良好的浏览体验。
- 技术栈: HTML5, CSS3 (Flexbox, Grid), 原生JavaScript (ES6+)。
最终效果预览
桌面端布局:
移动端布局:
代码实现
您可以直接复制以下代码到一个 .html 文件中,然后在浏览器中打开即可看到效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">HTML5 阶段案例与开发工具</title>
<style>
/* --- 全局样式和变量 --- */
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--success-color: #28a745;
--warning-color: #ffc107;
--danger-color: #dc3545;
--light-color: #f8f9fa;
--dark-color: #343a40;
--border-radius: 8px;
--box-shadow: 0 4px 8px rgba(0,0,0,0.1);
--transition: all 0.3s ease;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
background-color: #f0f2f5;
color: var(--dark-color);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* --- 头部样式 --- */
header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 2rem 0;
box-shadow: var(--box-shadow);
}
header h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
header p {
font-size: 1.1rem;
opacity: 0.9;
}
/* --- 主要内容区 --- */
main {
padding: 2rem 0;
}
/* --- 搜索和筛选栏 --- */
.filter-bar {
background: white;
padding: 1.5rem;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
margin-bottom: 2rem;
display: flex;
flex-wrap: wrap;
gap: 1rem;
align-items: center;
}
.search-box {
flex-grow: 1;
min-width: 250px;
}
.search-box input {
width: 100%;
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: var(--border-radius);
font-size: 1rem;
transition: var(--transition);
}
.search-box input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(0,123,255,0.25);
}
.filter-group {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.filter-btn, .sort-btn {
padding: 0.5rem 1rem;
border: 1px solid #ddd;
background: white;
border-radius: var(--border-radius);
cursor: pointer;
transition: var(--transition);
font-size: 0.9rem;
}
.filter-btn:hover, .sort-btn:hover {
background: var(--light-color);
}
.filter-btn.active {
background: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
/* --- 软件列表网格 --- */
.software-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 1.5rem;
}
/* --- 软件卡片样式 --- */
.software-card {
background: white;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
overflow: hidden;
transition: var(--transition);
display: flex;
flex-direction: column;
}
.software-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0,0,0,0.15);
}
.card-header {
padding: 1.5rem;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.card-header h3 {
font-size: 1.4rem;
margin-bottom: 0.5rem;
color: var(--dark-color);
}
.card-body {
padding: 1.5rem;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.card-description {
color: var(--secondary-color);
margin-bottom: 1rem;
flex-grow: 1;
}
.card-footer {
padding: 1rem 1.5rem;
border-top: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
.tech-tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tech-tag {
background: var(--light-color);
color: var(--secondary-color);
padding: 0.2rem 0.6rem;
border-radius: 12px;
font-size: 0.8rem;
}
.card-actions {
display: flex;
align-items: center;
gap: 1rem;
}
.difficulty {
font-size: 0.9rem;
font-weight: bold;
}
.difficulty.beginner { color: var(--success-color); }
.difficulty.intermediate { color: var(--warning-color); }
.difficulty.advanced { color: var(--danger-color); }
.rating {
display: flex;
align-items: center;
gap: 0.3rem;
}
.stars {
color: #ffc107;
}
.favorite-btn {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--secondary-color);
transition: var(--transition);
}
.favorite-btn:hover,
.favorite-btn.active {
color: var(--danger-color);
transform: scale(1.1);
}
/* --- 响应式设计 --- */
@media (max-width: 768px) {
header h1 {
font-size: 2rem;
}
.filter-bar {
flex-direction: column;
align-items: stretch;
}
.search-box {
min-width: 100%;
}
.software-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<header>
<div class="container">
<h1>HTML5 阶段案例与开发工具</h1>
<p>从入门到精通,精选项目案例与高效工具,助你成为前端大师</p>
</div>
</header>
<main>
<div class="container">
<!-- 搜索和筛选栏 -->
<section class="filter-bar">
<div class="search-box">
<input type="text" id="searchInput" placeholder="搜索软件名称或技术...">
</div>
<div class="filter-group">
<span style="font-weight: bold;">分类:</span>
<button class="filter-btn active" data-category="all">全部</button>
<button class="filter-btn" data-category="game">游戏</button>
<button class="filter-btn" data-category="form">表单</button>
<button class="filter-btn" data-category="animation">动画</button>
<button class="filter-btn" data-category="tool">工具</button>
</div>
<div class="filter-group">
<span style="font-weight: bold;">排序:</span>
<button class="sort-btn" id="sortByRating">按评分</button>
<button class="sort-btn" id="sortByFavorites">按收藏</button>
</div>
</section>
<!-- 软件列表 -->
<section id="softwareList" class="software-grid">
<!-- 软件卡片将通过 JavaScript 动态生成 -->
</section>
</div>
</main>
<script>
// --- 数据模型 ---
const softwareData = [
{
id: 1,
name: "Canvas 贪吃蛇游戏",
category: "game",
description: "使用 HTML5 Canvas API 实现的经典贪吃蛇游戏,包含得分、速度递增等核心功能。",
tech: ["HTML5", "Canvas", "JavaScript"],
difficulty: "beginner",
rating: 4.5,
favorites: 120
},
{
id: 2,
name: "响应式注册表单",
category: "form",
description: "一个功能完善的注册表单,包含实时验证、密码强度检测和友好的错误提示。",
tech: ["HTML5", "CSS3", "JavaScript"],
difficulty: "intermediate",
rating: 4.7,
favorites: 95
},
{
id: 3,
name: "CSS3 动画加载页",
category: "animation",
description: "纯 CSS3 制作的炫酷加载动画,无需 JavaScript,性能优异,易于集成。",
tech: ["HTML5", "CSS3"],
difficulty: "beginner",
rating: 4.2,
favorites: 80
},
{
id: 4,
name: "本地存储待办事项",
category: "tool",
description: "利用 LocalStorage API 构建的离线待办事项应用,数据保存在浏览器本地。",
tech: ["HTML5", "JavaScript", "LocalStorage"],
difficulty: "intermediate",
rating: 4.6,
favorites: 150
},
{
id: 5,
name: "WebGL 3D 立方体",
category: "game",
description: "使用 Three.js 库创建的交互式 3D 立方体,支持鼠标拖拽旋转。",
tech: ["HTML5", "WebGL", "Three.js"],
difficulty: "advanced",
rating: 4.8,
favorites: 200
},
{
id: 6,
name: "拖放文件上传器",
category: "tool",
description: "一个现代化的文件上传组件,支持拖放、多文件选择和上传进度显示。",
tech: ["HTML5", "JavaScript", "File API"],
difficulty: "advanced",
rating: 4.9,
favorites: 180
},
{
id: 7,
name: "SVG 交互动画",
category: "animation",
description: "结合 SVG 和 CSS/JS 制作的数据可视化动画,图表可交互、可缩放。",
tech: ["HTML5", "SVG", "JavaScript"],
difficulty: "intermediate",
rating: 4.4,
favorites: 65
},
{
id: 8,
name: "表单验证与提交",
category: "form",
description: "深入讲解 HTML5 表单验证 API 的使用,并结合原生 JS 实现自定义验证逻辑。",
tech: ["HTML5", "JavaScript"],
difficulty: "intermediate",
rating: 4.3,
favorites: 110
}
];
// --- 状态管理 ---
let currentCategory = 'all';
let favoriteItems = new Set(JSON.parse(localStorage.getItem('favorites') || '[]'));
let sortBy = 'default';
// --- DOM 元素 ---
const softwareListEl = document.getElementById('softwareList');
const searchInputEl = document.getElementById('searchInput');
const filterBtns = document.querySelectorAll('.filter-btn');
const sortByRatingBtn = document.getElementById('sortByRating');
const sortByFavoritesBtn = document.getElementById('sortByFavorites');
// --- 渲染函数 ---
function renderSoftwareList(data) {
softwareListEl.innerHTML = '';
data.forEach(software => {
const card = createSoftwareCard(software);
softwareListEl.appendChild(card);
});
}
function createSoftwareCard(software) {
const card = document.createElement('div');
card.className = 'software-card';
card.dataset.category = software.category;
card.dataset.id = software.id;
const isFavorite = favoriteItems.has(software.id);
card.innerHTML = `
<div class="card-header">
<h3>${software.name}</h3>
</div>
<div class="card-body">
<p class="card-description">${software.description}</p>
</div>
<div class="card-footer">
<div class="tech-tags">
${software.tech.map(t => `<span class="tech-tag">${t}</span>`).join('')}
</div>
<div class="card-actions">
<span class="difficulty ${software.difficulty}">${getDifficultyText(software.difficulty)}</span>
<div class="rating">
<span class="stars">${generateStars(software.rating)}</span>
<span>${software.rating}</span>
</div>
<button class="favorite-btn ${isFavorite ? 'active' : ''}" data-id="${software.id}">
${isFavorite ? '❤️' : '🤍'}
</button>
</div>
</div>
`;
// 添加收藏按钮事件监听
const favoriteBtn = card.querySelector('.favorite-btn');
favoriteBtn.addEventListener('click', () => toggleFavorite(software.id, favoriteBtn));
return card;
}
function getDifficultyText(difficulty) {
const map = { beginner: '入门', intermediate: '进阶', advanced: '精通' };
return map[difficulty] || difficulty;
}
function generateStars(rating) {
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 !== 0;
let stars = '★'.repeat(fullStars);
if (hasHalfStar) stars += '☆';
return stars;
}
// --- 事件处理函数 ---
function toggleFavorite(id, btnElement) {
if (favoriteItems.has(id)) {
favoriteItems.delete(id);
btnElement.classList.remove('active');
btnElement.textContent = '🤍';
} else {
favoriteItems.add(id);
btnElement.classList.add('active');
btnElement.textContent = '❤️';
}
localStorage.setItem('favorites', JSON.stringify([...favoriteItems]));
}
function getFilteredAndSortedData() {
let filteredData = softwareData;
// 1. 分类筛选
if (currentCategory !== 'all') {
filteredData = filteredData.filter(s => s.category === currentCategory);
}
// 2. 搜索筛选
const searchTerm = searchInputEl.value.toLowerCase();
if (searchTerm) {
filteredData = filteredData.filter(s =>
s.name.toLowerCase().includes(searchTerm) ||
s.description.toLowerCase().includes(searchTerm) ||
s.tech.some(t => t.toLowerCase().includes(searchTerm))
);
}
// 3. 排序
if (sortBy === 'rating') {
filteredData.sort((a, b) => b.rating - a.rating);
} else if (sortBy === 'favorites') {
filteredData.sort((a, b) => b.favorites - a.favorites);
}
return filteredData;
}
// --- 事件监听器 ---
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
filterBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
currentCategory = btn.dataset.category;
renderSoftwareList(getFilteredAndSortedData());
});
});
searchInputEl.addEventListener('input', () => {
renderSoftwareList(getFilteredAndSortedData());
});
sortByRatingBtn.addEventListener('click', () => {
sortBy = sortBy === 'rating' ? 'default' : 'rating';
sortByRatingBtn.textContent = sortBy === 'rating' ? '默认' : '按评分';
renderSoftwareList(getFilteredAndSortedData());
});
sortByFavoritesBtn.addEventListener('click', () => {
sortBy = sortBy === 'favorites' ? 'default' : 'favorites';
sortByFavoritesBtn.textContent = sortBy === 'favorites' ? '默认' : '按收藏';
renderSoftwareList(getFilteredAndSortedData());
});
// --- 初始化 ---
renderSoftwareList(getFilteredAndSortedData());
</script>
</body>
</html>
设计亮点解析
-
现代化视觉设计
(图片来源网络,侵删)- 渐变色彩: 头部和卡片头部使用了渐变背景,让页面更具视觉吸引力。
- 卡片式布局: 每个软件/案例都以卡片形式呈现,信息结构清晰,符合现代设计趋势。
- 微交互: 鼠标悬停时卡片上浮,收藏按钮点击后变色,这些细节提升了用户体验。
-
功能强大的筛选与搜索
- 多维度筛选: 用户可以按“分类”(游戏、表单等)和“排序”(评分、收藏)进行筛选。
- 实时搜索: 输入关键词后,列表会实时更新,无需点击搜索按钮。
- 数据联动: 筛选、搜索和排序功能可以组合使用,在“游戏”分类下“按评分”排序。
-
丰富的信息展示
- 难度标识: 用不同颜色的文字(绿、黄、红)直观地表示案例的难度等级。
- 星级评分: 用星星符号直观展示评分,比纯数字更友好。
- 技术标签: 清晰地列出每个案例涉及的核心技术,方便开发者快速判断。
-
贴心的用户功能
- 收藏功能: 用户可以点击心形图标收藏感兴趣的案例,数据通过
localStorage保存在浏览器中,刷新页面后收藏状态依然保留。 - 响应式布局: 使用 CSS Grid 和 Flexbox,页面能自适应不同屏幕尺寸,在手机、平板和电脑上都有良好表现。
- 收藏功能: 用户可以点击心形图标收藏感兴趣的案例,数据通过
-
代码结构清晰
(图片来源网络,侵删)- 数据与视图分离: 所有软件数据存储在
softwareData数组中,JavaScript 负责处理数据和渲染视图,逻辑清晰。 - 模块化函数:
renderSoftwareList,createSoftwareCard,getFilteredAndSortedData等函数各司其职,便于维护和扩展。 - 事件委托: 虽然这个例子中为每个收藏按钮单独添加了监听器,但在更复杂的列表中,可以考虑使用事件委托来优化性能。
- 数据与视图分离: 所有软件数据存储在
这个案例不仅是一个静态的列表,更是一个功能完备的、可交互的 Web 应用,充分展示了 HTML5、CSS3 和 JavaScript 协同工作的强大能力。
