最近在开发S1 B/S 的前端页面时,有一个下载bs包进度条的样式编写,遇到一个莫名的坑,一句话描述不清,直接上图和代码。
先看一下原来的样式:
布局样式代码如下:
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.bar-wrapper {
width: 400px;
height: 80px;
border: 1px solid #333;
padding-top: 33px;
margin: 20px auto;
}
.progress-bar-container {
width: 180px;
height: 14px;
border: 1px solid red;
border-radius: 15px;
background: red;
margin: 0 auto;
}
.progress-bar {
display: block;
width: 25%;
height: 14px;
border-radius: 15px;
border: 1px solid greenyellow;
background: greenyellow;
}
</style>
</head>
<body>
<div class="bar-wrapper">
<div class="progress-bar-container">
<span class="progress-bar"></span>
</div>
</div>
</body>
</html>
可以看到,绿色部分的进度条高度是和它的父元素,也就是红色的部分的高度是一样的,都是14px,但是很明显绿色部分没有撑满红色部分的高度,在纵向上有一点偏移。
对于为什么会产生这个偏移,我暂时还没找到原因,不过有一个办法可以勉强解决这个偏移问题,就是去掉父元素的border,如下:
但是,如果这个border必要的话,就不能这么操作了,这个时候还需要给父元素加一个box-sizing属性,让它的值为content-box,注意,除了它,其他元素的这个属性都要设置为border-box,效果如下:
经过同事的讲解,终于明白了子元素对不齐父元素边框的原因了:box-sizing属性。先来说说box-sizing的两个属性值:border-box/content-box:
~1. border-box:这个属性值的作用是把一个盒模型的边框以及内边距都计算到设置的盒子的长宽中。以上面的进度条为例,红色区域的height设置的是14px;当我给它设置border-box的时候,它的各布局属性如下:
即//** 实际高度 = height = 2border + 2padding + contentHeight**// = 14px,所以它真正的内容区高度只有12px,即contentHeight = 12px。而绿色的部分是它的子元素,所以理应在红色部分的内容区,但是因为有一层border在外面,所以子元素始终对不齐红色的父元素的外边框,内容区会被边框挤下来一个边框宽度的距离;
- content-box:该属性值的作用的与border-box的区别就是:盒模型的边框和内边距都不包括在盒子的长宽中,当我们在style或者css文件中设置该盒子的高度height为14px时,再给它一个padding或者border,盒子的实际高度应该是 //实际高度 = contentHeight+ 2padding + 2border//,并且此时//contentHeight= height// = 14px:
上述进度条中,绿色的子元素也是14px的高度,且//浏览器默认的box-sizing属性值为content-box//,所以它的实际高度其实是14px,所以会超出父元素的高度,这个时候,如果把子元素的box-sizing属性设置为border-box,让他实际高度就为14px,再把红色的父元素的box-sizing属性设置为content-box,让他实际高度为16px(加上边框),那么就能让子元素完全嵌入父元素中了。总之,要让父元素的实际高度大于子元素,才不会把子元素挤出来。
所以还有一个解决方法就是,不给父子元素加box-sizing属性,只给父元素加2个边框值的高度:即给红色部分设置height:16px;或者父元素height不变,子元素高度减去2个边框值高度,即给绿色部分设置height:12px。