# CSS
# 对BFC的理解,如何创建BFC
面试官:请说说什么是BFC?大白话讲清楚 (opens new window)
# BFC到底是什么东西
BFC
全称:Block Formatting Context
, 名为 "块级格式化上下文"。
W3C
官方解释为:BFC
它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,Block Formatting Context
提供了一个环境,HTML
在这个环境中按照一定的规则进行布局。
简单来说就是,BFC
是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。那么怎么使用BFC
呢,BFC
可以看做是一个CSS
元素属性
# 怎样触发BFC
这里简单列举几个触发BFC
使用的CSS
属性
- overflow: hidden
- display: inline-block
- position: absolute
- position: fixed
- display: table-cell
- display: flex
# BFC的规则
BFC
就是一个块级元素,块级元素会在垂直方向一个接一个的排列BFC
就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签- 垂直方向的距离由margin决定, 属于同一个
BFC
的两个相邻的标签外边距会发生重叠 - 计算
BFC
的高度时,浮动元素也参与计算。
# BFC的作用
- 解决margin的重叠问题:由于BFC是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个BFC,就解决了margin重叠的问题。
- 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为0。解决这个问题,只需要把父元素变成一个BFC。常用的办法是给父元素设置
overflow:hidden
。 - 创建自适应两栏布局:可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应。
.left {
width: 100px;
height: 200px;
background: red;
float: left;
}
.right {
height: 300px;
background: blue;
overflow: hidden;
}
<div class="left"></div>
<div class="right"></div>
左侧设置float:left
,右侧设置overflow: hidden
。这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠,实现了自适应两栏布局。
# BFC 如何影响 margin
重叠?
BFC 可以在某些情况下防止 margin
重叠,但并不是所有情况。具体来说,BFC 可以防止以下几种情况的 margin
重叠:
- 父元素与子元素之间的
margin
重叠:- 当一个块级元素包含另一个块级元素时,子元素的
margin
会与父元素的margin
重叠。如果父元素形成了一个 BFC,这种重叠会被防止。
- 当一个块级元素包含另一个块级元素时,子元素的
- 浮动元素与相邻元素之间的
margin
重叠:- 浮动元素的
margin
有时会与相邻的非浮动元素的margin
重叠。如果浮动元素和相邻元素都形成了 BFC,这种重叠会被防止。
- 浮动元素的
# 为什么上下相邻的两个容器的 margin
仍然会重叠?
即使两个容器都形成了 BFC,它们之间的 margin
仍然可能会重叠,因为 BFC 主要影响的是内部元素的布局,而不是外部元素之间的关系。具体来说:
BFC 影响的是内部布局:
- BFC 主要用于防止内部元素的
margin
与外部元素的margin
重叠,而不是防止外部元素之间的margin
重叠。
- BFC 主要用于防止内部元素的
外部
margin
重叠:- 即使两个容器都形成了 BFC,它们仍然是独立的块级元素,它们之间的
margin
仍然会按照标准的margin
重叠规则进行处理。
- 即使两个容器都形成了 BFC,它们仍然是独立的块级元素,它们之间的
# px、em、rem
三者的区别:
- px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
- em和rem相对于px更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
- em是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。
使用场景:
- 对于只需要适配少部分移动设备,且分辨率对页面影响不大的,使用px即可 。
- 对于需要适配各种移动设备,使用rem,例如需要适配iPhone和iPad等分辨率差别比较挺大的设备。
# 1px 问题
1px问题是指在高DPI(dots per inch,每英寸点数)或高PPI(pixels per inch,每英寸像素数)屏幕,尤其是Retina屏幕(苹果公司对于高分辨率显示屏的一种称呼)上,当使用CSS定义1px宽度的边框或线条时,实际渲染出来的线条可能会显得过粗。这是因为移动设备的屏幕像素密度通常比传统计算机屏幕高得多,导致CSS中定义的1px并不等同于物理屏幕上的1个像素点。例如,在一个2倍DPR(device pixel ratio,设备像素比)的屏幕上,1个CSS像素实际上会被渲染为2x2=4个物理像素。因此,为了使边框或线条在高分辨率屏幕上看起来更加细腻,开发者们需要寻找方法来实现视觉上接近1px的边框或线条。
# 解决1px问题的方法
- 使用0.5px边框:直接在CSS中设置
border: 0.5px solid #000;
。然而,这种方法在一些旧版本的浏览器或设备上可能不被支持,会自动四舍五入到最接近的整数值。 - 使用伪元素和transform:创建一个伪元素,并使用
transform: scaleY(0.5);
来缩小其高度,从而达到视觉上0.5px的效果。这种方法兼容性较好,广泛应用于各种设备和浏览器。 - 使用box-shadow:通过设置
box-shadow: 0 0.5px 0 #000;
来模拟边框效果。不过,这种方法可能会产生轻微的模糊感,且不是所有情况下都适用。 - 使用SVG:利用SVG的矢量特性,可以精确控制线条的粗细,不受屏幕分辨率的影响。这种方法适用于需要绘制复杂形状或路径的情况。
- 使用viewport单位和REM单位:通过动态计算并设置合适的viewport单位(如vw, vh)或REM单位,结合媒体查询,根据不同的屏幕尺寸和DPR值来调整边框的宽度。
- 使用图片作为边框:虽然不太常用,但也可以使用预设好的1px宽度的图片作为边框背景,通过CSS的
border-image
属性来应用。这种方法的缺点是灵活性较差,难以适应不同的颜色需求。