BFC - 块级格式化上下文
块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
BFC 解决了什么问题?
清除浮动
在 flex 布局还没流行的时候,常常会用到浮动 float
,浮动元素脱离的文档流,带来直接的一个问题就是父级高度塌陷。
清除浮动常用的方法有, clear
属性,还有就是构建 BFC
,看个小例子
.con{
border: 1px solid;
width: 300px;
}
.float{
float: left;
height: 100px;
background-color: sandybrown;
}
<div class="con">
<div class="float">xxxxxxxx</div>
<p>dsfsdfwefesfhjkhjkhuhjk</p>
</div>
黄色 div 是个浮动元素,定了 100px 高度,父级不定高,很明显父级高度没有被撑开。
给父级 con 加上 overflow: auto;
效果如下
这时候父级div就是一个 BFC
外边距折叠
在CSS中,两个或多个毗邻的普通流中的盒子(可能是父子元素,也可能是兄弟元素)在垂直方向上的外边距会发生叠加,这种形成的外边距称之为外边距叠加。
形成外边距折叠有几个关键要素:毗邻、两个及以上、垂直方向、正常流
毗邻:对于父子元素,他们自己是紧挨着的,子元素没有被父元素 border padding 给隔开,这样他们就是毗邻的;对于兄弟元素,他们的盒模型是挨着一起的就是毗邻的。
正常流:除去浮动定位、绝对定位,也就是正常的文档流。
这是个非常常见的问题。解决方案也挺多的,无外乎打破三要素中的一个即可,比如采用浮动、绝对定位、inline-block、添加空白的flex元素、还有就是接下来要说的构建 BFC
.con {
width: 300px;
background-color: antiquewhite;
}
.one {
height: 100px;
margin-top: 10px;
margin-bottom: 20px;
background-color: seagreen;
}
.two {
height: 100px;
margin-top: 10px;
background-color: slateblue;
}
<div class="con">
<div class="one"></div>
<div class="two"></div>
</div>
div one
的 margin-top: 10px;
导致父级向下移动 10px,这是父子元素的外边距折叠,用构建 BFC 的方式解决。
.con {
width: 300px;
background-color: antiquewhite;
overflow: auto; /* 构建BFC */
}
效果如下:
那么对于毗邻的兄弟节点,方法也是一样,把一个节点构建成 BFC 即可
<div class="con">
<div class="one"></div>
<div style="overflow: auto;">
<div class="two"></div>
</div>
</div>
BFC的创建方式
方法很多,可根据实际情况选择
- 根元素(html)
- 浮动元素(元素的 float 不是 none)
- 绝对定位元素(元素的 position 为 absolute 或 fixed)
- 行内块元素(元素的 display 为 inline-block)
- 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
- 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
- 匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
- overflow 值不为 visible 的块元素
- display 值为 flow-root 的元素
- contain 值为 layout、content或 paint 的元素
- 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
- 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
- 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
BFC解决了什么问题
上面可看出 BFC 可以清除浮动,可以解决外边距折叠两问题。
BFC 可通俗理解成是构建一个独立的区域,可包含区域内的所有元素,包括浮动元素,与外界互不打扰的一个空间。absolute 是相对哪个元素定位的
position 属性取值有
relative, absolute, fixed 或 sticky
,元素设置了其中之一的就是定位元素。(换句话说,除static以外的任何东西)。
目前定位类型有四类:相对定位元素(relatively positioned element)是计算后位置属性为 relative 的元素。
- 绝对定位元素(absolutely positioned element)是计算后位置属性为 absolute 或 fixed 的元素。
- 粘性定位元素(stickily positioned element)是计算后位置属性为 sticky 的元素。用于滑动中固定某一元素,这个目前有些兼容性问题。
相对定位
position: relative;
元素按照文档流的布局放置元素,它的用处是可以在不改变布局方式的前提下调整元素位置,使用top bottom left right
绝对定位
position: absolute;
绝对定位的元素脱离了文档流,不会占据文档流的空间,感觉就像在文档流的上一层。
绝对定位的元素可以使用top bottom left right
调整布局位置,在没有设置这几个值的时候,绝对定位元素显示还是保持在当前的位置。如果设置了值,那么这个元素就需要找到一个锚点,因为已经脱离文档流,所以需要找到一个参考点,这参考点就是最近的非 static 祖先元素
,可以是relative, absolute, fixed
,一直往上到 body 元素。
所以常常会采用relative + absolute
的组合布局方式,当然也可以利用绝对定位元素在当前位置显示的特性结合margin
来使用。
绝对定位还有个用处,就是避免触发回流,因为脱离正常的文档流,因此对于频繁回流的元素可以采用绝对定位。z-index
z-index
表示创建一个新的显示层级,值大的在最上层。多个绝对定位元素会按照后一个覆盖前一个的显示方式,而且绝对定位元素会覆盖文档流中的元素,那么只有在元素位置不当便调整顺序的时候才只用,正常情况下不建议设置值,毕竟多使用一个元素,就容易出现诡异的问题。DPR
先看看几个概念像素
是图像显示的基本单位,类似于米是长度的一个单位一样。1像素是显示的最小区域。物理像素
设备的物理像素,每个设备的物理像素都是厂家固定好的,css像素
这个主要用于编码用的,约定好的在显示层上的单位,screen.width
可获取到逻辑编码中的窗口最大像素。DPR
在 iphone 没有搞事之前,物理像素和逻辑像素是相等的,但如今高清屏已经快成标配,可显示的像素点越多越清晰,导致设备上每英寸可显示的像素点(PPI)越来越多,这样一来,屏幕的大小没变,css的逻辑像素没变,可物理像素却变多了,一个逻辑像素要对于多个物理像素,这两者的比例就是 DPR,DPR = 物理像素/css逻辑像素
,可以通过window.devicePixelRatio
获取设备的 DPR。1px 问题了解么?有什么解决方案?
在高清屏中 DPR 可能会是 2 或者 3 ,那么原先 1px 像素的线在高清屏下就占了2个或者3个物理像素,导致线看着比较粗。
解决:
- 使用伪类,设置 border 1px scale(0.5)
- 设置 meta initial-scale 根据DPR设置初始值
伪类 + transform: scaleY(0.5);
/* 伪类 + transform: scaleY(0.5); */
.px1 {
position: relative;
}
.px1:before {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 200%;
border: 1px solid black;
color: black;
height: 200%;
transform-origin: left top;
transform: scale(0.5);
}
link 和 @import 的区别
@import 根据字面意思就知道是用于导入其他样式文件的,两者的区别如下:
从属关系区别
link:是 html 提供的标签,不仅可以加载css样式表,还可以定义 RSS、rel 连接属性等。
@import:是 css 提供的语法规则,用于导入样式表。- 加载顺序区别
link:文件是同时加载。
@import 引入的 CSS 将在页面加载完毕后被加载。 - 兼容性问题
link 不存在兼容性问题;@import 可能会有兼容性问题
display:none与visibility:hidden的区别?
效果都是隐藏元素display:none
在文档布局中不在分配空间(节点),值变化会导致回流和重绘visibility:hidden
保留渲染树中的节点,占用空间,会导致重绘inline-block block 的区别
这两个分别是:行内块级元素和块级元素,顺带介绍下行内元素块级元素
块级元素的特点:元素总是在新的一行开始,盒模型的属性均可以控制,div p ul ol ...
等元素默认就是块级元素,也可以通过display: block;
设置为块级元素。行内元素
行内元素的特点:和其他元素在同一行,元素不可以设置高度和宽度,取决于内容的宽高度,默认的行内元素有span a lable input img ...
,也可通过display: inline;
设置为行内元素。行内块级元素
名字看上去就是上面两者的结合,同时具备了两个的特性。通过display: inline-block;
设置。
但是两个相邻的 inline-block 元素中间有空格就会出现间隙,解决办法可以粗暴的移除空格和换行,还有设置字体大小为 0 , 因空格也是字符,所以可给父级设置font-size:0、letter-spacing:-3px
rem em vh vw 的区别
这几个单位常用于自适应布局rem em
rem
: css3 新增,相对于根节点的字体大小的一个单位,eg:1rem * font-size:20px = 20px
在开发前先制定好一个基准,比如说以 375 宽的设计稿作为规范,设定这个宽度下的字体大小为 375/10 = 37.5 ,那设计稿下 60px 的宽对应的 rem 就是:60px = (60/37.5)rem
若使用css预处理,可以写一个转换函数@function px2rem($px) {
@return ($px/37.5) + rem;
}
em
: 与rem类似,但是相对于父级元素的字体大小。vw vh
相对于视口宽高的百分比值vw
: 1vw 等于视口宽度的1%vh
: 1vh 等于视口高度的1%vmin
: 选取 vw 和 vh 中最小的那个vmax
: 选取 vw 和 vh 中最大的那个
//iPhone 6尺寸作为设计稿基准
$vm_base: 375;
@function vw($px) {
@return ($px / $vm_base) * 100vw;
}
单行、多行文本居中
单行:
- 设置
line-height
跟height
相同 flex
布局,设置交叉轴对齐方式
多行:
- flex 布局
display: flex;align-items: center;
table 布局 ,外层使用
display: table;
内层使用vertical-align: middle;display: table-cell;
table-cell 可以将元素表现与单元格 td 类似,在对单元格设置居中,不过会破坏其他属性,比如浮动、margin 等.text{
background-color: sandybrown;
width: 200px;
height: 300px;
display: table;
}
.cell{
vertical-align: middle;
}
<div class="text">
<div class="cell">
今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.
</div>
</div>
设置外层 line-height 等于外层高度,文本一行的高度就等于容器的高度,内层使用
display: inline-block;vertical-align: middle;line-height: 17px;
内层设定为行内块级元素,设置行内元素的对齐方式是 middle,在对元素重新设定行高.text {
background-color: sandybrown;
width: 200px;
height: 300px;
line-height: 300px;
}
.cell {
display: inline-block;
vertical-align: middle;
line-height: 20px;
}
<div class="text">
<div class="cell">
今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.
</div>
</div>
css 选择器和优先级
id选择器(#myid)、类选择器(.myclassname)、标签选择器(div, h1, p)、相邻选择器(h1 + p)、子选择器(ul > li)、后代选择器(li a)、通配符选择器(*)、属性选择器(a[rel=”external”])、伪类选择器(a:hover, li:nth-child),简单介绍下面几个:
a > b
:子类选择器,只有直接的子类才生效a + b
:毗邻选择器,只有毗邻的下一个元素才生效a ~ b
:后续选择器,a元素之后的所有同级的b元素[attribute]
:属性选择器,含有这个属性的元素才生效:first-of-type
: 选择器匹配元素其父级是特定类型的第一个子元素
选择器权重
优先级排序:!important
> 行内样式 > ID > 类、伪类、属性 > 标签名 > 通配符 > 继承
权重值如下,每个都是相差一个量级
- word-break: break-all 对字符起作用,断开单词,下个字母自动到下一行。主要解决了长串英文的问题。
- word-wrap:break-word 只对英文起作用,以单词作为换行依据
哪些属性可以继承
元素外观相关的属性可以继承,比如字体相关的属性、文本系列的属性。布局相关的属性不可以继承,具体属性名就不列举了。flex 常见有属性
容器上的属性
flex-direction
: 主轴方向flex-wrap
: 换行的方式flex-flow
:上面两个的简写justify-content
: 主轴的对其方式align-items
: 交叉轴的对齐方式align-content
: 多根主轴的对齐方式
元素上的属性
order
: 排序值,数值越小越靠前flex-grow
: 项目放大的比例,默认为 0 不放大flex-shrink
: 项目缩小的比例,默认 1flex-basis
: 属性定义了在分配多余空间之前,项目占据的主轴空间,如果元素定义了宽,那么宽度将无效默认 autoflex
:以上三个的简称