CSS盒模型
盒子Box
Box是CSS布局的对象和基本单位,一个页面由很多个Box组成;
Box的类型,由元素的类型和display属性决定;
不同类型的Box,会参与不同的Formatting Context,因此Box内的元素会以不同的方式渲染;
标准模型 与 IE模型
标准W3C盒子的宽度为width = content内容区域
IE盒子的宽度为 width = conetent内容区域 + border + padding
标准盒子与IE盒子的设置是box-sizing属性:
标准盒子:box-sizing: content-box;
IE盒子:box-sizing: border-box;
所以由上面的知识点可以知道,宽度相同的盒子,标准盒子的width要比IE盒子的大;对比下图可一清二楚:
顺便提一下,chrome的box-sizing值是content-box;
BFC
块级格式化上下文(Block Fromatting Context,BFC),指一个 隔离的独立的块级渲染区域,是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒子的区域,也是 浮动元素 与其他元素的交互限定区域。
注意:一个 BFC 的范围包含创建该上下文的所有子元素,但 不包括 创建了新 BFC 的子元素的内部元素。这从另一个角度说明,一个元素不能同时存在于两个 BFC 中。因为如果一个元素能够同时处于两个 BFC 中,那么就意味着这个元素能与两个 BFC 中的元素发生作用,就违反了 BFC 的 隔离作用。
创建BFC的方法:
1、float部位none;
2、position不为static或者relative;
3、display为table
4、overflow部位visible;
运用场景:
1、外边距崩塌问题:
两个相邻盒子有反方向的外边距,会在垂直方向上产生上下边距合并的效果:
如两个外边距都为
30的盒子,他们之间的距离并不是60,而是30;
解决方法:给任意盒子加个父元素,并给其父元素加上任意创建BFC的条件;
2、另外还有清除浮动、浮动元素造成父元素的塌陷等问题,都可以利用BFC解决;
IFC
内联格式化上下文(Inline Formatting Context),是用于 布局内联元素 盒子的一块 渲染区域。
形成条件: 块级元素中仅包含内联级别元素;
布局规则:
1、子元素水平方向横向排列,并且垂直方向起点为元素顶部。
2、子元素只计算横向样式空间,padding、border、margin在垂直方向上的样式空间不会被计算。
3、在垂直方向上,子元素会以不同形式来对齐vertical-align
(例如:给高度最大的子元素设置vertical-align: 可以实现其他元素垂直居中)
4、能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和与其中的浮动来决定。
5、IFC中的“line box”一般左右边贴紧其包含块,但float元素会优先排列。
6、IFC中的“line box”高度由 CSS 行高计算规则来确定,同个IFC下的多个line box高度可能会不同。
7、当 inline-level boxes的总宽度少于包含它们的line box时,其水平渲染规则由text-align 属性值来决定。
(例如,利用text-align实现多元素水平居中)
8、当一个“inline box”超过父元素的宽度时,它会被分割成多个boxes,这些 boxes 分布在多个“line box”中。如果子元素未设置强制换行的情况下,“inline box”将不可被分割,将会溢出父元素。
举例场景:
垂直间距不生效
如,在IFC中,给子元素加上margin值,只有左右边距生效,上下并没有生效,这就符合了第二条规则;
FFC 与 GFC
FFC
flex是flexible box的缩写,一般称之为弹性盒模型。
flex布局提供一种更加有效的方式来进行容器内的项目布局,以适应各种类型的显示设备和各种尺寸的屏幕,使用Flex box布局实际上就是声明创建了自适应格式上下文(Flex Formatting Context) 。
使用flex布局不得不提一个重要的属性flex: 1;
这是一个简写属性,由flex-grow,flex-shrink,flex-basis组成,默认值为0 1 auto
这里对flex-basis深究一下:
flex-basis的尺寸是作用在content-box上的,这个和width属性是一样的;而且flex-basis的优先级比width大,也就是同时设置了这两个,浏览器是优先展示flex-basis;
在content-box上:
在border-box上:
再看看zhangxinxu大佬的一句话,真的学到了!!
再来看看width与flex-basis表现不同的情况:
可以看到当content内容超出时,flex-basis是按照content的最小内容宽度显示,而width是限制死的,字符直接溢出容器;
其实还有很多更细节的地方,这里就不一一探究了,但是有一个极其重要的原则:
flex-basis数值属性值和width数值属性值不要同时使用,Flex布局中,除非万不得已,否则没有使用width属性的理由,请使用flex-basis代替。
flex一个问题:
有一个flex布局的盒子,其中子元素box1固定宽度,另一个子元素box2自由伸缩放,box2中有个p元素;
<style>
.box1 {
width: 100px;
height: 100%;
background-color: aqua;
}
.box2 {
flex: 1;
background-color: rgba(255, 145, 0, 0.89);
}
.box-wrap {
display: flex;
// width: 500px; 后面再加上
height: 500px
}
p {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
</style>
<div class="box-wrap">
<div class="box1">box1</div>
<div class="box2">
<p>
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</p>
</div>
</div>
Then...box2把父盒子撑开的同时,把兄弟元素box1也挤得变形;
原因是:box2中的p元素装有长文本,内容套多导致父盒子被撑开;
解决方法: box2(也就是被撑开的元素)加上属性width: 0;
为什么能解决:
flex-basis属性下的最小尺寸是由内容决定的,而width属性下的最小尺寸是由width属性的计算值决定的。
按我的理解是:
1、在flex-basis和width的共同作用下,首先flex-basis的优先级是大于width的,所以在的正常宽度内(父盒子不被撑开或者子盒子的宽度大于内容宽度),是先按flex-basis的默认值0%展示的;
2、但是当内容宽度大于正常宽度时,就需要按照width的计算值来算,比如我给父盒子加上width: 500px,由于box1为100px,所以box2在设置width时在400px的范围内是正常的;但是如果width设置超过了400px,box2首先会挤压box1,然后当box1被挤压到最小内容宽度时,会撑开父盒子进行增长;
那么如果说box2不设置宽度的话,那么其宽度就由内容宽度决定,所以父盒子会被撑开;其次,设置width后,则按照上面理解的第二条,width: 0则不会超出父盒子,所以box2最大也就是父盒子的宽度 - box1.width
flex知识点2
在W3C的文档中,flex-basis 除了能接受 auto、content等值外,还能接受 与width、height 属性相同的值,并且解析方式也相同。就是说 height 怎么解析 0px、0%,flex-basis 也这么解析。所以一般情况下,这2个值对 flex-basis 而言,在浏览器上的表现效果应该都是一样的;但是:
如果一个元素的
flex-basis属性 的值为百分数,且它父级元素(flex容器)在主轴方向上的尺寸没有被显式设置,此时flex-basis的值会被解析为content。即此种情况下,0%呈现的结果会与0px不同
通过查阅文档,知道W3C对于flex-basis的解析规则经历了0px > 0% > 0px的变化,但是在浏览器中只有0px > 0%,原因是会有兼容性问题。现在已有很多网页都利用了 flex 属性的这个特性来开发。如果简写语法里 flex-basis 的解析从 0% 变为 0px 会导致部分情况下flex容器塌陷,致使很多网页异常;
可以以下例子更直观的看到两者的区别:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box-container {
/* 没有设置明确height或者height为auto都会导致塌陷 */
display: flex;
flex-direction: column;
align-items: center;
}
.box-wrap {
flex-grow: 1;
flex-shrink: 1;
padding: 5px;
margin: 5px;
overflow: hidden;
background-color: aqua;
}
.box {
width: 300px;
height: 300px;
background-color: rgba(255, 145, 0, 0.89);
}
.basis-0-pct {
flex-basis: 0%;
}
.basis-0-px {
flex-basis: 0;
}
</style>
</head>
<body>
<div class="box-container">
<p>flex: 0%的盒子</p>
<div class="box-wrap basis-0-pct">
<div class="box"></div>
</div>
</div>
<div class="box-container">
<p>flex: 0的盒子</p>
<div class="box-wrap basis-0-px">
<div class="box"></div>
</div>
</div>
</body>
</html>
flex: auto 与 flex: 1; flex: 0 与 flex: none;的区别
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>学习</title>
<style>
.box-wrap {
display: flex;
/* 为了方便看效果,flex: 0与flex: none会加上该属性 */
flex-direction: column;
width: 800px;
margin: 100px auto;
}
.item {
margin: 10px;
background-color: aquamarine;
}
/* 不断变化该属性值进行测试 */
.flex-type {
flex: 1;
}
</style>
</head>
<body>
<div class="box-wrap">
<div class="item flex-type">上面代码使用useEffect来进行数据的转化,效率很低。其实并不需要使用useEffect。当某些值可以从现有的props或state中计算出来时,不要把它放在状态中,在渲染期间计算它</div>
<div class="item flex-type">上面代码使用useEffect来进行数据的转化,效率很低。其实并不需要使用useEffect。当某些值可以从现有的props或state中计算出来时,</div>
<div class="item flex-type">上面代码使用useEffect来进行数据的转化,效率很低。其实并不需要使用useEffect。</div>
<div class="item flex-type">上面代码使用useEffect来进行数据的转化,效率很低。</div>
</div>
</body>
</html>
flex: 1;
flex: auto;
felx: 1是平分空间,flex: auto是根据内容大小来分,不是均分;
两者的差别为flex-basis: 0%/auto
flex: 0:
flex: none;
flex: 0即flex-grow: 0; flex-shrik: 1; flex-basis: 0%;
而flex: none即flex-grow: 0; flex-shrik: 0; flex-basis: auto;
flex: 0 不可扩大,可缩小,表现形式为最小内容宽度;
而flex: none 不可扩大,不可缩小,内容本身的宽度是多少就是多少;
GFC
GFC即网格布局格式化上下文(Grids Formatting Context),目前使用还比较少,届时再回来补充......
另外,再补充一点对于display: none, overflow: hidden, visibility: hidden之间的区别
1、dispaly: none: 隐藏元素,不占据空间;会产生回流与重绘;
2、overflow: hidden: 超出的元素部分隐藏且不占据空间;
3、visibility: hidden: 隐藏元素,但占据空间;只产生重绘