重读《CSS 世界》:流、盒子与被忽略的默认值
第三次读这本书,才真正开始理解“流”不是背景,而是布局本身。
第一次读《CSS 世界》是在刚学前端的时候,把它当成一本查漏补缺的手册;第二次是工作两年后,带着“为什么又错位了”的怨气去翻;这一次读得慢,反而读出了些设计层面的东西。
一、流不是背景,是布局本身
书里反复讲“流”,一开始我觉得这是废话:块级元素从上往下排,行内元素从左往右排,谁不知道呢。后来才意识到,这句话的真正含义是——CSS 的默认排版就是一套完整的算法,而不是需要被清除的“副作用”。
写 float、position: absolute、flex,本质上都是在说“这个元素不按水流走”。把流当成一条河,别的布局方式只是人工开凿的支流:
- 正常流:水往低处流,最自然。
- 浮动:让盒子暂时离开河道,后面的内容绕过去。
- 绝对定位:把盒子从水里捞出来,钉在墙上。
- Flex / Grid:自己修一条新河道,规则由你定。
理解了这层,再看“清除浮动”这种历史遗留问题,就不会觉得是玄学,而是一场河道治理。
二、盒子模型的默认值是一种契约
width 默认是 content-box,写 width: 100%; padding: 24px 会撑出父容器。很多人第一反应是“CSS 有病”,其实它只是选择了一种契约:宽度管内容,内边距和边框另算。
.card {
box-sizing: border-box;
width: 100%;
padding: 24px;
border: 1px solid #ddd;
}border-box 也不是“正确”,只是另一种契约:宽度包含内边距和边框。选哪种都行,关键是整个项目统一,并且知道自己在选什么。
三、行内盒子的那些缝
图片底下多出 3 像素、两个 inline-block 之间凭空出现空隙——这两个问题我遇到过不止一次,每次都是搜一下、改掉、忘掉。
原因其实很统一:图片和行内块都坐在基线上,而基线下面还给字母的降部留了空间。
.avatar {
display: block; /* 或者 vertical-align: middle; */
}
.list {
display: flex; /* 顺便消灭 inline-block 之间的空白字符 */
gap: 12px;
}line-height、vertical-align、font-size 这三个属性共同决定了行盒的高度。书上有一整章讲这个,我当时跳过了,现在补了回来。
四、margin 合并:不是 bug,是段落感
相邻兄弟的上下 margin 会合并,父子元素的 margin 也会“穿透”出去,空元素自己的上下 margin 还会合并。刚学的时候觉得这是 CSS 最不可理喻的地方,后来写文章排版才明白:合并产生的正是段落之间的呼吸感。
如果两个段落的间距是各自 margin 相加,那么段落越多、缝隙越大,页面会变得松散。取较大值,反而更接近传统排版的习惯。
阻止合并的方法也很标准:给父元素建立 BFC(overflow: hidden、display: flow-root),或者用 padding / border 隔开。
五、这次真正读到的
合上书,我记住的不是某个属性值,而是一种视角:CSS 的默认值更像一套“最小惊讶”的约定——块级元素占满一行、行内元素围绕文字、外边距彼此礼让。
现代布局把很多隐式行为显式化了,gap 取代了 margin 技巧,grid 取代了 float 拼图。但那些默认值还在,遇到奇怪的错位时,答案往往还是回到最基础的三件事:它是块级还是行内?它在不在流里?它的盒子怎么算?
书还是那本书,变的是读它的人。