css盒模型
- 盒模型的概念
css定义所有的元素都可以项盒子一样的外形和平面空间,它是CSS布局的基石,规定了网页元素如何显示以及元素之间的相互关系;
盒子模型有两种,分别是 ie 盒子模型和标准 w3c 盒子模型
- 盒模型的组成
css盒子模式都具备这些属性:内容(content)、填充(padding)、边框(border)、边界(margin)
- 标准模型和IE模型的区别,height的计算方式
从上图可以看到标准 W3C 盒子模型的范围包括 margin、border、padding、content,并且 content 部分不包含其他部分
w3c中的盒子模型的宽:包括margin+border+padding+width;
width:margin*2+border*2+padding*2+width;
height:margin*2+border*2+padding*2+height;
从上图可以看到 IE 盒子模型的范围也包括 margin、border、padding、content,和标准 W3C 盒子模型不同的是:IE 盒子模型的 content 部分包含了 border 和 pading。
IE中的盒子模型的width:也包括margin+border+padding+width;
上面的两个宽度相加的属性是一样的。不过在ie中content的宽度包括padding和border这两个属性;
- 如何设置两种盒子模型
标准盒模型:box-sizing:border-box;
IE盒模型:box-sizing: box-sizing
-
JS如何获取盒模型的宽/高
1.dom.style.width/height:只能取出内联样式的宽度和高度
这种方式只能取到dom元素内联样式所设置的宽高,也就是说如果该节点的样式是在style标签中或是外部的CSS样式表中的话,通过这种方法是没办法获取dom的宽高的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
.child {
background: rgb(228, 95, 95);
height: 100px;
margin-top: 10px;
}
</style>
</head>
<body>
<section id="sec">
<article class="child">嵌入式</article>
<article id="child2" style="width:300px; height:300px; background:#faa;">内联样式</article>
</section>
<script>
let height1 = document.getElementsByClassName('child')[0].style.height
let height2 = document.getElementById('child2').style.height
console.log('height1', height1)
console.log('height2', height2)
</script>
</body>
</html>
2.dom.currentStyle.width/height:获取即时的计算的样式,但是只有IE支持
这种方式获取的是在页面渲染完成后的结果,意味着无论以哪种方式,内联也好,style标签中也好,都可以获取的到。但是这种方法只能在IE浏览器中使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
.child {
background: rgb(228, 95, 95);
height: 100px;
margin-top: 10px;
}
</style>
</head>
<body>
<section id="sec">
<article class="child">嵌入式</article>
<article id="child2" style="width:300px; height:300px; background:#faa;">内联样式</article>
</section>
<script>
let height1 = document.getElementsByClassName('child')[0].currentStyle.height
let height2 = document.getElementById('child2').currentStyle.height
console.log('height1', height1)
console.log('height2', height2)
</script>
</body>
</html>
chrome浏览器效果
3.**window.getComputedStyle(dom).width/height**:获取即时计算的样式,支持其他浏览器,兼容性更好
这种方式的原理和方式二是一样的,都可以在任何方式在获取页面在完成渲染之后的结果。相比dom.currentStyle.width/height方式而言,这种方式可以兼容更多的浏览器,不仅仅是IE浏览器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
.child {
background: rgb(228, 95, 95);
height: 100px;
margin-top: 10px;
}
</style>
</head>
<body>
<section id="sec">
<article class="child">嵌入式</article>
<article id="child2" style="width:300px; height:300px; background:#faa;">内联样式</article>
</section>
<script>
let height1 = window.getComputedStyle(document.getElementsByClassName('child')[0]).height;
let height2 = window.getComputedStyle(document.getElementById('child2')).height;
console.log('height1', height1);
console.log('height2', height2)
</script>
</body>
</html>
4.**dom.getBoundingClientRect( ).width/height**:计算盒模型在页面中的绝对位置
这个方法可以获得运行后的属性。一般用于计算一个元素的绝对定位。返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
.child {
background: rgb(228, 95, 95);
height: 100px;
margin-top: 10px;
}
</style>
</head>
<body>
<section id="sec">
<article class="child">嵌入式</article>
<article id="child2" style="width:300px; height:300px; background:#faa;">内联样式</article>
</section>
<script>
let dom1 = document.getElementsByClassName('child')[0].getBoundingClientRect();
let dom2 = document.getElementById('child2').getBoundingClientRect();
console.log('dom1 ', dom1);
console.log('dom2', dom2)
</script>
</body>
</html>
5.**dom.offsetWidth/offectHeight:**返回元素实际大小
这组方法可以 返回元素实际大小,包含边框,内边距和滚动条。返回元素大小,默认单位是px。如果没有设置任何CSS宽度和高度,也会在计算后得到宽度和高度。理解offsetWidth和offsetHeight设置的元素实际大小:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
.child {
background: rgb(228, 95, 95);
height: 100px;
margin-top: 10px;
border: 1px solid royalblue;
margin: 10px;
padding: 20px;
}
</style>
</head>
<body>
<section id="sec">
<article class="child">嵌入式</article>
<article id="child2" style="width:300px; height:300px; background:#faa;">内联样式</article>
</section>
<script>
let height1 = document.getElementsByClassName('child')[0].offsetHeight;
let height2 = document.getElementById('child2').offsetHeight;
console.log('height1 ', height1);
console.log('height2', height2)
</script>
</body>
</html>
设置边框,输出值等于原本大小+边框大小;
设置内边距,输出值等于原本大小+内边距大小;
设置外边距 / 滚动条,输出值无变化等于原本大小;
对于元素大小的获取,一般是块级(block)元素并且以设置了CSS大小的元素较为方便。如果是内联元素(inline)或者没有设置大小的元素就尤为麻烦,所以,建议使用的时候注意。
- 根据盒模型解释边距重叠
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
#sec p {
background: rgb(221, 99, 156);
margin-bottom: 10px;
margin-top: 30px;
}
</style>
</head>
<body>
<section id="sec">
<p class="item1">1</p>
<p class="item2">2</p>
<p class="item3">3</p>
</section>
</body>
</html>
上图:边距重叠,解决,给子元素增加一个父元素,创建BFC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: royalblue;
}
#sec p {
background: rgb(221, 99, 156);
margin-bottom: 10px;
margin-top: 30px;
}
.item-box {
/* 父级容器创建BFC */
overflow: auto;
/* overflow: hidden; */
}
</style>
</head>
<body>
<section id="sec">
<p class="item1">1</p>
<div class="item-box">
<p class="item2">2</p>
</div>
<p class="item3">3</p>
</section>
</body>
</html>
-
BFC(Block Formatting Content)边距重叠解决方案
1.BFC概念:
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
2.BFC布局规则:
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定,同一个BFC中两个相邻的Box垂直方向的margin会发生重叠;
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
在同一个BFC下会发生外边距合并
BFC的区域不会与float box重叠
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: rgb(83, 168, 238);
}
#sec p {
background: rgb(221, 99, 156);
height: 20px;
}
#sec .item2 {
float: left;
height: 100px;
width: 200px;
background-color: aqua;
}
#sec .item3 {
height: 120px;
background: burlywood;
}
</style>
</head>
<body>
<section id="sec">
<p class="item1">1</p>
<p class="item2">2</p>
<p class="item3">3</p>
</section>
</body>
</html>
当item2box浮动之后,由于脱出文档流,item3高度增加之后环绕于item2,假设要解决这个问题,让item在垂直方向上增加高度,不包裹item2,便需要给item3box创建BFC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
#sec {
background: rgb(83, 168, 238);
}
#sec p {
background: rgb(221, 99, 156);
height: 20px;
}
#sec .item2 {
float: left;
height: 100px;
width: 200px;
background-color: aqua;
}
#sec .item3 {
height: 120px;
background: burlywood;
/* ITEM3创建BFC */
overflow: hidden;
}
</style>
</head>
<body>
<!BFC 不与Float重叠---->
<section id="sec">
<p class="item1">1</p>
<p class="item2">2</p>
<p class="item3">3</p>
</section>
</body>
</html>
计算BFC的高度时,浮动元素也参与计算
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
.float-box {
background-color: crimson;
}
.float-box .float {
font-size: 20px;
color: rgb(13, 124, 228);
float: left;
}
</style>
</head>
<body>
<section class="float-box">
<p class="float">我是浮动元素</p>
</section>
</body>
</html>
上图中父级容器的背景色是没有展示的,高度为0; 因此可以为父级容器创建BFC清除浮动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Css盒模型</title>
<style>
html * {
padding: 0;
margin: 0;
}
.float-box {
background-color: crimson;
/* 父级容器创建BFC ,以下方式都可使子容器参与父级容器的高度计算*/
/* overflow: hidden; */
/* overflow: auto; */
float: left;
}
.float-box .float {
font-size: 20px;
color: rgb(13, 124, 228);
float: left;
}
</style>
</head>
<body>
<section class="float-box">
<p class="float">我是浮动元素</p>
</section>
</body>
</html>
每个盒子的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 100%;
position: relative;
}
.left {
width: 100px;
height: 150px;
float: left;
background: rgb(139, 214, 78);
text-align: center;
line-height: 150px;
font-size: 20px;
}
.right {
height: 300px;
background: rgb(170, 54, 236);
text-align: center;
line-height: 300px;
font-size: 40px;
}
</style>
<body>
<div class="left">LEFT</div>
<div class="right">RIGHT</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 100%;
position: relative;
}
.left {
width: 100px;
height: 150px;
float: left;
background: rgb(139, 214, 78);
text-align: center;
line-height: 150px;
font-size: 20px;
}
.right {
/* 创建BFC */
overflow: hidden;
height: 300px;
background: rgb(170, 54, 236);
text-align: center;
line-height: 300px;
font-size: 40px;
}
</style>
<body>
<div class="left">LEFT</div>
<div class="right">RIGHT</div>
</body>
</html>
上图right会自动的适应宽度,这时候就形成了一个两栏自适应的布局。
- BFC的作用
由上述例子可知,BFC的作用
1.BFC可以避免margin重叠;
2.清除浮动
3.自适应两栏布局
4.如何创建BFC
1、float的值不是none。
2、position的值不是static或者relative。
3、display的值是inline-block、table-cell、flex、table-caption或者inline-flex
4、overflow的值不是visible
综上:
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。