mengtuifrontend / Blog

芦叶满汀洲,寒沙带浅流。二十年重过南楼。柳下系船犹未稳,能几日,又中秋。 黄鹤断矶头,故人今在否?旧江山浑是新愁。欲买桂花同载酒,终不似,少年游。
18 stars 5 forks source link

CSS 世界 —— 盒尺寸四大家族 #26

Open shenxuxiang opened 4 years ago

shenxuxiang commented 4 years ago

盒尺寸四大家族

替换元素

通过修改某个属性值呈现的内容就可以被替换的元素就被称为 “替换元素”。<img>、<object>、<vedio>、<iframe>、<textarea>、<input> 等都是典型的替换元素

替换元素除了内容可替换以外,还有哪些特性:
替换元素的尺寸计算规则

可以将替换元素的尺寸从内到外分为:“固有尺寸”、“HTML尺寸”、“CSS尺寸”

计算规则

如果 ”固有尺寸“ 含有固有的宽度比例,同时仅设置了宽度或者仅设置了高度,则元素依然按照固有比例宽高显示

padding

  <div style="height: 32px; line-height: 32px; background: #444">
    xxxx<span style="background: #999; padding: 20px 0; border: 5px solid #fff">我是谁</span>xxxx
  </div>
  <div style="height: 32px; line-height: 32px; background: #555">
    xxxx的是非得失丰富的水分是我的  
  </div>

先看看上面这个 demo,可以看出来,对于内联元素来说,paddingborder 对内联元素的文字对齐没有影响。(其实内联元素的 padding/border 不计算在行框盒子的高度内)

注意:padding 不能出现负值

padding 的百分比值
HTML标签内置的 padding
同背景属性结合绘制特殊的图形
  <div style="height: 300px; background: #ccc; margin: 20px">
    <div class="circle"></div>
    <div class="three-line"></div>
    <div class="triangle"></div>
  </div>
  .circle {
    width: 20px;
    height: 20px;
    padding: 5px;
    background: #fff;
    background-clip: content-box;
    border: 2px solid #fff;
    border-radius: 50%;
  }

  .three-line {
    width: 20px;
    height: 25px;
    border: 3px solid #fff;
    border-left-width: 0;
    border-right-width: 0;
    padding: 8px 0;
    background: #fff;
    background-clip: content-box;
    box-sizing: border-box;
  }

  .triangle {
    display: inline-block;
    background: transparent;
    border: 10px solid transparent;
    border-top-color: #333;
  }

margin 与元素尺寸以及相关布局

先介绍几个概念术语

margin 与元素的内部尺寸

当元素设置了 width 属性或者当元素具有 “包裹性” 的时候,margin 对尺寸是没有影响的。只有当元素是 “充分利用可用空间” 的时候,margin 才可以改变元素的可视尺寸。

  <div style="margin-left: 100px;">
    <div style="background: #ccc">123</div>
  </div>

同样,垂直方向也是可以的

  <div style="position: relative; width: 100px; height: 100px; background: #333">
    <div style="background: #ccc; position: absolute; top: 0; bottom: 0; margin-top: 30px;">123</div>
  </div>

上面的 demo 可以看出来,当前元素表现为 “格式化宽高” 的时候,元素自动充满父容器的宽度和高度,这个时候 margin\border\padding\content 自动分配水平和垂直方向空间。当元素表现为正常流特性的时候,和 “格式化宽度” 是一样的。

看看下面的几个 demo

  <div style="background: #ccc; overflow: hidden">
    <img src="./static/images/timg.jpg" alt="" class="right">
    <div class="left">1234567890</div>
  </div>
  .left {
    margin-right: 100px;
  }
  .right {
    float: right;
    width: 100px;
  }
  <div style="background: #ccc; overflow: hidden">
    <img src="./static/images/timg.jpg" alt="" class="left">
    <div class="right">1234567890</div>
  </div>
  .right {
    margin-left: 100px;
  }
  .left {
    float: left;
    width: 100px;
  }
  <div style="background: #ccc; overflow: hidden">
    <div class="middle">
      <div class="con">1234567890</div>
    </div>
    <img src="./static/images/timg.jpg" alt="" class="left">
    <img src="./static/images/timg.jpg" alt="" class="right">
  </div>
  .right {
    float: left;
    width: 100px;
    margin-left: -100px;
  }
  .left {
    float: left;
    width: 100px;
    margin-left: -100%;
  }
  .middle {
    /*margin: 0 100px;*/
    float: left;
    width: 100%;
  }
  .con {
    margin: 0 100px;
  }
  <div style="background: #ccc; overflow: hidden">
    <img src="./static/images/timg.jpg" alt="" class="left">
    <img src="./static/images/timg.jpg" alt="" class="right">
    <div class="middle">
      <div class="con">1234567890</div>
    </div>
  </div>
  .right {
    float: right;
    width: 100px;
  }
  .left {
    float: left;
    width: 100px;
  }
  .middle {
    width: 100%;
  }
  .con {
    margin: 0 100px;
  }

注意: 这个时候当 margin 为负值的时候,容器的 width 会增加

  <div style="margin-right: -30px; background: #333; text-align: right">1234567890</div>
margin 与元素的外部尺寸

在 CSS 世界中很多棘手的问题都是需要借助 margin 的外部尺寸特性来实现的。比方说, FireFox 浏览器下,设置了 overflow: auto/scroll 的容器会忽略 padding-bottom 值。

  <div style="padding: 50px; background: #ccc; height: 200px; overflow: scroll;">
    <img src="./static/images/timg.jpg" alt="" height="300px">
  </div>

注意:如果 padding-bottom 属性的数值设置的过小,则看不出是否被忽略的效果,所以这里我设置的是 50px

那么对于上面的问题,我们可以在最后一个子元素中设置 margin-bootom 来替换就可以了。


margin 和 padding 之间的相互作用

margin 为负值的时候,“元素尺寸” 就会变大。这个时候,如果 padding/border 是固定的数值,那么 content (这里的 width 的值为 auto)就会随着 margin 负值的增加而变大,但对于 height 来说,没有任何影响(不会影响 height 值)。

注意:不是定位方向的 margin 是不会对元素的定位产生影响的,只能对该元素后面相邻的元素定位产生影响。

我们这里有一个需求是:一个盒子内部需要让左右两栏的背景高度一致,取最高那部分的高度。(使用 margin 和 padding 互补)

  <div style="max-height: 200px; overflow: hidden;">
    <div style="float: left; width: 50%;background: #ccc; padding-bottom: 500px; margin-bottom: -500px;">
      <p>1213r</p>
      <p>1213r</p>
      <p>1213r</p>
      <p>1213r</p>
      <p>1213r</p>
      <p>1213r</p>
      <p>1213r</p>
      <p>1213r</p>
    </div>
    <div style="float: left; width: 50%; background: #444; padding-bottom: 500px; margin-bottom: -500px;">
      456
    </div>
  </div>

paddingmargin 互补部分的尺寸是不会计算到布局定位中的

margin 的百分比值 和 padding 一样都是相对于父容器的 width 进行计算的

margin 的合并

块级元素的上、下外边距有时候是会发生合并的,发生 “margin合并” 必须满足两点重要信息

哪些场景会发生合并:
  <div style="background: #444">
    <div style="width: 50%; height: 50px; background: #ccc; margin: 100px">
    </div>
  </div>
如何消除 margin-top 合并
如何消除 margin-bottom 合并
如果一个元素是一个空元素(没有任何内容),那么如果同时设置了 margin-topmargin-bottom。那么这个时候 margin-topmargin-bottom 是会发生合并的。所以实际定位时只计算一个 margin-top/margin-bottom 的值(谁的值大取谁)。如何消除这种情况的 margin 合并
margin 合并的计算规则:
margin: auto 作用机制

下面的这个案例就可以完美的解释 margin: auto

  <div style="width: 300px; background: #ccc">
    <div style="width: 200px; margin-left: auto; margin-right: 80px; background: #455">123</div>
  </div>
什么情况下设置的 margin 无效

border

border-width
border-style 默认值就是 none。所以当我们设置 border-widthborder-color 没有显示边框的原因。但是当我们只设置 border-style: solid 就会出现边框。
border-color 有一个很重要的特性就是 border-color 的默认值就是 color 色值。当没有设置 border-color 颜色值的时候,会使用当前元素的 `color 计算值作为边框色。