响应式布局
语法:
响应式大小控制
1. clamp() —— 在一个范围里自适应
语法:
font-size: clamp(最小值, 理想值, 最大值);📌 例子:
h1 {
font-size: clamp(1.5rem, 2vw + 1rem, 3rem);
}- 最小值:
1.5rem→ 字体不会比这个小。 - 理想值:
2vw + 1rem→ 随着视口宽度变化。 - 最大值:
3rem→ 字体不会无限变大。
👉 这样可以在小屏幕不至于太小、大屏幕不至于过大,中间则平滑过渡。
2. 相对单位
(1) em —— 相对父元素的字体大小
.container {
font-size: 16px;
}
.child {
font-size: 1.5em; /* = 16px × 1.5 = 24px */
}📌 特点:层层叠加,容易出现「级联放大」现象。
(2) rem —— 相对根元素 <html> 的字体大小
html {
font-size: 16px;
}
p {
font-size: 1.5rem; /* = 16px × 1.5 = 24px,无论父元素多大 */
}📌 特点:避免了 em 的层层放大,更适合做全局排版。
(3) vw / vh —— 相对视口宽度/高度
1vw = 视口宽度的 1%1vh = 视口高度的 1%
h1 {
font-size: 5vw; /* 宽度的 5% */
}📌 特点:超级自适应,但可能在超小/超大屏幕下效果不理想,所以常和 clamp() 搭配。
(4) % —— 相对父容器的(content)大小
.box {
width: 50%; /* 父容器宽度的一半 */
}📌 在布局中非常常见,但对 font-size 用处不大。
如果父元素的高度没明确指定(比如高度由内容撑开),那么子元素的百分比高度是 无效 的。
备注
width / height → 相对父元素 content box 的宽/高
padding / margin → 一律相对父元素content box 的宽度
定位属性 → 相对定位容器 content box 的宽/高
利用百分比
padding / margin → 一律相对父元素content box 的宽度
这样可以设置背景图片不用使用img来保持大小了,只需要使用百分比保持比例!
比如:
width:100%
height:60%
图片比例就是这个,直接设置background-img完全一样了,不用固定父元素大小!
类似于:
img{
width:100%
}媒体查询
现在我要再了解媒体查询语法以及媒体查询如何在断点(breakpoints)时切换风格,比如整个布局要改变。
媒体查询的形式是:
@media (条件) {
/* 样式 */
}
最常用的条件是 width 和 height,一般写成:
@media (min-width: 768px)→ 屏幕宽度大于等于 768px 时生效。@media (max-width: 768px)→ 屏幕宽度小于等于 768px 时生效。
/* 小屏幕(手机) */
@media (max-width: 600px) {
body {
background: lightblue;
}
}
/* 中等屏幕(平板) */
@media (min-width: 601px) and (max-width: 1024px) {
body {
background: lightgreen;
}
}
/* 大屏幕(桌面) */
@media (min-width: 1025px) {
body {
background: lightpink;
}
}
调试的时候可以打开媒体查询

这样就可以选择不同的大小

蓝色的是max-with
黄色的是min-width
回到正题,还可以设置布局
.container {
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.container {
display: grid;
grid-template-columns: 1fr 3fr;
}
}
小屏幕用上下堆叠(flex),到大屏幕切换成左右分栏(grid)。3. 常见断点(breakpoints)
没有绝对标准,但前端常用的几个区间:
| 设备类型 | 宽度断点 |
|---|---|
| 手机 | max-width: 600px |
| 平板 | 601px ~ 1024px |
| 桌面 | 1025px ~ 1440px |
| 大屏桌面 | min-width: 1441px |
4. 移动优先(推荐写法)
通常我们写 默认样式先适配手机,然后用 min-width 一步步增强:
/* 默认:手机 */
.container {
flex-direction: column;
}
/* 平板以上:改成行布局 */
@media (min-width: 768px) {
.container {
flex-direction: row;
}
}
/* 桌面以上:加上侧边栏 */
@media (min-width: 1024px) {
.container {
display: grid;
grid-template-columns: 200px 1fr;
}
}答疑
不是我就奇怪了,手机这种为什么要设置flex-direction: column;本来放div元素不就是从上到下吗,为什么一定要在根容器上设置为flex
1. 默认流确实是「从上到下」
没错,<div> 默认就是 块级元素,会在标准文档流里从上到下排布。
👉 所以 在最简单的手机布局场景 下,确实不用特意加 flex-direction: column;。
2. 为什么很多教程还写了 flex-direction: column;?
主要有这几个原因:
(1) 为了和「大屏布局」对齐思路
很多时候设计是这样的:
- 手机:上下堆叠
- 平板:两列
- 桌面:三列
用 flex/grid 的好处是,你只要在不同断点切换容器属性就行:
.container {
display: flex;
flex-direction: column; /* 手机:上下 */
}
@media (min-width: 768px) {
.container {
flex-direction: row; /* 平板:左右 */
}
}👉 这样写比较「语义对称」:一开始就是 flex 布局,然后只改方向,而不是从 block → flex。
(2) 方便做水平/垂直对齐
如果只是标准流:
- 元素之间要平均分布?难。
- 垂直方向要居中?得写很多额外样式。
但 flex 自带:
.container {
display: flex;
flex-direction: column;
justify-content: center; /* 垂直居中 */
align-items: center; /* 水平居中 */
}👉 如果一开始就用 flex,布局调整和对齐会很方便。
(3) 未来可能要拓展
产品迭代时,设计师经常说:
- 「手机还是一列,但想要某些卡片在中间对齐」
- 「间距要平均」
- 「底部加个自适应的按钮栏」
如果容器已经是 flex,就能直接用 justify-content / align-items / gap,不需要大改。
3. 总结
- 手机上一列 确实不需要 flex,默认文档流就能搞定。
- 但很多团队会 一开始就用 flex/grid,因为:
- 方便和大屏布局保持一致(只改方向,不改 display)。
- 带来了更灵活的对齐、分布能力。
- 提前为未来需求留余地。
所以教程里写 flex-direction: column; 更多是 布局习惯和可扩展性考虑,而不是说“必须这么写”。
布局思路 和 CSS 语义/性能差别。
1. 100vw / 100vh
.full {
width: 100vw;
height: 100vh;
}- vw/vh:视口宽度/高度的百分比,1vw = 视口宽度的 1%,1vh = 视口高度的 1%。
- 这种写法的意思是:元素的尺寸始终等于视口大小。
- 它本质是一个「尺寸设定」,不会影响元素的定位方式(还是正常文档流)。
📌 用途:全屏背景、全屏容器、轮播图一屏占满。
2. position: fixed; top:0; right:0; bottom:0; left:0;
.full {
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
}- 固定定位,锚定在视口上,大小等于视口。
- 不管页面滚动到哪里,它都会 固定不动。
- 本质是「定位方式」,而不是「尺寸设置」。
📌 用途:固定导航栏、浮层、模态框、遮罩。
100vw在有滚动条时会 包含滚动条宽度,容易导致出现横向滚动条(比如 PC 浏览器)。
- 解决办法:可以用
width: 100%;替代,或者calc(100vw - var(--scrollbar-width))。
100vh在移动端 Safari 上会因为地址栏的显示/隐藏而变化,导致「跳动」。
- 新标准有
svh,lvh,dvh可以解决。
标准流间隙问题
1. 为什么会超出
- 标准流 + inline-block:元素之间的空格(HTML 里的空格/换行)会占宽度。
- 标准流 + float:50% + 50% = 100%,但如果再加
margin,总宽度就 > 100%。 - 标准流 + box-sizing: content-box(默认):width 只算内容,不算 padding/border,加了 padding 也会超出。
原来那些空格是来自HTML 里的空格/换行,我把格式改为这样
<body>
<div class="container">
<div class="box1"></div><div class="box2"></div>
</div>
</body>效果:

还原回去:
<body>
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>效果:

提示
当元素是 inline 或 inline-block 时,HTML 源码里的空格/换行 会被浏览器当成 一个空白字符(whitespace) 渲染出来。
2. 如何避免这种“神秘间隔”?
方法 1:去掉换行/空格
<div style="display:inline-block;width:50%">A</div><div style="display:inline-block;width:50%">B</div>但这很丑,不好维护。
方法 2:父容器 font-size:0
.parent {
font-size: 0;
}
.parent > div {
font-size: 16px; /* 还原内容文字大小 */
}👉 因为空格宽度依赖 font-size,设成 0 就没有空隙了。
方法 3:负 margin
.left {
display: inline-block;
width: 50%;
margin-right: -4px;
}(丑陋 hack,不推荐 🙈)(导致左边元素大小被右边元素占用,左边元素变小)
方法 4:不用 inline-block,改用 flex / grid
这是最推荐的现代方案:
.parent {
display: flex;
}
.child {
flex: 1;
}👉 完全没有空隙问题,而且还能用 gap 控制间距。
body
body元素自带margin:8px;,需要去除才能完全拥有浏览器界面
margin为什么合并
<style>
.box1 {
height: 200px;
background-color: lightpink;
margin-bottom: 20px;
}
.box2 {
height: 200px;
background-color: lightblue;
margin-top: 30px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>最终合并为30px:

之前在浮动里面演示了浮动是不会触发margin合并的,现在探究合并的根本原因
margin 合并只发生在垂直方向(上下 margin),不会发生在水平方向。
合并规则是取最大值,而不是相加。
媒体查询示例
媒体查询有一套编写顺序,如果使用min-width,就是从最小的屏幕样式开始不断向大的写,如果是max-with就是从pc端样式不断向移动端过渡
两种风格
1. Mobile First(推荐,现代主流)
-
基础样式默认给 最小屏幕(移动端)。
-
媒体查询使用
min-width,随着屏幕变大不断“增强”样式。 -
写法示例:
css/* 默认:移动端样式 */ body { font-size: 14px; } /* 平板及以上 */ @media (min-width: 768px) { body { font-size: 16px; } } /* 桌面端及以上 */ @media (min-width: 1200px) { body { font-size: 18px; } }
2. Desktop First(传统思路)
-
基础样式默认给 PC 端。
-
媒体查询使用
max-width,屏幕变小的时候不断“覆盖”成适合小屏的样式。 -
写法示例:
css/* 默认:桌面端样式 */ body { font-size: 18px; } /* 平板及以下 */ @media (max-width: 1200px) { body { font-size: 16px; } } /* 手机及以下 */ @media (max-width: 768px) { body { font-size: 14px; } }
✅ 总结:
min-width→ Mobile First,从小到大。max-width→ Desktop First,从大到小。
现在大多数团队和框架(Bootstrap、Tailwind 等)都是 Mobile First,所以更常用 min-width。
示例
现在开始讲述max-width类型转变关键!
PC隐藏移动端组件:
/* 移动端隐藏元素 */
.mobile-nav,
.mobile-main {
display: none;
}平板
/* 平板端媒体查询 (768px - 1024px) */
@media (max-width: 1024px) {
.features {
grid-template-columns: repeat(2, 1fr);
}
.desktop-main {
grid-template-columns: 1fr;
}
.sidebar {
order: -1;
}
}移动端:
/* 移动端媒体查询 (小于768px) - 完全不同的框架 */
@media (max-width: 768px) {
/* 隐藏桌面端元素 */
.desktop-nav,
.desktop-main,
.features {
display: none;
}
/* 显示移动端元素 */
.mobile-nav,
.mobile-main {
display: block;
}
/* 移动端导航 - 垂直卡片式 */
/*导航以及导航的子元素都定义在这边*/
.mobile-nav {
...
}
/* 移动端主要内容 - 垂直卡片堆叠 */
/*主题内容以及主题内容子元素都放在这个媒体查询里面*/
.mobile-main {
...
}
}超级小屏幕
/* 超小屏幕 (小于480px) */
@media (max-width: 480px) {
.mobile-nav-buttons {
justify-content: center;
}
.mobile-nav-btn {
flex: 1;
min-width: 80px;
}
.mobile-stats {
grid-template-columns: 1fr;
}
.mobile-hero h1 {
font-size: 1.5rem;
}
}amfe-flexible
特别好用,在html上设置font-size,不管屏幕大小怎么变化,font-size相应变化,使用rem作为大小单位可维持相对大小比例不变!
评论
评论加载中……