CSS 练习题(15 题)

学了那么多属性,得动手写才算真的会。这一页给 15 道精心挑选的练习题,按难度分三级——基础 6 题(文本 / 字体 / 颜色 / 边框)、进阶 5 题(Flexbox / Grid / 响应式)、实战 4 题(组件与动画)。每题都含题目描述、提示、可折叠的参考答案。

使用建议:先别急着展开答案。读题后自己打开本地项目或 CodePen 试着写,卡住了再看提示,实在写不出再对照参考答案。CSS 同一效果常常有多种写法,你的写法可能比参考更好——能跨浏览器、视觉对、可维护就是好代码。

基础(6 题):文本 / 字体 / 颜色 / 边框

这一组覆盖最基础的视觉属性,目标是用最短的代码做出一个清晰可读的视觉块,训练"把设计稿翻译成 CSS"的能力。

第 1 题:文本水平垂直居中

题目:一个固定高度 100px 的盒子,内部一行文字要求水平、垂直都居中。提示:本问只考虑单行。

提示:水平居中用 text-align: center;单行垂直居中的经典技巧是把 line-height 设成等于容器高度(这里 100px)。

参考答案
/* HTML: <div class="box">一行文字</div> */
.box {
  height: 100px;            /* 固定高度才能用 line-height 居中 */
  line-height: 100px;       /* 等于容器高度,文字垂直居中 */
  text-align: center;       /* 水平居中 */
  border: 1px solid #ddd;
}
/* 渲染:边框盒子里的文字水平垂直居中(仅适用单行) */

第 2 题:字体样式

题目:给一段正文设置 16px、1.6 倍行距、深灰色(#333),并使用跨平台可读的中文字体栈(优先苹方 / 微软雅黑)。

提示:用 font-family 写一个字体栈(逗号分隔,带空格的字体名加引号),最后兜底 sans-serif;line-height: 1.6 是无单位写法,会按当前字号倍数计算;正文颜色避免纯黑 #000,#333 更柔和。

参考答案
/* HTML: <p class="body">正文段落</p> */
.body {
  font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 16px;
  line-height: 1.6;         /* 1.6 倍行距,正文常用 */
  color: #333;              /* 不用纯黑 #000,接近黑更柔和 */
}
/* 渲染:16px 中文无衬线字体、1.6 行距的深灰正文 */

第 3 题:圆角边框 + 盒子阴影

题目:做一张白底卡片——圆角 8px、柔和阴影、内边距 16px。

提示:border-radius: 8px 控制圆角半径;box-shadow 偏移格式是 x偏移 y偏移 模糊半径 颜色;用 rgba(0,0,0,.1) 而非纯黑能让阴影更自然。

参考答案
/* HTML: <div class="card">内容</div> */
.card {
  border-radius: 8px;                  /* 圆角半径 */
  box-shadow: 0 2px 8px rgba(0,0,0,.1); /* x偏移 y偏移 模糊 半透明黑 */
  padding: 16px;
  background: #fff;
}
/* 渲染:一张白底圆角、带柔和阴影的卡片 */

第 4 题:背景渐变

题目:给一个横幅盒子设置 135° 方向、从 #667eea 到 #764ba2 的渐变背景,白字居中。

提示:linear-gradient(角度, 起色, 终色);角度单位是 deg,135deg 是从左上到右下;可加 0% / 100% 位置精确控制;background 简写或 background-image 都行。

参考答案
/* HTML: <div class="banner">横幅</div> */
.banner {
  /* linear-gradient(方向, 起色, 终色) */
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  padding: 32px;
  text-align: center;
}
/* 渲染:135deg 紫蓝斜向渐变的彩色横幅 */

第 5 题:hover 状态变色(transition)

题目:做一个蓝色按钮,鼠标悬停时背景变深(#2563eb)、整体上浮 2px,且颜色变化要平滑过渡(不要瞬间跳变)。

提示:transition: 属性 时长 声明要过渡的属性(可多个,逗号分隔);:hover 伪类里写悬停状态;transform: translateY(-2px) 比改 top 更适合做小位移(不触发重排)。

参考答案
/* HTML: <button class="btn">按钮</button> */
.btn {
  background: #4f8cff;
  color: #fff;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  /* transition 让颜色变化平滑过渡,而非瞬间跳变 */
  transition: background 0.2s, transform 0.2s;
}
.btn:hover {
  background: #2563eb;        /* hover 时变深 */
  transform: translateY(-2px); /* 上浮 2px */
}
/* 渲染:蓝色按钮,hover 时变深且上浮,过渡平滑 */

第 6 题:列表去圆点

题目:把 <ul> 默认的圆点去掉,并改成水平排列的菜单项。

提示:list-style: none 去圆点(同时清掉 padding: 0 才能去掉默认左缩进);display: inline-block 让 <li> 横向排;现代写法是把 ul 设为 display: flex 配 gap。

参考答案
/* HTML:
   <ul class="menu">
     <li>首页</li>
     <li>关于</li>
   </ul> */
.menu {
  list-style: none;   /* 去掉默认圆点 */
  padding: 0;         /* 同步清掉默认左缩进 */
  margin: 0;
}
.menu li {
  display: inline-block;   /* 改成水平排列 */
  margin-right: 16px;
}
/* 渲染:无圆点的水平菜单项 */

进阶(5 题):Flexbox / Grid / 响应式

这一组开始组合布局模型——用 Flexbox 做对齐、用 Grid 做二维布局、用 media query 做响应式。做完了你会对"现代 CSS 布局"有直观感受,告别 float 和 table 时代。

第 7 题:Flexbox 水平垂直居中

题目:用 Flexbox 让一个子盒子在父容器内水平、垂直都居中。这是 Flexbox 最经典的用法,比第 1 题的 line-height 技巧更通用(支持任意内容)。

提示:父容器 display: flex;justify-content: center 控制主轴(默认水平);align-items: center 控制交叉轴(默认垂直)。两行代码搞定任意内容的居中。

参考答案
/* HTML: <div class="wrap"><div class="box">居中</div></div> */
.wrap {
  display: flex;
  justify-content: center;  /* 主轴(默认水平)居中 */
  align-items: center;      /* 交叉轴(默认垂直)居中 */
  height: 200px;
  border: 1px dashed #999;
}
.box { background: #4f8cff; color: #fff; padding: 16px; }
/* 渲染:小盒子在虚线容器内水平垂直居中 */

第 8 题:两栏布局

题目:左侧固定宽度 200px 的侧栏,右侧自适应宽度的主区。整行用 Flex 实现。

提示:父容器 display: flex;侧栏 width: 200px + flex-shrink: 0(防止被压缩);主区 flex: 1(等价于 flex-grow:1; flex-shrink:1; flex-basis:0%)自动占满剩余空间。

参考答案
/* HTML:
   <div class="layout">
     <aside class="side">侧栏</aside>
     <main class="main">主区</main>
   </div> */
.layout { display: flex; }
.side {
  width: 200px;
  flex-shrink: 0;          /* 防止侧栏被压缩 */
  background: #f0f0f0;
}
.main {
  flex: 1;                 /* 占满剩余宽度 */
  background: #fff;
  padding: 16px;
}
/* 渲染:左侧 200px 固定灰底,右侧自适应宽度的白色主区 */

第 9 题:CSS Grid 三栏

题目:用 CSS Grid 做三栏布局——左 200px、中间弹性、右 200px。

提示:display: grid + grid-template-columns: 200px 1fr 200px 一行搞定;1fr 是"剩余空间的 1 份",Grid 比 Flex 更适合做这种"二维、定宽 + 弹性混合"的布局。

参考答案
/* HTML:
   <div class="grid3">
     <div>左</div><div>中</div><div>右</div>
   </div> */
.grid3 {
  display: grid;
  /* 三列:200px 固定 / 1fr 弹性 / 200px 固定 */
  grid-template-columns: 200px 1fr 200px;
  min-height: 200px;
}
.grid3 > div {
  border: 1px solid #ccc;
  padding: 16px;
}
/* 渲染:左 200px / 中间弹性 / 右 200px 的三栏布局 */

第 10 题:响应式 media query

题目:做一排卡片——手机默认 1 列,桌面(>=768px)切换为 3 列。窗口缩放时自动切换列数。

提示:@media (min-width: 768px) { ... } 是断点;"移动优先"写法是默认写手机样式、用 min-width 向上叠加桌面样式;grid-template-columns 在断点里覆盖即可。

参考答案
/* HTML:
   <div class="cards">
     <div class="card">1</div>
     <div class="card">2</div>
     <div class="card">3</div>
     <div class="card">4</div>
   </div> */
.cards {
  display: grid;
  grid-template-columns: repeat(1, 1fr); /* 手机默认 1 列 */
  gap: 12px;
}
/* 桌面(>=768px)切换为 3 列 */
@media (min-width: 768px) {
  .cards { grid-template-columns: repeat(3, 1fr); }
}
/* 渲染:手机单列、桌面三列的卡片网格,窗口缩放自动切换 */

第 11 题:绝对定位居中

题目:用绝对定位(position: absolute)让一个固定尺寸的子盒子在父容器内水平垂直居中。给两种写法。

提示:写法一:inset: 0 + margin: auto(需要子盒子有明确宽高);写法二:top: 50%; left: 50%; transform: translate(-50%, -50%)(无需知道尺寸)。父级必须 position: relative 当定位上下文。

参考答案
/* HTML:
   <div class="parent">
     <div class="child">居中</div>
   </div> */
.parent {
  position: relative;      /* 父级 relative 子级才能 absolute */
  height: 300px;
  border: 1px solid #ddd;
}
.child {
  position: absolute;
  inset: 0;                /* top/right/bottom/left 全为 0 */
  margin: auto;            /* 自动分配剩余空间,实现居中 */
  width: 120px; height: 60px;
  background: #4f8cff;
  color: #fff;
  /* 另一种写法:transform 居中(不需要 inset/margin) */
  /* top: 50%; left: 50%; transform: translate(-50%, -50%); */
}
/* 渲染:子盒子在父容器水平垂直居中 */

实战(4 题):组件与动画

这一组每题都会综合用到多个属性——圆角、阴影、渐变、过渡、动画、响应式——做出一个接近真实场景的小组件。建议每题都完整跑一遍,再想想怎么扩展。

第 12 题:卡片组件(圆角 + 阴影 + 渐变 + 内边距)

题目:做一个"价格卡片"组件——圆角 12px、淡紫渐变底、柔和阴影、24px 内边距;价格数字加粗加大,主色调。鼠标悬停时整体上浮。

提示:把第 3、4、5 题的技巧合起来——border-radius + box-shadow + linear-gradient + transition;悬停时改 transform 和加深 box-shadow;价格用更大 font-size 和品牌色突出。

参考答案
/* HTML:
   <article class="price-card">
     <h3>Pro</h3>
     <p class="price">¥99/月</p>
     <ul><li>不限流量</li><li>优先支持</li></ul>
   </article> */
.price-card {
  border-radius: 12px;
  padding: 24px;
  background: linear-gradient(135deg, #fff 0%, #f5f7ff 100%);
  box-shadow: 0 8px 24px rgba(79,140,255,.15);
  transition: transform 0.2s, box-shadow 0.2s;
}
.price-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(79,140,255,.25);
}
.price-card .price {
  font-size: 32px;
  color: #4f8cff;
  margin: 12px 0;
}
/* 渲染:一张圆角渐变底带阴影的价格卡片,hover 时上浮 */

第 13 题:响应式导航栏(flex + media query 折叠)

题目:做一个深色导航栏——左侧 Logo、右侧水平菜单,两端对齐;手机端(<768px)隐藏菜单(实战会用汉堡按钮触发,这里只做样式)。

提示:父级 display: flex + justify-content: space-between 实现两端对齐;菜单 display: flex + gap 简化项间距;@media (max-width: 768px) 里把菜单 display: none(注意移动优先建议用 min-width,这里用 max-width 是为了"桌面默认显,移动端隐藏"的逻辑更直观)。

参考答案
/* HTML:
   <nav class="navbar">
     <span class="brand">Logo</span>
     <ul class="links">
       <li>首页</li><li>产品</li><li>关于</li>
     </ul>
   </nav> */
.navbar {
  display: flex;
  justify-content: space-between; /* 两端对齐:Logo 左,菜单右 */
  align-items: center;
  padding: 12px 20px;
  background: #1e293b;
  color: #fff;
}
.links {
  display: flex;
  gap: 16px;               /* gap 替代 margin 写法更简洁 */
  list-style: none;
  padding: 0;
  margin: 0;
}
/* 手机(<768px)隐藏菜单链接(实战加汉堡按钮) */
@media (max-width: 768px) {
  .links { display: none; }
}
/* 渲染:桌面两端对齐的深色导航,手机隐藏菜单 */

第 14 题:网格卡片响应布局(grid repeat + auto-fill + minmax)

题目:做一排响应式卡片——每张最小 200px,窗口变宽时自动加列、变窄时自动减列,不需要任何 media query。

提示:核心是 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));auto-fill 让浏览器自动算能放几列;minmax(最小, 最大) 控制每列的弹性范围。这一行就实现了无断点的真响应式。

参考答案
/* HTML:
   <div class="auto-grid">
     <div class="card">1</div>
     <div class="card">2</div>
     <div class="card">3</div>
     <div class="card">4</div>
     <div class="card">5</div>
   </div> */
.auto-grid {
  display: grid;
  /* auto-fill 自动填充列;
     minmax(最小, 最大) 控制每列弹性范围 */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}
.card {
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 16px;
}
/* 渲染:每张卡片宽度 >=200px 自动填满,窗口变宽自动加列,变窄自动减列 */

第 15 题:纯 CSS 动画按钮(@keyframes + hover transition)

题目:做一个胶囊形按钮——背景蓝色、常态有"呼吸光晕"动画(@keyframes 循环),鼠标悬停时变深、上浮、发光更强。

提示:胶囊形用 border-radius: 999px(远大于高度的一半);常驻动画 animation: pulse 2s infinite;@keyframes pulse 用 box-shadow 的扩散半径做呼吸;:hover 用 transition 平滑过渡到目标态。

参考答案
/* HTML: <button class="glow">点我</button> */
.glow {
  padding: 10px 24px;
  border: none;
  border-radius: 999px;     /* 完全圆角=胶囊形 */
  color: #fff;
  background: #4f8cff;
  cursor: pointer;
  transition: all 0.3s ease;
  animation: pulse 2s infinite; /* 常驻动画:2 秒一次循环 */
}
.glow:hover {
  background: #2563eb;
  transform: translateY(-3px);
  box-shadow: 0 6px 20px rgba(79,140,255,.4);
}
/* @keyframes 定义动画的关键帧 */
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(79,140,255,.5); }
  50%      { box-shadow: 0 0 0 10px rgba(79,140,255,0); }
}
/* 渲染:呼吸光晕的胶囊按钮,hover 时上浮发光 */

练习建议

不要只看答案。把每道题在本地或 CodePen 亲手敲一遍,改一改颜色、尺寸、断点试试效果差异。CSS 属性多但常用就那么二三十个,键盘上练出来的肌肉记忆比眼睛看十遍都管用。

试着扩展:做完第 12 题价格卡片,能不能做一组"基础版 / 推荐版 / 专业版"三张并排的定价表(推荐版高亮 + 缩放)?做完第 13 题导航栏,能不能加一个纯 CSS 的下拉子菜单(:hover 控制 display)?做完第 15 题动画按钮,能不能做一个加载旋转圈(@keyframes + transform: rotate)?每个扩展都是一次小型的真实开发。

更多练习资源:布局游戏玩 Flexbox Froggy / Grid Garden;查属性兼容性看 Can I Use;系统学看 MDN CSS(有中文版)。

← 上一篇 CSS 实战项目

返回 CSS 教程目录

✈️💬