这篇笔记从“盒模型”讲起,再讲 Flex、Grid 和媒体查询怎么用, 最后给出一个页面在手机、平板、电脑上自动切换布局的完整例子。
网页里的每一个元素,都可以理解成一层一层的盒子,从里到外是:
很多新手布局出问题的第一原因就是:给元素设置了宽度,又加了 padding, 结果整个元素被撑大了。解决办法是给所有元素设置:
/* 让 padding 和 border 都算进 width 里面,元素不会被“撑大” */
* {
box-sizing: border-box;
}主页的卡片、按钮、代码块都用了这个设置,所以给它们加内边距时,宽度不会莫名其妙变大。
Flex 是一维布局:它只管“横着排”或者“竖着排”。最典型的场景是导航栏:
/* CSS */
.topbar {
display: flex; /* 开启弹性布局 */
align-items: center; /* 子元素垂直方向居中 */
justify-content: space-between; /* 左右两端各放一个,中间留空隙 */
gap: 12px; /* 子元素之间的间距 */
flex-wrap: wrap; /* 太窄放不下时自动换行,而不是挤出去 */
}对应的 HTML 结构是这样的:
<div class="topbar">
<a href="#" class="logo">我的网站</a>
<nav>
<a href="#">学习笔记</a>
<a href="#">资源收藏</a>
<a href="#">关于我</a>
</nav>
</div>其中常用的几个属性:
justify-content:控制横向怎么排(居中、两端、均匀分布);align-items:控制纵向怎么对齐(顶部、居中、底部);flex-wrap: wrap:空间不够时允许换行,这是手机适配的关键之一;gap:直接设置间距,不用再给每个子元素单独写 margin。Grid 是二维布局:它同时控制行和列,非常适合做卡片网格。比如主页的“学习笔记”就是三列网格:
/* CSS */
.notes-grid {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 三列,每列宽度相同 */
gap: 18px;
}Grid 还有一个很实用的“自适应”写法,不写媒体查询也能自动变列数:
/* 容器够宽就多放几列,不够宽就自动减少列数 */
.auto-grid {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
/* 解释:
auto-fit —— 尽量多生成几列
minmax(240px, 1fr) —— 每列至少 240px,多出来的空间平均分配 */首先,响应式的第一步是 HTML 里必须有这行(你的页面通常已经带了):
<meta name="viewport" content="width=device-width, initial-scale=1.0" />它的作用是告诉手机浏览器:“请按真实屏幕宽度显示”,否则手机会把 900px 宽的网页缩小成一整屏,字小得没法看。
媒体查询的两种常用写法:
/* 手机优先:从小到大写 */
.cards {
display: flex;
flex-direction: column; /* 手机默认上下排列 */
gap: 16px;
}
@media (min-width: 768px) {
.cards {
display: grid;
grid-template-columns: repeat(2, 1fr); /* 平板:两列 */
}
}
@media (min-width: 1024px) {
.cards {
grid-template-columns: repeat(3, 1fr); /* 电脑:三列 */
}
}注意这里的顺序:768px 写在前面,1024px 写在后面。因为两个条件都会命中大屏,后写的规则会覆盖前面的,所以要从窄到宽写。
常用的断点参考:
| 屏幕 | 大致宽度 | 典型布局 |
|---|---|---|
| 手机 | 小于 600px | 一列 |
| 平板 | 600px ~ 1024px | 两列 |
| 电脑 | 大于 1024px | 三列或更多 |
断点数字不是规定死的,以你的内容什么时候“放不下”为准。主页现在的做法就是: 900px 以下变两列,600px 以下变一列。
一个比较典型的页面结构:顶部用 Flex 做导航,中间用 Grid 做卡片。HTML 长这样:
<div class="page">
<header class="topbar">
<span>Logo</span>
<nav class="menu">
<a href="#">首页</a>
<a href="#">笔记</a>
<a href="#">资源</a>
</nav>
</header>
<main class="cards">
<article class="card">卡片 1</article>
<article class="card">卡片 2</article>
<article class="card">卡片 3</article>
</main>
</div>CSS 用“手机优先”的顺序来写:
/* ===== 所有屏幕都适用 ===== */
.page {
max-width: 1080px;
margin: 0 auto;
padding: 0 20px;
}
/* 顶部导航:用 Flex 管一排,空间不够就换行 */
.topbar {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
padding: 18px 0;
}
.menu {
display: flex;
gap: 20px;
}
/* ===== 手机默认:卡片一列 ===== */
.cards {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
/* ===== 平板:两列 ===== */
@media (min-width: 768px) {
.cards {
grid-template-columns: repeat(2, 1fr);
}
}
/* ===== 电脑:三列 ===== */
@media (min-width: 1024px) {
.cards {
grid-template-columns: repeat(3, 1fr);
}
}这段代码的思路就是主页卡片的实现方式:布局骨架用 Grid,一排内部的小元素用 Flex, 整页宽度变化靠媒体查询,卡片宽度变化可以靠 auto-fit。
home.css,把 .notes-grid 的列数改成 2 列,观察变化;box-sizing: border-box 打好底;一排用 Flex;
成片用 Grid;手机优先从窄到宽写媒体查询;改完一定在手机、平板、电脑三种宽度下都看一眼。