CSS 中一些属性或属性值的特性
CSS 不少属性存在反直觉的规则、特殊取值、边界限制,日常开发很容易踩坑。
本文整理 visibility、font-style、border、vertical-align、overflow、相对定位 relative、text-indent 等属性的特殊行为,同时补充部分高频易混淆属性特性。
visibility
visibility 用于控制元素显示与隐藏,隐藏不会改变页面布局,元素占位保留,还对表格元素有特殊行为。
取值:
visible:元素正常显示。hidden:元素不可见,但保留原本布局占位;若子元素设置visibility: visible,子元素依旧可以显示。collapse:- 仅对表格的行、列、行组、列组生效:隐藏对应行、列,不再占用表格空间,浏览器会保留单元格尺寸信息,避免重算整个表格宽高,提升表格性能。嵌套在折叠单元格内的表格也会被一并折叠,除非嵌套表格显式设置
visibility: visible。 - 对普通非表格元素、表格单元格,效果等价于
hidden。
- 仅对表格的行、列、行组、列组生效:隐藏对应行、列,不再占用表格空间,浏览器会保留单元格尺寸信息,避免重算整个表格宽高,提升表格性能。嵌套在折叠单元格内的表格也会被一并折叠,除非嵌套表格显式设置
注意:部分浏览器对 collapse 兼容性不完全一致,非表格元素优先使用 hidden。
font-style
控制字体斜体样式,区分「斜体 italic」与「倾斜 oblique」,可变字体支持角度控制倾斜幅度。
取值:
normal:常规字体样式。italic:使用字体专门设计的斜体字形(独立字体文件);若无专门italic字形,浏览器回退到oblique。oblique:将常规字体做几何倾斜;支持角度语法oblique <angle>,角度范围-90deg ~ 90deg,不写角度默认14deg。正值向右倾斜,负值向左倾斜。
font-style: normal;
font-style: italic;
font-style: oblique;
font-style: oblique 12deg;
注意:italic 是专门设计的手写感斜体;oblique 单纯把普通文字做倾斜变换。
border
border 是简写属性,简写同时包含 border-width、border-style、border-color。
多个易错点:
border-width不支持百分比单位。border-style默认值为none,不是solid;只写宽度颜色不写style,边框不会渲染。border-style: double:两条实线宽度始终相等,中间间隔误差最多1px,总宽度由border-width分配。border-color默认继承元素自身的color属性值。border简写不会设置border-image,反而会把border-image重置为初始值none。- 简写属性的通用规则:简写没有显式书写的子属性,会被重置为该子属性的初始值,而不是继承父元素的值。
vertical-align
vertical-align 用于垂直对齐,仅作用于行内(inline)、行内块(inline-block)、表格单元格(table-cell),对普通块级元素完全无效。
生效分为两套场景:行内盒子对齐、表格单元格对齐。
相对父元素对齐(行内、行内块):
baseline【默认】:元素基线对齐父元素基线;可替换元素(图片、<textarea>)基线各浏览器实现存在差异。sub:基线对齐父元素下标基线。super:基线对齐父元素上标基线。text-top:元素顶部对齐父字体字形顶部。text-bottom:元素底部对齐父字体字形底部。middle:元素中线对齐「父基线 + 二分之一 x-height」,不是父容器高度的几何居中。<length>:基线偏移,支持正负像素值,正数向上偏移,负数向下偏移。<percentage>:基于当前元素自身的 line-height 做百分比计算,控制基线偏移,可以为负数。
相对整行对齐(行内、行内块):
top:元素连同子元素顶部对齐整行盒子顶部。bottom:元素连同子元素底部对齐整行盒子底部。
inline-block 的基线判定:
- 如果内部存在行内内容,基线等于内部最后一行行内元素基线;
- 如果没有行内内容,或者设置了
overflow不为visible,则基线替换为该元素外边距下边缘。这也是图片、空 inline-block 经常出现下方缝隙的根源。
表格单元格场景:
baseline、sub、super、text-top、text-bottom、<length>、<percentage>:参与同行单元格基线对齐;top:单元格内边距盒上边缘对齐行顶部;middle:单元格内容在单元格盒内垂直居中;bottom:单元格内边距盒下边缘对齐行底部。
overflow
overflow 是 overflow-x、overflow-y 的简写,控制块容器内容溢出时的表现。
取值:
visible:溢出内容直接渲染在盒子外部,不裁剪,不生成滚动容器。hidden:裁剪溢出内容;JS 仍可以编程滚动(scrollTo、修改scrollLeft),会生成滚动容器;会创建新 BFC。clip:裁剪溢出,同时完全禁止一切滚动(JS 也无法滚动),不生成滚动容器,默认不产生 BFC。scroll:始终渲染滚动条,无论内容是否溢出;打印机可能打印溢出内容;创建新 BFC。auto:内容溢出才出现滚动条,不溢出则无滚动条;创建新 BFC。overlay【已废弃】:效果同 auto,滚动条浮在内容上方,不占布局空间。
重要特性与坑:
- 除
visible、clip以外,hidden、scroll、auto都会创建新的块格式化上下文 BFC。 - 隐式转换规则:如果其中一个轴设置为
hidden、scroll、auto,另一个轴为默认值visible,那么这个visible会被浏览器隐式计算为auto。 - 想要
overflow裁剪生效:容器需要设置height、max-height、width、max-width,或者行内强制不换行white-space: nowrap。 overflow:hidden的裁剪边界:裁剪发生在 border 盒子内边缘,不是 padding 内边缘。- 绝对定位元素不会被父级
overflow:hidden裁剪:前提条件,绝对定位元素与 overflow 容器之间没有任何已定位(非 static)的祖先元素。 - 即使父容器设置
overflow:auto、scroll,内部的绝对定位元素超出容器,不会产生滚动条。 - 容器设置
transform,旧版本 Chrome、Opera 会导致overflow裁剪失效。 - 原生自带滚动容器:
<html>根元素、<textarea>。
position: relative 相对定位
属性值特性:
- 偏移属性
left、top、right、bottom的百分比参照的是包含块,不是元素自身尺寸;但最终偏移是相对于元素原本自身的静态位置移动。 top、bottom使用百分比:参照包含块高度;若包含块高度是auto(由内容撑开),百分比计算值为0,偏移失效。- 对立方向同时设置:垂直同时写
top+bottom,仅top生效,bottom被忽略;水平同时写left+right,仅left生效,right被忽略。
注意:relative 只是视觉偏移,元素原本在文档流中的占位完全保留,不会脱离普通文档流。
text-indent
用于块级元素,设置首行文本缩进。
- 只对第一行行内盒子生效,不会缩进第二行、第三行。
- 只对块级盒子生效;普通
display:inline行内元素无效;inline-block、inline-table可以生效。 - 表单控件:
input、button上设置text-indent无效。 - 百分比参照包含块宽度,不是元素自身宽度;支持负值,可以实现首行悬挂缩进。
首行悬挂缩进:text-indent: -2em; padding-left: 2em;
::before、::after 伪元素
- 伪元素默认是行内元素(inline);不设置
display: block、inline-block,宽高设置无效。 - 必须要有
content属性,哪怕是空字符串content:"",否则伪元素不会生成渲染盒子。 - 伪元素属于元素内部的子盒子,不能获取 DOM,JS 无法选中;不属于 DOM 树。
- 不会继承部分表单元素(input、button),表单替换元素上
::before、::after无效。
position:sticky
- 是相对定位与固定定位的结合;任一祖先设置了非
visible的overflow(如hidden、auto、scroll),sticky可能失效。 - 必须设置
top、bottom、left、right其中一个阈值才会触发吸附效果。 - 吸顶的约束范围是最近的滚动祖先容器,不是视口。
line-height
line-height:1.5(无单位数字):子元素继承该系数,子元素行高 = 子元素自身font-size × 系数。line-height:150%(百分比):先在当前元素计算出像素值,子元素继承计算后的像素,不继承百分比系数。
示例:父字号 16px,line-height:150% → 计算得到行高 24px;子元素字号改为 20px,行高依旧继承 24px,不是 30px。
background-position 百分比
background-position: X% Y%;
公式:位置 = (容器尺寸 − 图片尺寸) × 百分比,不是把图片的某一点对齐容器百分比位置。0% 0%:图片左上角贴容器左上角;100% 100%:图片右下角贴容器右下角。
transform: translate 百分比
translate(x%, y%) 的百分比参照元素自身 border-box 尺寸,不是父容器。
备注:transform: translate(-50%, -50%) 就是拿自身宽高做计算,常配合绝对定位做居中。
margin 合并(外边距折叠)
普通文档流,块级元素垂直方向会发生 margin 折叠;水平 margin 永远不会折叠;设置 float、absolute、display: inline-block、生成 BFC 的盒子不会参与 margin 折叠。