参考: https://juejin.im/post/59dca82051882578db27b1d6
包含块
- 概念
每个盒子会变成他后代盒子的包含块,后代盒子的大小和位置会根据他包含块的矩形边框进行计算。但是不会受到包含块的限制,可能会溢出。 - 确定包含块的方法
- 对于根元素、position=fixed的元素,包含块都是视窗
- 如果元素是relative或者static,则是他最近的块形父元素的内容区(content)——注:规定了父元素必须是block container
- 如果元素是absolute,包含块是最近的非static的父元素的Padding区——注:父元素的类型未规定
包含块最直观的判断是一个元素对大小设置百分比时,相对的元素是哪一个,这个元素就是他的包含块
最普通的
例子
<div id="div1">
<p id="p1">第一行段落</p>
<p id="p2">
<em>第二行段落斜体<strong>加粗文字</strong></em>
</p>
</div>
* {
padding: 0;
margin: 0;
}
div {
background: red;
}
p {
padding: 10px;
}
#p2 {
background: green;
}
em {
padding-left: 10%;
background: antiquewhite;
}
strong {
padding-left: 10%;
background: aqua;
}
当em变成absolute定位
<div id="div1">
<p id="p1">第一行段落</p>
<p id="p2">
<em>第二行段落斜体<strong>加粗文字</strong></em>
</p>
</div>
* {
padding: 0;
margin: 0;
}
p {
padding: 10px;
width: 300px;
}
#div1 {
position: relative;
background: aquamarine;
padding: 10px;
width: 500px;
margin: 5px;
}
#p2 {
background: green;
}
em {
padding-left: 10%;
background: antiquewhite;
position: absolute;
top:0;
}
strong {
background: aqua;
padding-right: 10%;
}
发现em包含块已经不是p2了,而是div1
盒模型
- 概念
网页设计中常听的属性名:内容(content)、填充(padding)、边框(border)、边界(margin), CSS盒子模式都具备这些属性。
这些属性我们可以用日常生活中的常见事物——盒子作一个比喻来理解,所以叫它盒子模式。
CSS盒子模型就是在网页设计中经常用到的CSS技术所使用的一种思维模型。 -
- Margin(外边距) - 清除边框外的区域,外边距是透明的。
- Border(边框) - 围绕在内边距和内容外的边框。
- Padding(内边距) - 清除内容周围的区域,内边距是透明的。
- Content(内容) - 盒子的内容,显示文本和图像。
- 总元素的宽度=宽度+左填充+右填充+左边框+右边框+左边距+右边距
- 总元素的高度=高度+顶部填充+底部填充+上边框+下边框+上边距+下边距
- Margin
1.宽度。分为四个方向,都支持百分比和具体的像素。并且margin的百分比是根据元素的包含块(containing-block)的width来计算。并不是margin-top/ bottom对应height
<body>
<div class="main">
<p>段落1</p>
</div>
</body>
* {
margin:0;
padding:0;
}
body {
background: green;
}
.main {
background: aqua;
width: 400px;
border: 2px solid red;
margin: 10px;
padding: 10px;
}
p {
background: antiquewhite;
margin-top: 10%;
margin-left: 10%;
padding: 10%;
}
2.内联元素(display: inline)的margin-top和margin-bottom失效。浏览器不允许设置(内联对象就是不自动产生换行的元素,比如span)
3.对于position=static元素,负值相当于将元素向负值方向移动覆盖,但是只会覆盖颜色,不会覆盖文字
注意这句话:没有width的情况下,类似padding效果,但还是向左偏移,width=100%而已
<body>
<div class="base">body content left top</div>
<div class="one">one</div>
<div class="two">two</div>
</body>
* {
margin: 0px;
padding: 0px;
}
body {
background: #ccc;
margin: 20px;
}
.base {
background: #fcf;
}
.one {
background: aqua;
/* width: 200px; */
margin-top: -10px;
margin-bottom: -10px;
/* 没有width的情况下,类似padding效果,
但还是向左偏移,width=100%而已
*/
margin-left: -10px;
}
.two {
background: #ffc;
/* margin-top: -14px; */
}
4.对于position=relative元素, 负值还是会把下面的元素粘着一起移动,但会完全覆盖前一个元素。
<body>
<div class="main">
<div class="base">body content left top</div>
<div class="one">one</div>
<div class="two">two</div>
</div>
</body>
* {
margin: 0px;
padding: 0px;
}
body {
background: #ccc;
margin: 20px;
}
.main {
position: relative;
}
.base {
background: #fcf;
}
.one {
background: aqua;
/* relative还是会粘着下面的元素一起移动上去
和static不同的是,会完全覆盖前一个元素
*/
position: relative;
margin-top: -10px;
/* top: 8px; */
}
.two {
background: #ffc;
}
5.对于position=absolute元素,因为元素脱离了文档流,所以负值只会自己发生偏移,对前后元素没有任何影响。
.one {
background: aqua;
position: absolute;
margin-top: -10px;
}
6.对于float元素,可以通过负值进行覆盖,最常见的应用是三栏应用
<div class="main">
<div class="main-content">main content</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
*{
margin:0;
padding: 0
}
.main{
float: left;
width: 100%;
}
.main .main-content{
margin: 0 210px;
background-color: rgba(33, 114, 214, 0.8);
height: 500px
}
.left{
width: 200px;
float: left;
background-color: rgba(255, 82, 0, 0.8);
margin-left: -100%;
height: 200px
}
.right{
width: 200px;
height: 200px;
margin-left: -200px;
float: left;
background-color: rgba(90, 243, 151, 0.8);
}
7.水平的margin不会合并(inline-block和inline都支持)
span {
background: aqua;
margin: 20px;
}
8.都属于常规流内(in flow)块级盒,处于同一个上下文的兄弟元素 解决方法:将其中一个块盒变成BFC,阻止margin的合并 (详见上一篇)
9.块级父元素和其子元素,在没有padding,border,height,空隙将之隔开时,子元素的margin会渗透到父元素上。简单讲,父元素和子元素之间没有其他元素。
<div class="parent">
<div class="box">box</div>
</div>
body {
background: red;
}
.parent {
height: 60px;
background: #ccf;
下面三行任意一行即可解决渗透问题
padding: 10px;
/* overflow:hidden; */
/* border: 1px solid; */ */
}
.box {
margin-top: 20px;
}
解决前
解决后
Padding
1.宽度。同Margin
2.内联元素(display: inline)的padding生效,但是top和bottom并不会推挤,只会覆盖其他元素,覆盖情况遵循z-index原则
<body>
<p>我是span上面的块级元素,被覆盖</p>
<span>我是一个行内元素</span>
<p>我是span下面的块级元素,被覆盖</p>
</body>
* {
margin: 0;
padding: 0;
}
body {
background: #f1f1f1;
}
p {
background: #ccf;
}
span {
background: #fcc;
padding: 10px;
}
/*
为什么第一个p被完全盖住,而第二个只有背景被盖住?
因为非定位元素按照节点在html中出现的顺序排列,后出现的在上面
所以span会完全盖住上一个的,而背景色的优先级实在太低
所以span只能盖掉下面p的背景
*/
3.合并。Padding不存在合并情况
4.不允许负值
- Border
1.宽度。只有px,不支持百分比
2.合并。inline元素左右不合并,上下会合并。inline-block&block元素四个方向都不会合并
定位模式
常规流
流内元素有几大模型。CSS2.1中定义了IFC(Inline Formatting Contexts)与 BFC(Block Formatting Contexts)。CSS3中增加了GFC(GridLayout Formatting Contexts)和FFC(Flex Formatting Context)。
- BFC
参考上一篇BFC - IFC(Inline formatting contexts)内联格式化上下文
- 如何产生:只有在一个块级元素中仅仅包含内联级别元素时才会生成
- 特性
- 从包含块顶部水平方向排列
- 排列情况和浮动与否会改变行盒的高度
- 当一个行盒被分割,margin,border,padding都不会再有视觉效果了
- 浮动
- 概念:float CSS属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动中移除,尽管仍然保持部分的流动性
- 位置
- 当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素
- 浮动元素会根据上一个元素的类型判断位置,如果上一个是浮动的,则跟随他,放不下就挤到下一行
- 如果上一个是标准流的元素,则浮动元素的相对垂直高度不变,顶部和上一个元素的底部对齐。
- 清除浮动
- 引入空隙,父元素使用::after伪元素
- 浮动元素限制成BFC,使用overflow:hidden
- clear属性
- 绝对定位
- position=absolute设置元素绝对定位,会导致元素变成绝对定位,脱离文档流,并且元素此时是BFC布局,Margin不会进行合并。使用top/bottom/left/right(下面简写成TBLR)控制位置的变动,具体像素和百分比都参照包含块进行偏移。
- position=static 常规流布局,无法通过TBLR控制位置
- position=relative 盒子相对于其常规流位置进行偏移,兄弟元素相对其偏移前的位置定位。使用TBLR控制时,如果是固定像素,那盒子相对于自身边界偏移,如果是百分比,则参照包含块偏移。
- position=fixed 包含块是视窗,使用TBLR控制都是相对包含块偏移
- 对于百分比:left/right 相对于包含块的width,top/bottom相对于包含块的height
层叠关系
- 背景和边框 —— 形成层叠上下文的元素的背景和边框。 层叠上下文中的最低等级。
- 负z-index值 —— 层叠上下文内有着负z-index值的子元素。
- 块级盒 —— 文档流中非行内非定位子元素。
- 浮动盒 —— 非定位浮动元素。
- 行内盒 —— 文档流中行内级别非定位子元素。
- z-index: 0 —— 定位元素。 这些元素形成了新的层叠上下文。
- 正z-index值 —— 定位元素。 层叠上下文中的最高等级
当对某一个元素的z-index赋值了除了auto以外的值,就创建了一个新的层叠上下文,独立于其他的层叠上下文。
比较顺序变成,先比较各个层叠上下文的z-index。然后在层叠上下文中比较子元素的优先级。