Web 前端技术 第 4 周

CSS视觉设计与布局

系统介绍 CSS 基础语法、选择器、盒模型、Flex 与 Grid 布局、Tailwind CSS 响应式框架及 CSS 动画,帮助读者构建专业新闻页面的完整视觉设计能力。

2026-03-24 第 4 周

学习要点

  • 掌握 CSS 基础语法与常用选择器的书写规则及优先级计算方法
  • 理解盒模型的构成原理,能够运用 Flexbox 与 Grid 完成多列新闻页面布局
  • 了解 Tailwind CSS 的实用类体系,掌握响应式断点的配置与应用方式
  • 能够使用 CSS 过渡与动画为新闻交互页面添加视觉反馈效果

正文

CSS 基础语法与选择器

CSS(层叠样式表,Cascading Style Sheets)是一种专门用于描述 HTML 文档视觉表现的样式语言,负责控制页面的颜色、字体、间距与排版等全部外观属性。一条 CSS 规则由选择器(selector)和声明块(declaration block)两部分组成,声明块内每条声明由属性名(property)与属性值(value)以冒号分隔构成。

1
2
3
4
/* 基本规则结构 */
选择器 {
  属性名: 属性值;
}

可以将选择器理解为报纸的"版面编辑指令"——编辑在付印前标注"所有头条新闻用黑体加粗",CSS 选择器同样针对特定元素批量施加样式。CSS 提供了从粗粒度到细粒度的多层次选择机制:

  • 元素选择器:直接以 HTML 标签名为目标,如 p { } 选中页面所有段落。
  • 类选择器:以 .类名 形式书写,选中所有携带该 class 属性的元素,是新闻页面中最常用的选择方式,例如为"突发新闻"标签统一设置红色背景。
  • ID 选择器:以 #id名 形式书写,具有唯一性,通常用于页面主导航或主内容区等单一区块。
  • 后代与子代选择器article p 选中 article 内所有后代段落;article > p 仅选中直接子级段落,适合精确控制新闻卡片内部的文字层级。
  • 伪类选择器:hover:first-child:nth-child() 等,可在元素处于特定状态或位置时触发样式,例如鼠标悬停于新闻标题时改变颜色。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
/* 新闻卡片选择器示例 */
.news-card {               /* 类选择器:所有新闻卡片 */
  background: #fff;
  border-radius: 4px;
}

.news-card h2 {            /* 后代选择器:卡片内标题 */
  font-size: 1.25rem;
  color: #1a1a1a;
}

.news-card:hover {         /* 伪类:悬停时高亮 */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

#breaking-news {           /* ID 选择器:突发新闻专区 */
  border-left: 4px solid #e63946;
}

CSS 规则存在**优先级(specificity)**机制:ID 选择器 > 类选择器 > 元素选择器,同等优先级下后声明的规则覆盖先声明的规则,此即"层叠"的核心含义。!important 声明可强制提升优先级,但应谨慎使用,以免破坏样式的可维护性。

盒模型与文本样式

CSS 盒模型(Box Model)是所有布局计算的基础,每个 HTML 元素在渲染时都被视为一个矩形盒子,由内到外依次由四层构成:内容区(content)内边距(padding)边框(border)外边距(margin)

类比报纸的版面设计:内容区是文章正文所占的文字区域,内边距是正文与边框之间留出的"透气"空白,边框是版面切割线,外边距则是两篇文章之间保持的版面间距。理解这四层结构是解决"元素为什么不对齐""两个区块之间为什么有多余空白"等常见问题的前提。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/* 盒模型示意 */
.article-card {
  width: 320px;            /* 内容区宽度 */
  padding: 16px 20px;      /* 内边距:上下16px,左右20px */
  border: 1px solid #ddd;  /* 边框 */
  margin: 0 0 24px 0;      /* 外边距:底部24px,其余为0 */

  /* box-sizing 决定 width 的计算范围 */
  /* border-box 模式下 width 包含 padding 和 border,推荐使用 */
  box-sizing: border-box;
}

默认情况下 box-sizing 的值为 content-box,即 width 仅指内容区宽度,加上 padding 和 border 后实际占据空间更大,这往往导致布局计算困难。将其设置为 border-box 后,width 即为元素在页面上实际占据的总宽度,现代项目通常在全局统一设置:

1
2
3
*, *::before, *::after {
  box-sizing: border-box;  /* 全局启用 border-box 模式 */
}

文本样式是新闻网站视觉设计的核心关切,常用属性如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
.article-body {
  font-family: "Georgia", "宋体", serif; /* 字体族:衬线体适合正文阅读 */
  font-size: 1rem;                        /* 字号:1rem = 浏览器基础字号(通常16px)*/
  line-height: 1.8;                       /* 行高:新闻正文建议1.6-1.8 */
  color: #333333;                         /* 正文颜色:非纯黑,减少视觉疲劳 */
  letter-spacing: 0.02em;                 /* 字距:中文正文可微调 */
  text-align: justify;                    /* 两端对齐:报纸排版惯例 */
}

.article-title {
  font-weight: 700;                       /* 字重:标题加粗 */
  font-size: clamp(1.5rem, 3vw, 2.5rem);  /* 流体字号:随视口宽度响应缩放 */
  line-height: 1.3;                       /* 标题行高应小于正文 */
}

Flexbox 布局

Flexbox(弹性盒子布局)是一种一维布局模型,能够沿主轴(水平或垂直)方向对子元素进行排列、对齐与空间分配。在父元素上声明 display: flex 即可激活弹性容器,其直接子元素自动成为弹性项目(flex items)。

Flexbox 特别适合新闻网站中"导航栏、文章元数据行、卡片内部内容对齐"等一维排列场景,因为它能够以极少的代码实现过去需要 float 或绝对定位才能完成的布局效果。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/* 新闻导航栏:标题左对齐,导航链接右对齐 */
.site-header {
  display: flex;
  justify-content: space-between; /* 主轴:两端分布 */
  align-items: center;            /* 交叉轴:垂直居中 */
  padding: 0 24px;
  height: 60px;
  background: #1a1a2e;
}

/* 文章卡片列表:三列等宽排列 */
.news-grid {
  display: flex;
  flex-wrap: wrap;      /* 超出宽度时自动换行 */
  gap: 20px;            /* 卡片间距(替代 margin 计算) */
}

.news-grid .news-card {
  flex: 1 1 280px;      /* 可伸缩,最小宽度280px,自动分配剩余空间 */
}

justify-content 控制主轴方向的对齐方式(flex-startcenterspace-betweenspace-around 等),align-items 控制交叉轴方向的对齐方式。flex 简写属性的三个值依次为 flex-grow(伸展比例)、flex-shrink(收缩比例)、flex-basis(基础尺寸),是实现弹性等分布局的关键。

Grid 布局

CSS Grid 是二维布局系统,能够同时控制行与列两个方向,是构建复杂新闻版面的首选工具。可以将 Grid 类比为报纸的"网格系统"——传统报纸排版同样依赖固定的列数和行单元来组织头条、图片与侧栏的空间关系。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/* 经典新闻首页布局:左宽主内容 + 右侧边栏 */
.page-layout {
  display: grid;
  grid-template-columns: 1fr 300px;   /* 两列:主内容弹性占满,侧栏固定300px */
  grid-template-rows: auto 1fr auto;  /* 三行:页眉、主体、页脚 */
  grid-template-areas:
    "header  header"    /* 页眉跨两列 */
    "main    sidebar"   /* 主内容与侧栏并排 */
    "footer  footer";   /* 页脚跨两列 */
  gap: 24px;
  min-height: 100vh;
}

.site-header  { grid-area: header; }
.main-content { grid-area: main; }
.sidebar      { grid-area: sidebar; }
.site-footer  { grid-area: footer; }

grid-template-areas 通过直观的文本地图定义区域分配,极大提升了布局代码的可读性。fr 单位(fraction)代表网格容器剩余空间的一份,1fr 1fr 1fr 即三等分,相当于传统报纸的三栏版式。minmax(min, max) 函数可为列宽设置弹性范围:

1
2
3
4
5
6
/* 自适应多列卡片网格:每列最小200px,最大1fr */
.article-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

auto-fillminmax 组合使网格列数随容器宽度自动增减,无需任何 JavaScript 即可实现响应式卡片列表,是新闻聚合页面的常见实现模式。

Tailwind CSS 与响应式设计

Tailwind CSS 是一个以"实用优先"(utility-first)为核心理念的 CSS 框架,它将常见样式属性拆解为数百个原子化 class,开发者通过在 HTML 元素上组合 class 名称来实现设计,而非编写自定义 CSS 文件。对比传统框架(如 Bootstrap)的"组件预设"思路,Tailwind 更接近于给编辑提供了一套完整的"排版符号体系"——每个符号含义固定,随意组合即可排出任意版式,而非只能套用固定的"头版模板"。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!-- 传统 CSS 写法 -->
<div class="news-card">
  <h2 class="card-title">人工智能新闻摘要工具上线</h2>
</div>

<!-- Tailwind 写法:样式即 class -->
<div class="bg-white rounded-lg shadow-md p-5 hover:shadow-xl transition-shadow">
  <h2 class="text-xl font-bold text-gray-800 leading-tight">
    人工智能新闻摘要工具上线
  </h2>
</div>

响应式设计(Responsive Design)使页面能够根据设备视口宽度自动调整布局,Tailwind 通过断点前缀实现这一机制,默认断点为:sm(640px)、md(768px)、lg(1024px)、xl(1280px)。前缀意为"在该断点及以上时生效",体现移动优先(mobile-first)原则:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!-- 响应式新闻列表:手机单列、平板双列、桌面三列 -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
  <article class="bg-white rounded p-4">
    <img class="w-full h-48 object-cover rounded" src="cover.jpg" alt="新闻配图">
    <span class="text-xs text-red-600 font-semibold uppercase mt-2 block">
      突发新闻
    </span>
    <h2 class="text-lg font-bold mt-1 text-gray-900">新闻标题</h2>
    <p class="text-sm text-gray-500 mt-2">发布时间 · 作者姓名</p>
  </article>
</div>

CSS 过渡与动画

CSS 过渡(transition)和动画(animation)为界面交互提供视觉连续性。过渡作用于属性的状态变化过程,通常与 :hover:focus 等伪类配合使用;动画则通过 @keyframes 定义完整的时间轴,可独立运行无需用户触发。

在新闻网站中,合理的过渡效果能够模拟印刷媒体中"视觉层级引导"的功能——当读者的注意力移向某条新闻时,卡片的微妙抬升效果传递出"此处可交互"的信号。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* 新闻卡片悬停过渡 */
.news-card {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(0,0,0,0.08);
  /* transition: 属性 时长 缓动函数 延迟 */
  transition: transform 0.25s ease-out,
              box-shadow 0.25s ease-out;
}

.news-card:hover {
  transform: translateY(-4px);              /* 向上位移4px,产生悬浮感 */
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);  /* 投影加深 */
}

/* 突发新闻标签闪烁动画 */
@keyframes blink-badge {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.4; }
}

.badge-breaking {
  animation: blink-badge 1.4s ease-in-out infinite; /* 无限循环播放 */
  background: #e63946;
  color: #fff;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 0.75rem;
  font-weight: 700;
}

animation 简写属性的常用参数依次为:动画名称、持续时间、缓动函数、延迟时间、循环次数(infinite 为无限循环)、方向(alternate 为正反交替播放)。过度使用动画会干扰读者阅读,在新闻类网站中动画应服务于信息传达,而非单纯追求视觉效果。

实践示例

场景:为一家网络新闻媒体构建一个响应式新闻首页卡片区,包含页眉导航、三列新闻卡片网格,以及卡片的悬停动效。

目标:综合运用 Flexbox(导航栏)、Grid(卡片区)、CSS 过渡(悬停动效)和响应式断点,完成一个可直接在浏览器运行的完整页面结构。

实现步骤

第一步:建立 HTML 骨架

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <!-- viewport meta 是响应式设计的必要声明 -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>新闻速报</title>
  <link rel="stylesheet" href="news.css">
</head>
<body>
  <!-- 页眉导航 -->
  <header class="site-header">
    <div class="logo">新闻速报</div>
    <nav class="main-nav">
      <a href="#">首页</a>
      <a href="#">国际</a>
      <a href="#">科技</a>
      <a href="#">文化</a>
    </nav>
  </header>

  <!-- 主体内容 -->
  <main class="page-main">
    <h1 class="section-title">今日头条</h1>

    <!-- 新闻卡片网格 -->
    <div class="card-grid">
      <!-- 第一张卡片 -->
      <article class="news-card">
        <div class="card-image" style="background:#c9d6df;"></div>
        <div class="card-body">
          <span class="card-category breaking">突发</span>
          <h2 class="card-title">全球气候峰会达成关键协议</h2>
          <p class="card-excerpt">
            与会各国就2035年碳排放目标达成约束性共识,
            被誉为近十年最重要的气候外交突破。
          </p>
          <p class="card-meta">2026-03-24 · 国际部</p>
        </div>
      </article>

      <!-- 第二张卡片 -->
      <article class="news-card">
        <div class="card-image" style="background:#e0c3fc;"></div>
        <div class="card-body">
          <span class="card-category">科技</span>
          <h2 class="card-title">AI 编辑系统在多家媒体试点上线</h2>
          <p class="card-excerpt">
            大型语言模型辅助新闻核查工具进入实际编辑流程,
            准确率较人工初审提升约40%。
          </p>
          <p class="card-meta">2026-03-24 · 科技部</p>
        </div>
      </article>

      <!-- 第三张卡片 -->
      <article class="news-card">
        <div class="card-image" style="background:#ffecd2;"></div>
        <div class="card-body">
          <span class="card-category">文化</span>
          <h2 class="card-title">国家博物馆数字展厅正式对公众开放</h2>
          <p class="card-excerpt">
            采用三维实景扫描技术还原千件文物,
            用户可在线进行沉浸式参观体验。
          </p>
          <p class="card-meta">2026-03-23 · 文化部</p>
        </div>
      </article>
    </div>
  </main>
</body>
</html>

第二步:全局重置与基础变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* news.css */

/* 全局 box-sizing 重置 */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* CSS 自定义属性(变量):统一管理品牌色彩与间距 */
:root {
  --color-primary: #1a1a2e;   /* 主色:深蓝,用于页眉与标题 */
  --color-accent:  #e63946;   /* 强调色:红色,用于突发标签 */
  --color-text:    #2d2d2d;   /* 正文颜色 */
  --color-muted:   #6b7280;   /* 辅助文字颜色 */
  --radius:        8px;       /* 圆角统一规格 */
  --transition:    0.25s ease-out;
}

body {
  font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", sans-serif;
  background: #f5f5f5;
  color: var(--color-text);
  line-height: 1.6;
}

第三步:页眉导航(Flexbox)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* 页眉:Flexbox 两端对齐 */
.site-header {
  display: flex;
  justify-content: space-between;  /* Logo 左,导航右 */
  align-items: center;
  padding: 0 24px;
  height: 64px;
  background: var(--color-primary);
  position: sticky;               /* 页眉固定在顶部 */
  top: 0;
  z-index: 100;
}

.logo {
  font-size: 1.4rem;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.05em;
}

.main-nav {
  display: flex;
  gap: 28px;
}

.main-nav a {
  color: rgba(255, 255, 255, 0.8);
  text-decoration: none;
  font-size: 0.95rem;
  transition: color var(--transition);
}

.main-nav a:hover {
  color: #fff;  /* 悬停时导航链接变为纯白 */
}

第四步:卡片网格(Grid + 响应式)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.page-main {
  max-width: 1100px;
  margin: 0 auto;      /* 水平居中 */
  padding: 32px 16px;
}

.section-title {
  font-size: 1.5rem;
  font-weight: 700;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--color-primary);
}

/* 响应式网格:手机1列 → 平板2列 → 桌面3列 */
.card-grid {
  display: grid;
  grid-template-columns: 1fr;     /* 默认单列(移动端) */
  gap: 20px;
}

/* 视口宽度 ≥ 600px 时切换为两列 */
@media (min-width: 600px) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* 视口宽度 ≥ 900px 时切换为三列 */
@media (min-width: 900px) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

第五步:新闻卡片样式与悬停动效

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
.news-card {
  background: #fff;
  border-radius: var(--radius);
  overflow: hidden;               /* 圆角裁切图片 */
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.07);
  /* 过渡:transform 和 box-shadow 同步变化 */
  transition: transform var(--transition),
              box-shadow var(--transition);
}

/* 悬停:卡片上浮 + 投影加深 */
.news-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.13);
}

.card-image {
  width: 100%;
  height: 180px;                  /* 图片占位区域固定高度 */
}

.card-body {
  padding: 16px;
}

/* 分类标签 */
.card-category {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-primary);
  background: #e8eaf6;
  padding: 2px 8px;
  border-radius: 3px;
  margin-bottom: 8px;
}

/* 突发标签:闪烁动画 */
@keyframes pulse-badge {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.5; }
}

.card-category.breaking {
  color: #fff;
  background: var(--color-accent);
  animation: pulse-badge 1.6s ease-in-out infinite;
}

.card-title {
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.45;
  margin-bottom: 8px;
  color: var(--color-text);
}

.card-excerpt {
  font-size: 0.9rem;
  color: #4b5563;
  line-height: 1.7;
  margin-bottom: 12px;

  /* 限制最多显示三行,超出省略 */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-meta {
  font-size: 0.78rem;
  color: var(--color-muted);
}

效果说明:页面顶部显示深蓝色固定导航栏,Logo 位于左侧,导航链接右对齐;链接悬停时以平滑过渡变为纯白。主内容区在手机上呈单列排列,平板(≥600px)自动扩展为两列,桌面(≥900px)变为三列,无需刷新即可在浏览器开发者工具的设备模拟模式下直接观察切换效果。第一张卡片携带红色闪烁的"突发"标签,视觉权重明显高于其余卡片。所有卡片在鼠标悬停时以0.25秒缓动动画平滑上浮6像素,投影随之加深,清晰传达可点击信号。

练习

  1. 基础练习:在实践示例的基础上,为页面添加一个页脚(<footer>),包含版权信息与三个社交媒体链接。要求使用 Flexbox 使链接在页脚内水平居中排列,并为链接添加颜色过渡效果,悬停时变为媒体品牌色(可自定义)。

  2. 进阶练习:将卡片网格改用 Tailwind CSS 重写(引入 Tailwind CDN),对比两种写法在代码组织方式上的差异,并说明在哪种项目场景下更适合使用 Tailwind,哪种场景更适合编写自定义 CSS,写出不少于150字的对比分析注释。

  3. 综合练习:参照真实新闻网站(如《卫报》guardian.com 或《纽约时报》nytimes.com),选取其首页某一版块进行视觉分析:识别该版块使用了哪种布局模型(Flex 或 Grid),估算其网格列数与间距规律,并用 CSS 编写一个结构与视觉风格相近的仿制版块,配合一份不少于300字的设计说明,解释你在颜色、字体、间距和动效方面的设计决策与对应的新闻传播逻辑。

本章小结

  • CSS 选择器与优先级:CSS 通过元素、类、ID 及伪类等多层选择器定位目标元素,优先级由特异性值决定,层叠规则确保多条规则可预测地合并。
  • 盒模型:每个元素由内容区、内边距、边框、外边距四层构成,box-sizing: border-box 使宽度计算更直观,是现代布局的基础前提。
  • Flexbox 与 Grid:Flexbox 擅长一维(导航、卡片内部)排列,Grid 擅长二维(整体页面、卡片网格)布局,两者通常配合使用以覆盖不同层级的排版需求。
  • Tailwind CSS 与响应式:Tailwind 以原子化 class 实现样式,结合移动优先断点前缀(sm:md:lg:)可快速构建跨设备响应式页面。
  • CSS 过渡与动画transition 为状态切换提供平滑时间过程,@keyframes 定义独立运行的动画,两者均应服务于信息传达,而非过度装饰。

延伸阅读