项目实战_基础
项目实战_基础
从零构建响应式网页
本章将通过一个实际项目,展示如何应用前面学习的 CSS 和 Sass 知识。我们将创建一个简单的响应式网页,包含导航栏、英雄区、特性展示和页脚等常见组件。
项目结构
project/
├── index.html
├── css/
│ └── main.css
├── scss/
│ ├── _variables.scss
│ ├── _mixins.scss
│ ├── _reset.scss
│ ├── _typography.scss
│ ├── _components.scss
│ ├── _layout.scss
│ └── main.scss
└── images/
└── hero-bg.jpg
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="css/main.css" />
</head>
<body>
<!-- 导航栏 -->
<header class="header">
<div class="container">
<div class="logo">Brand</div>
<nav class="nav">
<button class="nav-toggle" aria-label="Toggle Navigation">
<span></span>
<span></span>
<span></span>
</button>
<ul class="nav-menu">
<li><a href="#" class="nav-link">首页</a></li>
<li><a href="#" class="nav-link">特性</a></li>
<li><a href="#" class="nav-link">价格</a></li>
<li><a href="#" class="nav-link">关于</a></li>
<li><a href="#" class="nav-link btn btn-primary">注册</a></li>
</ul>
</nav>
</div>
</header>
<!-- 英雄区 -->
<section class="hero">
<div class="container">
<div class="hero-content">
<h1>创建美观的响应式网站</h1>
<p>使用现代CSS和Sass技术,轻松构建专业级网站</p>
<div class="hero-buttons">
<a href="#" class="btn btn-primary">开始使用</a>
<a href="#" class="btn btn-outline">了解更多</a>
</div>
</div>
</div>
</section>
<!-- 特性区 -->
<section class="features">
<div class="container">
<h2 class="section-title">核心特性</h2>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">🎨</div>
<h3>现代设计</h3>
<p>采用最新的设计趋势,创造出色的用户体验</p>
</div>
<div class="feature-card">
<div class="feature-icon">📱</div>
<h3>完全响应式</h3>
<p>在任何设备上都能完美展示</p>
</div>
<div class="feature-card">
<div class="feature-icon">⚡</div>
<h3>性能优化</h3>
<p>快速加载,流畅交互</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔧</div>
<h3>易于定制</h3>
<p>简单调整以适应您的品牌</p>
</div>
</div>
</div>
</section>
<!-- 页脚 -->
<footer class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-logo">Brand</div>
<div class="footer-links">
<div class="footer-column">
<h4>产品</h4>
<ul>
<li><a href="#">特性</a></li>
<li><a href="#">价格</a></li>
<li><a href="#">案例</a></li>
</ul>
</div>
<div class="footer-column">
<h4>资源</h4>
<ul>
<li><a href="#">文档</a></li>
<li><a href="#">教程</a></li>
<li><a href="#">博客</a></li>
</ul>
</div>
<div class="footer-column">
<h4>公司</h4>
<ul>
<li><a href="#">关于我们</a></li>
<li><a href="#">联系我们</a></li>
<li><a href="#">招聘</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-bottom">
<p>© 2025 Brand. 保留所有权利。</p>
</div>
</div>
</footer>
<script>
// 简单的导航菜单切换
document
.querySelector(".nav-toggle")
.addEventListener("click", function () {
document.querySelector(".nav-menu").classList.toggle("active");
this.classList.toggle("active");
});
</script>
</body>
</html>
Sass 文件
_variables.scss
// 颜色
$primary-color: #3498db;
$secondary-color: #2ecc71;
$dark-color: #333333;
$light-color: #f4f4f4;
$gray-color: #888888;
$white-color: #ffffff;
// 字体
$font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
$font-sizes: (
small: 0.875rem,
normal: 1rem,
medium: 1.25rem,
large: 1.5rem,
xl: 2rem,
xxl: 3rem,
);
// 布局
$container-width: 1200px;
$gutter: 20px;
// 断点
$breakpoints: (
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
);
// 其他
$border-radius: 4px;
$box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
$transition: all 0.3s ease;
_mixins.scss
// 媒体查询
@mixin respond-to($breakpoint) {
$value: map-get($breakpoints, $breakpoint);
@if $value != null {
@media (max-width: $value) {
@content;
}
} @else {
@error "Unknown breakpoint: #{$breakpoint}.";
}
}
// Flexbox
@mixin flex($direction: row, $justify: flex-start, $align: stretch) {
display: flex;
flex-direction: $direction;
justify-content: $justify;
align-items: $align;
}
// 按钮样式
@mixin button-style($bg-color, $text-color, $hover-darken: 10%) {
background-color: $bg-color;
color: $text-color;
&:hover {
background-color: darken($bg-color, $hover-darken);
}
}
// 卡片样式
@mixin card {
background-color: $white-color;
border-radius: $border-radius;
box-shadow: $box-shadow;
padding: $gutter;
}
_reset.scss
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: $font-family;
line-height: 1.6;
color: $dark-color;
background-color: $white-color;
}
a {
text-decoration: none;
color: $primary-color;
}
ul {
list-style: none;
}
img {
max-width: 100%;
height: auto;
}
_typography.scss
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 700;
line-height: 1.2;
margin-bottom: 1rem;
}
h1 {
font-size: map-get($font-sizes, xxl);
@include respond-to(md) {
font-size: map-get($font-sizes, xl);
}
}
h2 {
font-size: map-get($font-sizes, xl);
@include respond-to(md) {
font-size: map-get($font-sizes, large);
}
}
h3 {
font-size: map-get($font-sizes, large);
}
h4 {
font-size: map-get($font-sizes, medium);
}
p {
margin-bottom: 1rem;
}
.section-title {
text-align: center;
margin-bottom: 2rem;
&::after {
content: "";
display: block;
width: 50px;
height: 3px;
background-color: $primary-color;
margin: 1rem auto 0;
}
}
_components.scss
// 按钮
.btn {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: $border-radius;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: $transition;
border: none;
&-primary {
@include button-style($primary-color, $white-color);
}
&-secondary {
@include button-style($secondary-color, $white-color);
}
&-outline {
background-color: transparent;
border: 2px solid $primary-color;
color: $primary-color;
&:hover {
background-color: $primary-color;
color: $white-color;
}
}
}
// 卡片
.feature-card {
@include card;
text-align: center;
transition: $transition;
&:hover {
transform: translateY(-5px);
}
.feature-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
}
// 导航菜单
.nav-toggle {
display: none;
background: none;
border: none;
cursor: pointer;
span {
display: block;
width: 25px;
height: 3px;
background-color: $dark-color;
margin: 5px 0;
transition: $transition;
}
&.active {
span:nth-child(1) {
transform: rotate(45deg) translate(5px, 5px);
}
span:nth-child(2) {
opacity: 0;
}
span:nth-child(3) {
transform: rotate(-45deg) translate(7px, -6px);
}
}
@include respond-to(md) {
display: block;
}
}
_layout.scss
// 容器
.container {
max-width: $container-width;
margin: 0 auto;
padding: 0 $gutter;
}
// 头部
.header {
padding: 1rem 0;
box-shadow: $box-shadow;
position: sticky;
top: 0;
background-color: $white-color;
z-index: 100;
.container {
@include flex(row, space-between, center);
}
.logo {
font-size: map-get($font-sizes, large);
font-weight: 700;
color: $primary-color;
}
.nav {
@include flex(row, flex-end, center);
.nav-menu {
@include flex(row, flex-end, center);
li {
margin-left: 1.5rem;
}
.nav-link {
color: $dark-color;
font-weight: 500;
transition: $transition;
&:hover {
color: $primary-color;
}
}
}
@include respond-to(md) {
.nav-menu {
position: fixed;
top: 0;
right: -100%;
width: 80%;
max-width: 300px;
height: 100vh;
background-color: $white-color;
@include flex(column, flex-start, flex-start);
padding: 5rem 2rem;
box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);
transition: $transition;
&.active {
right: 0;
}
li {
margin: 1rem 0;
width: 100%;
}
.nav-link {
display: block;
padding: 0.5rem 0;
}
}
}
}
}
// 英雄区
.hero {
background-image: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)),
url("../images/hero-bg.jpg");
background-size: cover;
background-position: center;
color: $white-color;
padding: 5rem 0;
.hero-content {
max-width: 600px;
h1 {
margin-bottom: 1rem;
}
p {
font-size: map-get($font-sizes, medium);
margin-bottom: 2rem;
}
.hero-buttons {
.btn {
margin-right: 1rem;
margin-bottom: 1rem;
}
}
}
@include respond-to(md) {
text-align: center;
.hero-content {
margin: 0 auto;
}
}
}
// 特性区
.features {
padding: 5rem 0;
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: $gutter;
}
}
// 页脚
.footer {
background-color: $dark-color;
color: $light-color;
padding: 3rem 0 1rem;
.footer-content {
@include flex(row, space-between, flex-start);
margin-bottom: 2rem;
.footer-logo {
font-size: map-get($font-sizes, large);
font-weight: 700;
color: $white-color;
}
.footer-links {
@include flex(row, flex-end, flex-start);
flex-wrap: wrap;
.footer-column {
margin-left: 3rem;
h4 {
color: $white-color;
margin-bottom: 1rem;
}
ul li {
margin-bottom: 0.5rem;
a {
color: $light-color;
transition: $transition;
&:hover {
color: $primary-color;
}
}
}
}
}
}
.footer-bottom {
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 1rem;
text-align: center;
font-size: map-get($font-sizes, small);
}
@include respond-to(md) {
.footer-content {
flex-direction: column;
.footer-logo {
margin-bottom: 2rem;
}
.footer-links {
justify-content: flex-start;
.footer-column {
margin-left: 0;
margin-right: 2rem;
margin-bottom: 2rem;
}
}
}
}
}
main.scss
// 导入变量和混合
@import "variables";
@import "mixins";
// 导入基础样式
@import "reset";
@import "typography";
// 导入组件和布局
@import "components";
@import "layout";
编译 Sass
使用命令行编译 Sass:
# 安装Sass
npm install -g sass
# 编译
sass scss/main.scss css/main.css
# 监视文件变化
sass --watch scss/main.scss:css/main.css
项目要点
- 模块化结构:将样式分成多个文件,便于维护
- 响应式设计:使用媒体查询适配不同设备
- 组件化思想:创建可复用的 UI 组件
- Sass 功能应用:变量、混合、嵌套等
- 性能考虑:优化选择器和样式
这个项目展示了如何将前面学习的 CSS 和 Sass 知识应用到实际开发中,创建一个完整的响应式网页。