简介
我们知道,width属性的默认值是auto,但是在开发中,很多时候我们会将一个块元素的width属性设为100%用于达到和其包含块同等的宽度的目的。而且有时候,width属性值为auto和100%看到的效果几乎是一样的,那它们两者到底有没有区别呢?
阅前须知
首先,我们得知道不同盒模型中width属性对应的盒模型部分是不一样的
- 比如在标准盒模型中,
width的值就是盒模型的content(内容)区域的长度 - 但是在
IE盒模型(box-sizing: border-box)中,width的值却是content(内容) + padding(内边距) + border(边框)这三者区域的总长度
对于常规流块盒有个特性:其在水平方向上必须撑满包含块的内容区域。下面我们的讨论将在标准盒模型中开展:
width: auto
当元素没有显式设置width属性时,那么width属性的默认值就是auto;通过该属性值设置内容区宽度时有个特点,那就是要满足content + padding + border + margin撑满整个父元素的content区域
简单来说,就是子盒子所占空间在水平方向上一定要撑满包含块的内容区域。话不多说,光看理论知识不好理解,我们来看看几个示例:
子元素没有padding、border、margin属性
由于width的默认值就是auto,所以我们可以不用书写
<style>
.father {
width: 400px;
height: 400px;
background-color: lightblue;
}
.son {
/* width: auto; */
height: 200px;
background-color: orange;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
在这种情况下,我们可以看到子元素内容区的长度被设置成了400px,刚好符合子盒子所占的空间在水平方向上一定要撑满父元素的内容区域的特点
子元素有padding、border、margin
盒模型分成四个部分:content、padding、border和margin,盒子的大小在计算的时候不包含margin,但是盒子所占的空间包括marign
.father {
width: 400px;
height: 400px;
margin: 0 auto;
background-color: lightblue;
}
.son {
/* width: auto; */
height: 200px;
padding: 0 10px;
border: 10px solid #ccc;
margin: 0 10px;
background-color: orange;
}
从图中可以看出,内容区域的宽度变为了340px,而不是刚刚的400px了。如果你理解了我们之前强调过的特点的话,那么肯定已经想到为什么了。因为浏览器看到width属性值为auto时,它给内容区分配长度是按照这个公式:内容区的长度 = 父元素内容区的长度 - 子元素的margin值 - 子元素的border值 - 子元素的padding值 得来的,刚好符合前面那个特点:子盒子所占空间在水平方向上一定要撑满包含块的内容区域
子元素margin值为负
刚刚我们谈到了子元素有margin值的情况,但那个值为正数。如果margin值为负数,会不会有什么特殊的情况出现呢?
.father {
width: 400px;
height: 400px;
margin: 0 auto;
background-color: lightblue;
}
.son {
/* width: auto; */
height: 200px;
margin: 0 -20px;
background-color: orange;
}
奇怪的事情出现了,子元素内容区的长度超过了父元素内容区的长度,从而导致子元素溢出到了父元素的外面,这是为什么呢?
其实不必吃惊,等你缓过神来就会发现这不还是前面讲过的东西吗?盒子所占的空间是包括margin的,也就是说计算该空间时用到的公式是 盒子所占空间 = margin值 + border值 + padding值 + content值,如果margin值为负数,那么想要让子元素所占空间填满父元素的内容区,子元素就必须要增加内容区的长度,所以子元素的内容区长度才变为了440px
width: 100%
一旦块级元素给width属性设置了100%后,子元素的content内容区长度就一定会等于父元素的content内容区长度,无论子元素有没有padding、border、margin属性,它的内容区长度已经和父元素牢牢绑定在一起了。简单来说就是一个公式:子元素的content长度 = 父元素的content长度
但这会导致一个问题,子元素一旦有border、padding或margin属性,如果不设置子元素的盒模型为IE盒,则很容易出现子元素溢出父元素的情况,具体看下面的示例:
子元素没有padding、border、margin属性
代码和margin: auto中的该示例没有什么变化,只不过将width属性值更改为了100%而已
<style>
.father {
width: 400px;
height: 400px;
margin: 0 auto;
background-color: lightblue;
}
.son {
width: 100%;
height: 200px;
background-color: orange;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
盒子渲染出来的结果和margin: auto一样,因为没有padding、border、margin属性的干扰,所以子元素所占区域的宽度就是内容区的长度400px
子元素有padding、border、margin
.father {
width: 400px;
height: 400px;
margin: 0 auto;
background-color: lightblue;
}
.son {
width: 100%;
height: 200px;
padding: 0 10px;
border: 10px solid #ccc;
margin: 0 10px;
background-color: orange;
}
此时子元素就已经溢出了父元素,原因很简单,在width:100%属性下,浏览器计算子元素内容区的长度时是参照父元素内容区的长度来的,父元素内容区长度为400px,那么子元素内容区长度也为400px,那再加上padding、border和margin最终呈现出来的效果,整个盒子肯定是会超过父元素的
子元素margin值为负
.father {
width: 400px;
height: 400px;
margin: 0 auto;
background-color: lightblue;
}
.son {
width: 100%;
height: 200px;
margin: 0 -20px;
background-color: orange;
}
至于这种情况,大家应该可以提前猜到结果了,内容区长度依然是400px,但是由于在margin: 0 -20px的作用下,整个盒子会向左偏移20px
总结
margin: auto和margin: 100%固然是有区别的,当我们真正理解了它们内部的原理时,发现在页面布局时根本就没有什么奇怪的问题,只是我们对某些知识了解不够深入罢了!