绝对定位加 margin auto 为什么能让元素水平垂直都居中?
绝对定位元素同时给出四个边距偏移、明确宽高并设置 margin: auto 时,剩余空间可由两侧自动外边距平分,实现水平和垂直居中。普通流中自动垂直外边距不这样分配;尺寸不固定的元素更适合 Grid、Flex 或变换方案。
CSS · 盒模型与排版面试题第 1 页,显示第 1–38 题,共找到 38 道完整解析,可继续按分类、标签与关键词缩小范围。
按稳定语义路径排序
绝对定位元素同时给出四个边距偏移、明确宽高并设置 margin: auto 时,剩余空间可由两侧自动外边距平分,实现水平和垂直居中。普通流中自动垂直外边距不这样分配;尺寸不固定的元素更适合 Grid、Flex 或变换方案。
绝对定位元素通常以最近的定位祖先建立包含块,部分 transform、filter 等属性也可能改变参照物。找不到这样的祖先时会退回初始包含块;非定位祖先仍可能影响静态位置或裁剪,定位偏移不能只凭 DOM 层级判断。
BFC 是与外部布局相对独立的块级格式化区域。display: flow-root、特定 overflow 值、浮动和绝对定位都可能建立它;它能包住内部浮动、避开外部浮动并阻止父子外边距合并,但不同触发方式还会带来裁剪或脱离文档流等副作用。
span 等非替换行内元素不能靠 width、height 改变行内盒尺寸,垂直 margin 也不会撑开行高。垂直 padding 可能画到相邻行上,却不改变行盒高度;需要稳定宽高或块级间距时,可改用 inline-block、Flex 子项等布局形式。
默认的 content-box 模型里,width 只指定内容宽,左右 padding 与 border 会让盒子外宽继续增加。给内容区设 200 像素并不代表元素只占 200 像素;border-box 把边框计入指定宽度,外边距和 JavaScript 的宽度测量仍需另外区分。
clear: both 不会移除浮动,只会让当前元素移动到前面左右浮动的下方。浏览器为它加入的 clearance 可能让 margin-top 看起来不起作用;clear 只考虑相应格式化上下文中的前置浮动,clearfix 正是利用这一行为撑起父容器。
父元素内部只有浮动子项时,自动高度可能塌成零,因为浮动不参与普通流高度计算。clearfix 伪元素或建立新的 BFC 可以包住浮动;overflow: hidden 还会裁剪内容,display: flow-root 更明确,而现代横向布局通常可改用 Flex。
contain: layout 限制内部布局对外部的影响,contain: paint 约束绘制范围;它们能缩小浏览器需要处理的区域,却也可能改变定位参照与溢出可见性。contain: size 与 content-visibility 的关系不同,页面若依赖内容自动撑高不能直接套用。
content-box 下 width 指内容宽,padding 与 border 在外侧增加;border-box 下 width 包含它们,内容区随之缩小。全局使用 border-box 能减少宽度计算,但 min-width、flex-basis 与百分比尺寸仍各有自己的约束,不能仅靠盒模型设置消除溢出。
Flex 子项默认的自动最小宽度可能保留内容的最小尺寸,长单词或 nowrap 文本于是撑开容器,省略号始终没有溢出空间。给正确层级的子项设置 min-width: 0 或适当 overflow 才能允许收缩;多层嵌套和 Grid 轨道也有类似约束。
inline-block 未限制宽度时会随内容变宽,文字不会在元素内部溢出,text-overflow: ellipsis 因而看不到效果。限定 width 或 max-width 后还要设置不换行与溢出裁剪;纯 inline 元素无法按同样方式指定宽度,表格单元格又受列布局影响。
没有内容、边框、内边距和最小高度的空块,自身上下外边距可能合并,再与相邻块的外边距继续合并。正负值的计算不是简单相加;条件渲染产生空占位元素时,预留间距可能因此与设计稿不符。
float 让后续文字行在其旁边缩短,形成文字环绕;inline-block 仍属于行内排版,只占自己所在的行,不会让后续段落环绕。两者对父容器高度、对齐和源码空白的影响不同,普通横向排列通常交给 Flex 或 Grid。
height: auto 只根据参与普通流的内容决定父元素高度,绝对定位子元素不在其中,因此父盒可能包不住它。需要内容撑高时可改回普通流或用 Grid 叠放;确实必须测量浮层时,才考虑脚本同步父级尺寸。
相邻 inline-block 元素之间的源码换行或空格会折叠成可见的文本空格,宽度又随字体大小变化。删除源码空白、父级设零字号或使用负外边距都能消除间隙,但各有维护代价;Flex 与 Grid 的 gap 更适合有意控制间距。
isolation: isolate 会为元素创建新的层叠上下文,使组件内部的 z-index 不再与外部层级直接竞争,也能限定 mix-blend-mode 的混合背景。它不靠透明度或变换制造视觉副作用,但仍要确认弹窗是否被祖先层叠上下文整体压住。
弹窗的 z-index 写到 9999 仍被遮住,常见原因是它的祖先建立了层叠上下文,整个祖先先与旁边的上下文比较。定位加 z-index、透明度、变换等都可能建层;提高子元素数值并不能越过父层。
传统水平书写模式下,margin 和 padding 的百分比即使写在上下边,也相对包含块的宽度计算,避免尺寸计算形成循环依赖。竖排模式要按包含块的行内尺寸理解;做等比容器时旧式 padding 技巧可与 aspect-ratio 比较。
限宽容器常用 max-width 限制大屏宽度、margin-inline: auto 居中,再留出小屏内边距。width: 100% 与 padding 叠加可能溢出,min-width 又可能压过最大宽度;Flex 子项中的自动最小尺寸也会影响容器能否真正缩窄。
多行省略依赖纵向的旧版 WebKit 盒布局、行数限制和溢出裁剪共同作用,与单行的 text-overflow 不是同一套机制。内边距可能露出额外文字,构建工具也可能处理掉必要前缀;出现多一行或完全不截断时,要逐项检查这些声明。
负 z-index 的定位元素仍处于所属层叠上下文里,可能被祖先背景盖住,看起来像突然消失。给父级建立明确的层叠上下文可把装饰层限制在组件内部;伪元素背景要同时考虑点击命中和正文的层级。
overflow: auto 不只是按需显示滚动条,它还会建立滚动容器和 BFC,裁剪溢出,并改变 sticky 的滚动参照。Flex 子项使用时还可能改变自动最小尺寸;弹层被裁掉或吸顶失效时,应先检查祖先是否设置了它。
overflow: hidden 和 clip 都能裁剪内容,但 hidden 仍可通过脚本或焦点滚动,并会建立滚动容器;clip 不提供这类滚动行为。sticky 参照、BFC 与单轴裁剪因此会不同,overflow-clip-margin 还可调整 clip 的裁剪边界。
不设置 z-index 时,块背景、浮动、行内内容和定位元素仍按绘制层级叠放,同一层里通常后面的元素盖住前面的元素。后一个块的背景盖不住前一个块的文字,是两者处于不同绘制阶段;建立新层叠上下文后还要整体比较。
父容器的第一个子元素设置 margin-top 后,父元素自己也被推下去,通常是父子外边距合并。边框、内边距、新的格式化上下文或 Flex 布局都能隔断合并,但它们对尺寸、裁剪和子元素排列的影响并不相同。
定位元素的 z-index: auto 通常不创建新的层叠上下文,子元素仍可能与外层内容比较层级;z-index: 0 则建立独立上下文。角标被遮挡时,除了看数值,还要检查祖先的透明度、变换等是否提前把它关进另一层。
position: relative 的 top、left 只移动绘制位置,不会让兄弟元素重新占用它原来的空间,因此常留下空白或形成遮挡。margin 会参与正常布局,两者不能互换;相对定位还可为绝对定位后代提供参照。
父元素建立层叠上下文后,内部子元素无论写多大的 z-index,都只能作为父层的一部分与外部比较。弹窗被相邻卡片盖住时,应找出哪个祖先形成了新层,以及两个父层本身的顺序,而不是继续加大弹窗数值。
sticky 元素会以最近的滚动容器为参照;祖先的 overflow: hidden 可能让它盯着一个并不滚动的容器,页面滚动时自然不吸顶。单轴 overflow 也可能触发类似效果;可按需求调整容器、改用 clip 或移动吸顶元素。
吸顶导航何时开始停住,取决于 top 等偏移阈值与最近的滚动容器;到达包含块边界后又会被带走。通讯录分组标题会依次接替吸附位置,若 sticky 完全不生效,应检查滚动容器、可滚动距离及父元素尺寸。
单行省略需要元素确实发生水平方向溢出,再配合 white-space: nowrap、裁剪和 text-overflow: ellipsis 才能显示省略号。Flex 子项的最小宽度、纯行内元素没有可用宽度或声明写在错误层级,都会让文本继续撑开容器。
表格采用自动列宽时,长内容会撑大列,单元格即使写了 text-overflow: ellipsis 也未必发生溢出。table-layout: fixed 可让列宽受表格约束,内层包裹元素或特定宽度技巧也能制造裁剪范围;选法取决于整表列宽是否可固定。
祖先的 transform 不为 none 时,可成为 absolute 与 fixed 后代的包含块,固定弹窗于是跟随组件而非视口。filter 等属性也可能产生类似效果;需要视口级浮层时,Portal 可将元素移到不受该祖先约束的位置。
图片作为行内内容时默认靠文字基线对齐,基线下方仍需给字形下伸部分留空间,于是底部看起来有一条缝。让图片成为块级元素、调整 vertical-align 或改变行盒设置都能处理,但应按是否还需要文字同行来选择。
普通块布局里,相邻块的上下外边距可能合并,两个 20px 间距最终仍是 20px。正负边距有不同计算方式;Flex 与 Grid 子项不发生这种合并,BFC 只隔开内外边距,不能阻止同一上下文的兄弟互相合并。
display: none 让元素不生成布局盒子,周围内容会重新排列;visibility: hidden 保留盒子与占位,只隐藏绘制。两者对指针事件、后代覆盖、过渡与辅助技术的影响也不同,保留布局空位或做淡出时应先明确期望的交互状态。
普通块级元素的 width: auto 会考虑自身外边距、边框与内边距后填满可用空间;width: 100% 先把内容宽设为包含块宽,额外空间可能使它溢出。border-box 只能把边框和内边距纳入指定宽度,外边距仍需另算。
writing-mode 切换竖排后,块轴转为水平,沿块轴发生的外边距合并也可能表现为左右合并;direction 只改变行内方向,不改变块轴。width 是物理宽度,inline-size 则跟随书写轴,竖排布局中不能混用两种直觉。