- 项目简介:说明这个网页是做什么的,有哪些功能。
- 设计思路:讲解HTML结构、CSS样式和JavaScript交互的实现逻辑。
- 完整代码:可以直接复制粘贴运行的HTML、CSS和JavaScript代码。
- 如何运行:简单的操作指南。
- 可能的进阶方向:如果你想进一步挑战自己可以尝试什么。
个人作品集 / 个人简历网站 (入门级)
这是最经典也最适合初学者的作业,可以练习HTML标签的语义化使用、CSS布局(Flexbox/Grid)和响应式设计。

(图片来源网络,侵删)
项目简介
一个简洁、现代的个人作品集网站,包含以下几个部分:
- 导航栏:固定在顶部,点击可以平滑滚动到对应部分。
- 首页/英雄区:展示你的名字、职业和一句个人介绍。
- 关于我:一段关于自己的详细介绍。
- 我的技能:用进度条或图标展示你的技能水平。
- 项目展示:用卡片布局展示你的项目作品。
- 联系方式:一个简单的联系表单和你的社交媒体链接。
设计思路
- HTML结构:使用
<header>,<nav>,<main>,<section>,<footer>等语义化标签来构建页面骨架,让代码更清晰、对搜索引擎更友好。 - CSS样式:
- 使用 Flexbox 或 Grid 进行布局,实现灵活的对齐和排列。
- 使用 CSS变量 来定义主题色、字体大小等,方便统一管理和修改。
- 使用
position: sticky;实现导航栏的固定效果。 - 使用
scroll-behavior: smooth;实现平滑滚动。 - 使用媒体查询
@media实现响应式设计,确保在手机上也能良好显示。
- JavaScript交互:
- 为导航链接添加点击事件,阻止默认跳转,然后用
scrollIntoView({ behavior: 'smooth' })实现平滑滚动。 - 为导航栏添加一个效果:当用户滚动页面时,改变导航栏的背景色(从透明变为白色)。
- 为导航链接添加点击事件,阻止默认跳转,然后用
完整代码
这是一个单文件 index.html,包含了所有HTML、CSS和JavaScript代码。
<!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: #007bff;
--secondary-color: #343a40;
--text-color: #333;
--light-bg: #f8f9fa;
--white: #ffffff;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-color);
}
.container {
max-width: 1100px;
margin: auto;
padding: 0 2rem;
overflow: hidden;
}
h1, h2, h3 {
margin-bottom: 1rem;
line-height: 1.2;
}
h2 {
font-size: 2.5rem;
text-align: center;
margin-bottom: 3rem;
color: var(--secondary-color);
}
section {
padding: 4rem 0;
}
/* --- 导航栏 --- */
#main-nav {
position: sticky;
top: 0;
background: rgba(255, 255, 255, 0.95);
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: all 0.3s ease;
z-index: 1000;
}
#main-nav.scrolled {
background: var(--white);
padding: 0.5rem 2rem;
}
#main-nav .logo {
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
}
#main-nav ul {
display: flex;
list-style: none;
}
#main-nav ul li a {
color: var(--text-color);
text-decoration: none;
padding: 0.75rem 1rem;
transition: color 0.3s ease;
}
#main-nav ul li a:hover {
color: var(--primary-color);
}
/* --- 首页/英雄区 --- */
#hero {
height: 100vh;
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)), url('https://images.unsplash.com/photo-1557682257-2f9c37a3a5f3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80') no-repeat center center/cover;
color: var(--white);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
}
#hero h1 {
font-size: 3.5rem;
margin-bottom: 1rem;
}
#hero p {
font-size: 1.2rem;
margin-bottom: 2rem;
}
.btn {
display: inline-block;
background: var(--primary-color);
color: var(--white);
padding: 0.8rem 2rem;
border: none;
border-radius: 5px;
cursor: pointer;
text-decoration: none;
transition: background 0.3s ease;
}
.btn:hover {
background: #0056b3;
}
/* --- 关于我 --- */
#about {
background: var(--light-bg);
}
.about-content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.about-text {
flex: 1;
padding-right: 2rem;
}
.about-img {
flex: 1;
text-align: center;
}
.about-img img {
width: 70%;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
/* --- 技能 --- */
.skills-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.skill-item {
background: var(--white);
padding: 1.5rem;
border-radius: 5px;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
}
.skill-item h3 {
margin-bottom: 1rem;
}
.skill-bar {
background: #e0e0e0;
height: 10px;
border-radius: 5px;
overflow: hidden;
}
.skill-progress {
height: 100%;
background: var(--primary-color);
border-radius: 5px;
width: 0; /* 初始为0,JS会改变它 */
transition: width 2s ease-in-out;
}
/* --- 项目 --- */
.projects-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.project-card {
background: var(--white);
border-radius: 5px;
overflow: hidden;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
}
.project-card:hover {
transform: translateY(-10px);
}
.project-img {
height: 200px;
background: #ccc;
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
color: #666;
}
.project-info {
padding: 1.5rem;
}
.project-info h3 {
margin-bottom: 0.5rem;
}
/* --- 联系方式 --- */
#contact .contact-form {
max-width: 600px;
margin: 0 auto;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 0.8rem;
border: 1px solid #ddd;
border-radius: 5px;
font-family: inherit;
}
.form-group textarea {
height: 150px;
}
/* --- 页脚 --- */
#main-footer {
background: var(--secondary-color);
color: var(--white);
text-align: center;
padding: 1rem;
}
/* --- 响应式设计 --- */
@media (max-width: 768px) {
#main-nav {
flex-direction: column;
padding: 1rem;
}
#main-nav ul {
margin-top: 1rem;
}
#main-nav ul li {
margin: 0 0.5rem;
}
#hero h1 {
font-size: 2.5rem;
}
.about-content {
flex-direction: column;
}
.about-text {
padding-right: 0;
margin-bottom: 2rem;
}
}
</style>
</head>
<body>
<!-- 导航栏 -->
<header id="main-nav">
<div class="logo">张三</div>
<ul>
<li><a href="#hero">首页</a></li>
<li><a href="#about">关于我</a></li>
<li><a href="#skills">技能</a></li>
<li><a href="#projects">项目</a></li>
<li><a href="#contact">联系</a></li>
</ul>
</header>
<main>
<!-- 首页/英雄区 -->
<section id="hero">
<div class="container">
<h1>你好,我是张三</h1>
<p>一名充满激情的前端开发工程师</p>
<a href="#about" class="btn">了解更多</a>
</div>
</section>
<!-- 关于我 -->
<section id="about">
<div class="container">
<h2>关于我</h2>
<div class="about-content">
<div class="about-text">
<p>我是一名热爱创造美好网页体验的前端开发者,我专注于使用现代技术栈,如HTML5, CSS3, 和JavaScript,来构建响应式、用户友好的网站。</p>
<p>我相信,好的设计不仅要美观,更要功能强大且易于使用,我不断学习新技术,以跟上行业的快速发展,并致力于为用户提供最佳的交互体验。</p>
</div>
<div class="about-img">
<img src="https://i.pravatar.cc/150?u=zhangsan" alt="张三的头像">
</div>
</div>
</div>
</section>
<!-- 我的技能 -->
<section id="skills">
<div class="container">
<h2>我的技能</h2>
<div class="skills-grid">
<div class="skill-item">
<h3>HTML5 / CSS3</h3>
<div class="skill-bar">
<div class="skill-progress" data-width="90%"></div>
</div>
</div>
<div class="skill-item">
<h3>JavaScript (ES6+)</h3>
<div class="skill-bar">
<div class="skill-progress" data-width="85%"></div>
</div>
</div>
<div class="skill-item">
<h3>React / Vue</h3>
<div class="skill-bar">
<div class="skill-progress" data-width="75%"></div>
</div>
</div>
<div class="skill-item">
<h3>响应式设计</h3>
<div class="skill-bar">
<div class="skill-progress" data-width="95%"></div>
</div>
</div>
</div>
</div>
</section>
<!-- 项目展示 -->
<section id="projects">
<div class="container">
<h2>项目展示</h2>
<div class="projects-grid">
<div class="project-card">
<div class="project-img">🛒</div>
<div class="project-info">
<h3>在线购物商城</h3>
<p>一个功能完整的电商网站,包含商品展示、购物车、用户登录注册等功能,使用React和Node.js构建。</p>
</div>
</div>
<div class="project-card">
<div class="project-img">📝</div>
<div class="project-info">
<h3>任务管理应用</h3>
<p>一个简洁的任务管理工具,支持创建、编辑、删除和标记任务,使用Vue.js和本地存储实现。</p>
</div>
</div>
<div class="project-card">
<div class="project-img">📊</div>
<div class="project-info">
<h3>数据可视化看板</h3>
<p>一个用于展示销售数据的动态看板,使用Chart.js库实现图表的动态更新和交互。</p>
</div>
</div>
</div>
</div>
</section>
<!-- 联系方式 -->
<section id="contact">
<div class="container">
<h2>联系我</h2>
<form class="contact-form" id="contact-form">
<div class="form-group">
<label for="name">姓名</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="message">留言</label>
<textarea id="message" name="message" required></textarea>
</div>
<button type="submit" class="btn">发送</button>
</form>
</div>
</section>
</main>
<!-- 页脚 -->
<footer id="main-footer">
<div class="container">
<p>© 2025 张三的作品集. 保留所有权利.</p>
</div>
</footer>
<script>
// 1. 导航栏滚动效果
window.addEventListener('scroll', function() {
const nav = document.getElementById('main-nav');
if (window.scrollY > 50) {
nav.classList.add('scrolled');
} else {
nav.classList.remove('scrolled');
}
});
// 2. 技能条动画
const observerOptions = {
threshold: 0.5
};
const observer = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const skillBars = entry.target.querySelectorAll('.skill-progress');
skillBars.forEach(bar => {
const width = bar.getAttribute('data-width');
bar.style.width = width;
});
}
});
}, observerOptions);
const skillsSection = document.getElementById('skills');
if (skillsSection) {
observer.observe(skillsSection);
}
// 3. 联系表单提交(模拟)
const contactForm = document.getElementById('contact-form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
// 这里可以添加实际的表单提交逻辑,比如发送到服务器
// 目前我们只是模拟一个成功提示
alert('感谢您的留言!我会尽快回复您。');
contactForm.reset(); // 清空表单
});
}
</script>
</body>
</html>
如何运行
- 将以上所有代码复制到一个文本编辑器中(如 VS Code, Sublime Text, 或记事本)。
- 将文件另存为
index.html。 - 用任何现代浏览器(如 Chrome, Firefox, Edge)打开这个
index.html文件即可看到效果。
可能的进阶方向
- 添加更多动画:为项目卡片、按钮等添加更复杂的CSS动画或过渡效果。
- 集成真实数据:使用JavaScript从JSON文件或API动态加载项目数据,而不是硬编码在HTML中。
- 表单验证增强:使用HTML5的表单验证属性或更复杂的JavaScript进行实时验证。
- 部署上线:学习如何使用 GitHub Pages, Vercel, Netlify 等免费平台将你的作品集部署到互联网上。
- 添加暗黑模式:增加一个切换按钮,允许用户在亮色和暗色主题之间切换。
待办事项 应用 (中级)
这个作业更侧重于JavaScript的交互逻辑,可以让你练习DOM操作、事件处理和数据管理。
项目简介
一个功能完整的待办事项应用,用户可以:

(图片来源网络,侵删)
- 添加新的待办事项。
- 标记待办事项为“已完成”。
- 删除待办事项。
- 根据状态(全部/进行中/已完成)筛选待办事项。
- 将待办事项数据保存到浏览器的本地存储中,刷新页面后数据不会丢失。
设计思路
- HTML结构:一个简单的输入框和按钮,一个用于筛选的导航栏,一个用于展示待办事项列表的
<ul>。 - CSS样式:使用Flexbox布局,为“已完成”的待办事项添加删除线和灰色样式,使用
hover效果提升用户体验。 - JavaScript交互:
- 数据模型:使用一个数组来存储待办事项对象,每个对象包含
id,text,completed属性。 - DOM操作:
addEventListener监听“添加”按钮的点击事件和输入框的回车事件。- 在事件处理函数中,获取输入框的值,创建新的待办事项对象,并添加到数组中。
- 调用一个渲染函数(
renderTodos()),该函数会清空列表,然后遍历数组,为每个待办事项创建<li>元素并添加到<ul>中。 - 为每个
<li>元素中的“完成”和“删除”按钮绑定事件。
- 本地存储:
- 使用
localStorage.setItem('todos', JSON.stringify(todos))来保存数据。 - 使用
JSON.parse(localStorage.getItem('todos'))来读取数据。 - 在页面加载时,先尝试从
localStorage读取数据,如果有,就用它来初始化待办事项列表。
- 使用
- 筛选功能:监听筛选按钮的点击事件,根据点击的按钮来决定显示哪些待办事项,然后重新调用
renderTodos()。
- 数据模型:使用一个数组来存储待办事项对象,每个对象包含
完整代码
同样是一个单文件 todo-app.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: #4a90e2;
--danger-color: #e74c3c;
--light-bg: #f4f7f6;
--white: #ffffff;
--text-color: #333;
--border-color: #ddd;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Helvetica Neue', Arial, sans-serif;
background-color: var(--light-bg);
color: var(--text-color);
line-height: 1.6;
}
.container {
max-width: 600px;
margin: 2rem auto;
padding: 0 1rem;
}
header {
text-align: center;
margin-bottom: 2rem;
}
h1 {
color: var(--primary-color);
}
.todo-input-container {
display: flex;
margin-bottom: 1.5rem;
}
#todo-input {
flex: 1;
padding: 0.8rem;
border: 1px solid var(--border-color);
border-radius: 5px 0 0 5px;
font-size: 1rem;
outline: none;
}
#todo-input:focus {
border-color: var(--primary-color);
}
#add-btn {
padding: 0.8rem 1.5rem;
background: var(--primary-color);
color: var(--white);
border: none;
border-radius: 0 5px 5px 0;
cursor: pointer;
font-size: 1rem;
transition: background 0.3s ease;
}
#add-btn:hover {
background: #3a7bc8;
}
.filters {
display: flex;
justify-content: center;
margin-bottom: 1.5rem;
gap: 0.5rem;
}
.filter-btn {
padding: 0.5rem 1rem;
border: 1px solid var(--border-color);
background: var(--white);
color: var(--text-color);
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-btn.active {
background: var(--primary-color);
color: var(--white);
border-color: var(--primary-color);
}
#todo-list {
list-style: none;
background: var(--white);
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.todo-item {
display: flex;
align-items: center;
padding: 1rem;
border-bottom: 1px solid var(--border-color);
transition: background 0.3s ease;
}
.todo-item:last-child {
border-bottom: none;
}
.todo-item.completed {
background-color: #e8f5e9;
}
.todo-item.completed .todo-text {
text-decoration: line-through;
color: #888;
}
.todo-text {
flex: 1;
margin-left: 1rem;
}
.todo-actions {
display: flex;
gap: 0.5rem;
}
.complete-btn, .delete-btn {
padding: 0.4rem 0.8rem;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 0.9rem;
transition: background 0.3s ease;
}
.complete-btn {
background: #2ecc71;
color: var(--white);
}
.complete-btn:hover {
background: #27ae60;
}
.delete-btn {
background: var(--danger-color);
color: var(--white);
}
.delete-btn:hover {
background: #c0392b;
}
.empty-state {
text-align: center;
padding: 3rem 1rem;
color: #888;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>我的待办事项</h1>
</header>
<div class="todo-input-container">
<input type="text" id="todo-input" placeholder="添加一个新的待办事项..." autocomplete="off">
<button id="add-btn">添加</button>
</div>
<div class="filters">
<button class="filter-btn active" data-filter="all">全部</button>
<button class="filter-btn" data-filter="active">进行中</button>
<button class="filter-btn" data-filter="completed">已完成</button>
</div>
<ul id="todo-list">
<!-- 待办事项将通过JavaScript动态添加到这里 -->
</ul>
<div id="empty-state" class="empty-state" style="display: none;">
暂无待办事项,添加一个吧!
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// 获取DOM元素
const todoInput = document.getElementById('todo-input');
const addBtn = document.getElementById('add-btn');
const todoList = document.getElementById('todo-list');
const filterBtns = document.querySelectorAll('.filter-btn');
const emptyState = document.getElementById('empty-state');
// 从localStorage加载待办事项
let todos = JSON.parse(localStorage.getItem('todos')) || [];
let currentFilter = 'all';
// 初始化
renderTodos();
// 添加待办事项
function addTodo() {
const text = todoInput.value.trim();
if (text === '') {
alert('请输入待办事项内容!');
return;
}
const newTodo = {
id: Date.now(), // 使用时间戳作为唯一ID
text: text,
completed: false
};
todos.unshift(newTodo); // 添加到数组开头
saveTodos();
renderTodos();
todoInput.value = ''; // 清空输入框
}
// 切换完成状态
function toggleComplete(id) {
todos = todos.map(todo => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed };
}
return todo;
});
saveTodos();
renderTodos();
}
// 删除待办事项
function deleteTodo(id) {
todos = todos.filter(todo => todo.id !== id);
saveTodos();
renderTodos();
}
// 保存到localStorage
function saveTodos() {
localStorage.setItem('todos', JSON.stringify(todos));
}
// 渲染待办事项列表
function renderTodos() {
// 根据当前筛选器过滤待办事项
let filteredTodos = todos;
if (currentFilter === 'active') {
filteredTodos = todos.filter(todo => !todo.completed);
} else if (currentFilter === 'completed') {
filteredTodos = todos.filter(todo => todo.completed);
}
// 清空列表
todoList.innerHTML = '';
if (filteredTodos.length === 0) {
emptyState.style.display = 'block';
} else {
emptyState.style.display = 'none';
filteredTodos.forEach(todo => {
const li = document.createElement('li');
li.className = `todo-item ${todo.completed ? 'completed' : ''}`;
li.innerHTML = `
<span class="todo-text">${todo.text}</span>
<div class="todo-actions">
<button class="complete-btn">${todo.completed ? '撤销' : '完成'}</button>
<button class="delete-btn">删除</button>
</div>
`;
todoList.appendChild(li);
// 为按钮添加事件监听器
li.querySelector('.complete-btn').addEventListener('click', () => toggleComplete(todo.id));
li.querySelector('.delete-btn').addEventListener('click', () => deleteTodo(todo.id));
});
}
}
// 事件监听器
addBtn.addEventListener('click', addTodo);
todoInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addTodo();
}
});
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
// 更新活动按钮状态
filterBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
// 更新当前筛选器并重新渲染
currentFilter = btn.getAttribute('data-filter');
renderTodos();
});
});
});
</script>
</body>
</html>
如何运行
与第一个作业完全相同:复制代码,保存为 todo-app.html,然后用浏览器打开。
可能的进阶方向
- 编辑功能:为待办事项添加“编辑”按钮,点击后可以 inline(行内)编辑文本。
- 计数功能:在页面上显示“已完成”和“未完成”的数量。
- 排序功能:允许用户按创建时间或完成状态排序。
- 美化UI:使用更现代的设计风格,比如添加图标库(如 Font Awesome)。
- 更复杂的本地存储:使用 IndexedDB 替代 localStorage,以支持存储更复杂的数据结构。
希望这两个作业成品能对你有所帮助!祝你学习愉快!

(图片来源网络,侵删)
