你不知道的CSS — width:100%、width:auto、box-sizing:border-box

2,679 阅读9分钟

在页面设计时,我们经常使用到width属性,width可以说是css的重中之重。小伙伴应该经常用到width:100%、width:auto、box-sizing:border-box这三对属性和属性值,但是他们之间的关系你知道吗?这里就有小伙伴产很大的疑问了,这三个放在一起根本风马牛不相及的好嘛!废话不多说,如果你也是有这样疑惑的小伙伴,请答应我,一定要看完这篇文章,不保证你受益匪浅,但肯定会有所得!如果没有,那就是你太棒了!在揭晓答案之前,先假定小伙伴的css知识储备是一般情况,所以首先我先要将width:100%、width:auto的情况说明,其次会将box-sizing:border-box和box-sizing:content-box的区别说清楚,最后说明width:100%、width:autobox-sizing:border-box的关系。如果你已经对第一第二部分了然于胸,请直接看第三部分。

在页面布局的时候,经常会用到弹性布局。在最外层的父元素上给定宽高后,子元素设置width: 100%,当需要给子元素一个边框border,这时却发现子元素已经超出父元素的范围,这width:100%应该是和父元素同样的宽度,为什么会有这样的情况发生?如果你也有同样的疑问,请看下面的分析(第四种情况)。

一、width:100%、width:auto的区别

第一种情况:父元素上给定宽高,子元素设置width: auto,子元素宽度 = 父元素宽度

//结构
  <div class="box1">
    <div class="box2"></div>
  </div>
//样式
  .box1{
    height: 40px;width: 40px;background-color: #aaa;
  }
  .box2{
    height: 20px;width: auto;background-color: yellowgreen;
    }

第二种情况:父元素上给定宽高,子元素设置width: 100%,子元素宽度 = 父元素宽度

//结构
  <div class="box1">
    <div class="box2"></div>
  </div>
//样式
    .box1{
      height: 40px;width: 40px;background-color: #aaa;
    }
    .box2{
      height: 20px;width: 100%;background-color: yellowgreen;
    } 

第三种情况:父元素上给定宽高,子元素设置width: auto,并设置border或padding,子元素宽度+border+padding = 父元素宽度

//结构
  <div class="box1">
    <div class="box2"></div>
  </div>
//样式
    .box1{
      height: 40px;width: 40px;background-color: #aaa;
    }
    .box2{
      height: 20px;width: auto;background-color: yellowgreen;
    }

第四种情况:父元素上给定宽高,子元素设置width: 100%,并设置border或padding,子元素宽度+border+padding > 父元素宽度

//结构
  <div class="box1">
    <div class="box2"></div>
  </div>
//样式
    .box1{
      height: 40px;width: 40px;background-color: #aaa;
    }
    .box2{
      height: 20px;width: 100%;background-color: yellowgreen;
    }

第五种情况:父元素上给定宽高,子元素设置width: auto,并设置border或padding,产生浮动,子元素宽度+border+padding < 父元素宽度

//结构
  <div class="box1">
    <div class="box2"></div>
  </div>
//样式
    .box1{
      height: 40px;width: 40px;background-color: #aaa;
    }
    .box2{
      background-color: yellowgreen;
      height: 20px;
      padding: 2px;border: 1px solid red;
      float: left;
      width: auto;
    }

第六种情况:父元素上给定宽高,子元素设置width: auto,并设置border或padding,变为内联元素,white-space: nowrap;,子元素宽度+border+padding > 父元素宽度

//结构
  <div class="box1">
    <div class="box2">这一行的文字足够多,不会换行</div>
  </div>
//样式
    .box1{
      height: 40px;width: 40px;background-color: #aaa;
    }
    .box2{
      background-color: yellowgreen;
      padding: 2px;border: 1px solid red;
      display: inline-block;
      white-space: nowrap;
      width: auto;
    }

第七种情况:父元素上给定宽高,子元素设置width: 100%,position: absolute,父元素开启定位。子元素宽度 = 父元素宽度。子元素添加border,padding后,子元素宽度+border+padding > 父元素宽度

//结构
  <div class="box1">
    <div class="box2"></div>
  </div>
//样式
    .box1{
      height: 40px;width: 40px;background-color: #aaa;
      position: relative;
    }
    .box2{
      background-color: yellowgreen;
      height: 20px;
      width: 100%;
      position: absolute;
    }

总结

1. width:auto

给子元素设置width:auto,当子元素添加内外边距以及边框,都不会使子元素宽度超过父元素。因为 auto表示子元素的宽度+内边距+边框 才等于父元素的宽度

当我没有为元素设置宽度的时候,这是宽度表示就是为width:auto.这个就是width属性的默认值。而width:auto;这个不同元素表示形式也就不同 

1.1、像div,p这种元素的宽度默认是最大水平撑满父级容器(第一种情况) 

1.2、而对于有浮动,绝对定位,tabl元素或inline-block元素则表示为适当的收缩(第五种情况) 

1.3、收缩到最小,最容易出现在table-layout为auto中,某一列宽度最窄(www.zhangxinxu.com/wordpress/2… 

1.4、父元素宽度不够显示时会超出容器限制, 除非有明确的width设置,否则以上3中情况都不会超过父级元素容器宽度的。 例如内容很长的文字,或者内联元素被设置了white-space: nowarp, 子元素既保持了inline-block的收缩特性,又同时让内容宽度最大,直接无视父级元素限制 (第六种情况) 可以看出在没有其它影响流的属性(如上面定位,浮动,字体限制)存在时候,大部分块级元素表示为霸道总裁,最大程度的撑开。而行内元素或者行内块级元素表示为小鸟依人,适当的收缩 

2. width:100%

给子元素设置width:100%,表示子元素的宽度和父元素的宽度相等,子元素的宽度不包括子元素内边距以及边框的值,如果子元素添加了内外边距以及边框,其宽度就会超过父元素的宽度

2.1、正常流的情况下我不需要设置width:100%;如果设置了反而会出现不好的情况, 当我不为子元素设置宽度时表示为自动撑大,而设置100%后就超出父元素了(第四种情况)

2.2、当我为子元素设置了定位属,性这个时候就需要width100%帮助了,当我设置了绝对定位或固定定位后,宽度就自然缩小了,width:100%后宽度相对于最近具有定位的祖先元素计算,而当设置绝对定位时,同时设置left和right时候,这时宽度又表示为最大水平适应父元素了(第七种情况)

二、box-sizing: content-box 和 box-sizing:border-box 的区别

在讲解box-sizing: content-box 和 box-sizing:border-box 的区别之前,首先要介绍盒模型的知识。

 CSS3盒模型就是CSS技术所使用的一种思维模型,指在一个网页文档中,每个元素都被呈现为一个矩形的盒子,描述了元素所占空间的内容。 不知道大家有没有想过,为什么盒模型是矩形,而不是三角形、椭圆形甚至五角星形呢?当盒子一个个拼凑起来,怎样才能让盒子紧凑无缝地填满一张白纸,或者说填满矩形的窗口,答案当然就是盒子是矩形才最容易达成。那么你就会明白为什么盒子是矩形,而不是其他形状。 盒模型,顾名思义,就是一个盒子。生活中的盒子,有长宽,盒子本身也有厚度,可以用来装东西。页面上的盒模型我们可以理解为最常见的快递,快递是由物品和包装组成,物品是包装里装的东西,相当于盒模型的内容(content);物品与包装之间的空隙,理解为盒模型的内边距(padding);包装可以理解为边框(border),包装本身的厚度,就是盒模型的边框宽度(border);在一堆快递中,快递之间的间隔,就是盒子的外边距(margin)。这样对于盒模型的理解就轻松易懂啦! 元素的外边距(margin)、边框(border)、内边距(padding)、内容(content)就构成了CSS盒模型。盒模型的五大属性是width、height、padding、border、margin。 

 CSS盒模型分为IE盒模型和W3C盒模型。其实,IE盒模型是怪异模式(Quirks Mode)下的盒模型,也叫怪异盒模型;而W3C盒模型是标准模式(Standards Mode)下的盒模型,也叫标准盒模型。 IE6及其更高的版本,还有现在所有标准的浏览器都遵循的是W3C盒模型,IE6以下版本的浏览器遵循的是IE盒模型。 IE盒模型的宽度或者高度计算方式为:width/height = content + padding + border,W3C盒模型的宽度或者高度计算方式为:width/height = content。 CSS3新增了一个属性box-sizing: content-box | border-box | inherit,默认值为content-box。如果值为content-box,那元素遵循的是W3C盒模型;如果值为border-box,那元素遵循的是IE盒模型;如果值为inherit,该属性的值应该从父元素继承。

三、box-sizing:border-box + width:100% = width:auto

上面等式成立的条件是父子元素都是块级元素,子元素不会有float浮动和position定位,既然width:auto已经很好使,为什么还要width:100%,因为width:auto的应用场景非常有限,所以为了适应多场景width百分比就可以搭配box-sizing:border-box大展身手! 要求:box2宽度占父元素20%,box3宽度占父元素80%,并排填满一行,并自适应box1的宽度。此时改变padding和border并不会超出父元素宽度,对于弹性布局非常实用。

//结构
  <div class="box1">
    <div class="box2"></div>
    <div class="box3"></div>
  </div>
//样式
    .box1{
      height: 40px;width: 40%;background-color: #aaa;margin: 0 auto;
    }
    .box2,.box3{
      background-color: yellowgreen;
      height: 20px;
      width: 20%;
      padding: 1px;
      box-sizing: border-box;
      float: left;
    }
    .box3{
      width: 80%;
      background-color: aqua;
    }

后续你不知道的CSS系列

  • 你不知道的盒模型
  • 你不知道的vertical-align和line-height
  • 你不知道的float与position
  • 你不知道的元素显示与隐藏

参考文档

《CSS世界》 张鑫旭

参与 DevUI

DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师。
官方网站:devui.design
Ng组件库:ng-devui
Vue组件库:vue-devui
Ng Admin:ng-devui-admin

未来DevUI社区也会将更多内部优秀工程实践开源与内容发布,欢迎朋友们加入我们的社区,一起打造有竞争力的开源产品,营造有温度的开源社区,期待你的加入!(微信公众号:DevUI)