CSS第五篇:CSS属性-盒子模型

盒子模型

简介

  1. 盒子模型(Box Model)
    1. HTML中的每一个元素都可以看做是一个盒子,如下图所示,可以具备这4个属性

      pic

      1. 内容(content)
        1. 盒子里面装的东西
      2. 内边距(padding)
        1. 怕盒子里装的东西损坏而添加的泡沫或者其他抗震的辅料
      3. 边框(border)
        1. 就是盒子的边框,比如木盒子四周的木板
      4. 外边距(margin)
        1. 为了方便取出,盒子之间保留一定的空隙
    2. 默认的盒子模型如下图所示

      pic

      1. 实际占用宽度 = 边框宽度(border-left+right)+内边距(padding-left+right)+内容宽度(weight)
      2. 实际占用高度 = 边框(border-top+bottom)+内边距(padding-top+bottom)+内容高度(weight)

盒子模型常用属性

  1. 内边距相关的属性(padding)

     padding-left:左内边距
     padding-right:右内边距
     padding-top:上内边距
     padding-bottom:下内边距
     padding:上面四个属性的简写属性,上、右、下、左,顺时针方向
    
    1. 举例

       /* 上、右、下、左 */
       padding: 10px 20px 30px 40px;
       /* 上、右、下,左边等于右边 */
       padding: 10px 20px 30px;
       /* 上下、左右 */
       padding: 10px 20px;
      
    2. padding的取值规律

      1. 按照顺时针方向设置:top、right、bottom、left
      2. 如果缺少left,那么left就使用right的值
      3. 如果缺少bottom,那么bottom就是用top的值
  2. 外边距相关的属性(margin)

     margin-left:左外边距
     margin-right:右外边距
     margin-top:上外边距
     margin-bottom:下外边距
     margin:上面四个属性的简写属性,上、右、下、左,顺时针方向
    
    1. 设置特点跟padding一样

margin注意点

上下margin传递

  1. margin-top传递
    1. 如果块级元素的顶部线块级父元素的顶部线重叠,那么这个块级元素的margin-top值会传递给父元素
    2. 代码举例:

       <style>
           .div1 {
               width: 200px;
               height: 200px;
               background-color: #f00;
               /* 父元素也必须是块级,否则也不会传递 */
               /* display: inline-block; */
           }
           .div2 {
               width: 100px;
               height: 100px;
               background-color: #0f0;
               /* 子元素设置margin-top,父元素也会被传递 */
               margin-top: 40px;
               /* 如果改成非块级,就不会传递了 */
               /* display: inline-block; */
           }
       </style>
       <body>
           <div class="div1">
               <!-- 如果子元素跟父元素顶部不重叠,那么也不会传递 -->
               <!-- 123 -->
               <div class="div2"></div>
           </div>
                  
       </body>
      

      pic

    3. 案例:

       <style>
           div {
               background-color: #f00;
               width: 200px;
               height: 100px;
           }
                  
           p {
               width: 50px;
               height: 50px;
               background-color: #ff0; 
           }
       </style>
              
       <body>
       <div>
           <p></p>
       </div>
       </body>
      
      1. 效果图如下: pic

      2. 为何div标签顶部会出现间距?

        1. 因为p标签浏览器默认设置的有margin-top,然后对父元素div进行了margin-top传递
  2. margin-bottom传递
    1. 如果块级元素的底部线块级父元素的底部线重叠,并且父元素的高度是auto,那么这个块级元素的margin-bottom值会传递给父元素
    2. 代码举例:

       <style>
           .div1 {
               width: 200px;
               /* 不写height就相当于是auto */
               /* height: 200px; */
               background-color: #f00;
               /* 不是块级不会传递 */
               /* display: inline-block; */
           }
           .div2 {
               width: 100px;
               height: 100px;
               background-color: #0f0;
               margin-bottom: 40px;
               /* 不是块级不会传递 */
               /* display: inline-block; */
           }
       </style>
       <body>
       <div class="div1">
           <div class="div2"></div>
           <!-- 底部不重叠,不会传递 -->
           <!-- 777 -->
       </div>
       666
       </body>
      

      pic

  3. 如何防止出现传递问题?
    1. 将父元素或者子元素设置为行内块级:display: inline-block;
    2. 给父元素设置padding-top/padding-bottom,让顶部、底部不重叠.(这里的重叠指的是content重叠
    3. 给父元素设置border
    4. 以后理解的更深入,还会学到其他解决办法

       .div1 {
           width: 200px;
           height: 200px;
           background-color: #f00;
           /* 给父元素设置padding */
           /* padding-top: 1px; */
           /* 给父元素设置border */
           border: 1px solid;
       }
      
  4. 建议
    1. margin一般是用来设置兄弟元素之间的间距
    2. padding一般是用来设置父元素之间的间距
    3. 比如上面的子元素与父元素之间的间距,就应该设置父元素的padding,而不是设置子元素的margin

       .div1 {
           width: 200px;
           height: 200px;
           background-color: #f00;
           /* 父子元素,父元素用padding设置 */
           padding-top: 40px;
       }
       .div2 {
           width: 100px;
           height: 100px;
           background-color: #0f0;
           /* 子元素设置margin-top,父元素也会被传递 */
           /* margin-top: 40px; */
       }
      

上下margin折叠

  1. 垂直方向相邻的2个margin(margin-top、margin-bottom),有可能会合并为1个margin,这种现象叫做collapse(折叠)
  2. 水平方向上的margin(margin-right、margin-left)永远不会collapse
  3. 折叠后最终的计算规则
    1. 如果都谁数,最终值是:绝对值最大的那个数值
    2. 如果都是数,最终值是:绝对值最大的那个数值
    3. 如果数、数都有,最终值是:最大正数和最小负数相加
  4. 如何防止margin collapse?
    1. 只设置其中一个元素的margin
    2. 条件允许的话,使用padding取代margin
    3. 以后理解的更深入,还会学到其他解决办法
  5. 折叠类型
    1. 两个兄弟块级元素之间上下margin的折叠

       <style>
           div {
               width: 100px;
               height: 100px;
               background-color: #f00;
           }
           /* div1/div2同时设置,理论上应该是相加80,但是实际上合并在一起了,为40 */
           .div1 {
               margin-bottom: 40px;
           }
           .div2 {
               /* margin-top: 40px; */
               /* 正数,二者取最大值 */
               margin-top: 60px;
           }
       </style>
       <body>
       <div class="div1"></div>
       <div class="div2"></div>
       </body>
      
    2. 父子块级元素之间margin的折叠
      1. 子元素将自己的margin-top传递给父元素,子元素就没有margin-top了
      2. 最终的结果为父元素的margin-top取这2个的计算值
       <style>
           .div1 {
               width: 200px;
               height: 200px;
               background-color: #f00;
               margin-top: 40px;
           }
           .div2 {
               width: 100px;
               height: 100px;
               background-color: #0f0;
               margin-top: 60px;
           }
       </style>
       <body>
       <!-- div2的margin-top传递给div1,最后取最大值60px -->
       <div class="div1">
           <div class="div2"></div>
       </div>
       </body>
      
    3. 无内容块级元素内部margin的折叠(折叠是可以连续的)

       <style>
           .div1 {
               /* width: 200px;
               height: 200px; */
               background-color: #f00;
               margin-top: 60px;
               margin-bottom: 40px;
           }
       </style>
       <body>
       666
       <!--有内容-->
       <!-- <div class="div1">div</div> -->
       <!--无只要删除内容,2个margin-top、bottom就会折叠在一起,最终是60 -->
       <div class="div1"></div>
       777
       </body>
      

      pic

  6. 总结:只要块级元素的上下(无论是父子还是兄弟)2个margin直接接触,就会出现折叠现象

border(边框)

  1. 边框相关的属性
    1. 边框宽度
       border-top-width
       border-right-width
       border-bottom-width
       border-left-width
      
      1. border-width是上面4个属性的简写属性
    2. 边框的颜色

       border-top-color
       border-right-color
       border-bottom-color
       border-left-color
      
      1. border-color是上面4个属性的简写属性
    3. 边框样式:

       border-top-style
       border-right-style
       border-bottom-style
       border-left-style
      
      1. border-style是上面4个属性的简写属性
  2. 边框样式的取值

    pic

     div {
        width: 100px;
        height: 100px;
        background-color: #f00; 
    
         /* 设置边框这3个都不能少 */
         /* 边框宽度 */
        /* border-left-width: 5px; */
        /* 边框颜色 */
        /* border-left-color: #0f0; */
        /* 边框样式 */
        /* border-left-style: solid; */
    
         /* 设置边框这3个都不能少 */
        /* border-right-width: 5px; */
        /* border-right-color: #00f; */
        /* 边框样式 :虚线*/
        /* border-right-style: dashed; */
    
        /* 简写 */
        /* 方式1: */
        /* border-width: 5px 4px 3px 2px;
        border-color: purple green blue yellow;
        border-style: solid dashed dotted solid; */
    
        /* 方式2: */
        /* border-left: 5px solid yellow;
        border-right: 5px solid blue;
        border-bottom: 5px solid green;
        border-top: 5px solid purple; */
    
        /* 同时设置4个方向的边框 */
        border: 5px solid blue;
        /* 设置一个边框的颜色 */
         border-right-color: green;
         border-bottom:none;
     }
    
  3. 边框的形状
    1. 边框的形状可能是
      1. 矩形、梯形、三角形等形状
    2. 本质:通过将内容的width、height为0,然后设置边框,显示不同的形状
     /*梯形  */
     div {
        width: 100px;
        height: 100px;
        background-color: #f00; 
        /* 设置一个边框就是矩形,大于一个时就是梯形了 */
        border-left: 5px solid yellow;
        border-right: 5px solid blue;
        border-bottom: 5px solid green;
        border-top: 5px solid purple;
     }
    
     /* 三角形:注意设置的2个边框必须相邻 */
     div {
         width: 0;
        height: 0;
        /* 2个三角形 */
        /* border-top: 50px solid yellow; */
        /* 一个三角形 */
        border-top: 50px solid transparent;
        border-left: 50px solid blue;
        transform: rotate(135deg);
     }
     /* 实现双色平分 */
     div {
         background-color: #ddd;
         width: 100px;
         height: 50px;
         border-bottom: 50px solid #111;
     }
    

行内级非替换元素注意点

  1. 以下属性对行内级非替换元素不起作用

     width/height/margin-top/margin-bottom
    
    1. 举例

        /* 行内非替换 */
       span {
           background-color: #f00;
           /* 这4个属性都不行 */
           width: 100px;
           height: 100px;
           margin-top: 100;
           margin-bottom: 100;
           /* 可以 */
           margin-left: 40px;
           margin-right: 40px;
       }
       /* 行内替换 */
       img {
           /* 都支持 */
           width: 40px;
           height: 40px;
           margin-left: 40px;
           margin-bottom: 40px;
      
       }
              
       <body>
       <span>55555</span> 
       <a>999</a>
       <br>
       66666
       <img src="./images/test.png" alt="">
       </body>
      
  2. 以下属性对行内级非替换元素的效果比较特殊

    1. padding-top、padding-bottom、border-top、border-bottom
      1. 设置之后,占据空间不会向外部扩张,left、right没问题
    2. 代码举例

      1. padding

         /* 行内非替换 */
         span {
             background-color: #f00;
             padding-bottom: 10px;
             padding-top: 20px;
             padding-left: 10px;
             padding-right: 20px;
         }
            
         div {
             background-color: #0f0;
             width: 100px;
             padding-top: 40px;
             padding-bottom: 40px;
         }
         <body>
         <span>55555</span> 8888
         <br>
         66666
         <div>111</div>
         777
         </body>
        
      2. border

         /* 行内非替换 */
         span {
             background-color: #f00;
             border: 10px solid yellow;
         }
            
         div {
             background-color: #0f0;
             width: 100px;
             border: 5px solid yellow;
            
         }
         <body>
         <span>55555</span> 8888
         <br>
         66666
         <div>111</div>
         777
         </body>
        

      pic

border-radius

  1. 圆角半径相关的属性有

     border-top-left-radius
     border-top-right-radius
     border-bottom-left-radius
     border-bottom-right-radius
    
  2. border-*-*-radius定义的是四分之一椭圆的半径

     border-top-left-radius: 40px 20px;
    
    1. 第一个值是水平半径
    2. 第二个值是垂直半径(如果不设置,就跟随水平半径的值)
  3. 还可以设置百分比

     border-top-left-radius: 50%;
    
    1. 参考的是border-box的宽度
    2. 一个盒子可以看成boder-box、content-box、padding-box
    3. 只要border-radius大于等于50%,就会变成一个圆
  4. border-radius是一个缩写属性

     border-radius: 10px 20px 30px 40px/15px 25px 35px 45px;
    
    1. 斜线前面是水平半径,后面是垂直半径
    2. 4个值的顺序是top-left、top-right、bottom-right、bottom-left(顺时针方向)
      1. 如果bottom-left没设置就跟随top-right
      2. 如果bottom-right没设置就跟随top-left
      3. 如果top-right没设置就跟随top-left

outline

  1. outline表示元素的外轮廓
    1. 不占用空间
    2. 默认显示在border的外面
    3. 每个部位都是完整连接的,不会像border那样有可能会断开(比如行内级非替换元素的换行)
  2. outline相关属性有
    1. outline-width
    2. outline-style:取值跟border的样式一样,比如solid、dotted等
    3. outline-color
    4. outline:outline-width、outline-sytle、outline-color的简写属性,跟border用法类似
  3. 应用实例
    1. 去除a元素,input元素的focus轮廓效果
  4. 举例使用:
    1. 例1:

       div {
          width: 100px;
          height: 100px;
          background-color: #f00;
          border: 5px solid yellow;
          outline: 10px solid blue;
       }
              
       <body>
       <div></div>
       666
       </body>
      
    2. 例2:

       div {
          width: 100px;
          height: 150px;
          background-color: #f00;
       }
       span {
          background-color: #0f0;
          /* border: 2px solid #ff0; */
          outline: 2px solid #ff0; 
       }
              
       <body>
       <div>
           我是div我是div我是div我是div
           <span>我是span我是span我是span</span>
       </div>
       </body>
      

      pic

box-shadow

  1. box-shadow属性可以设置一个或者多个阴影
    1. 每个阴影用<shadow>表示
    2. 多个阴影之间用逗号,隔开,从前到后叠加
    3. <shadow>常见的格式如下
  2. <shadow>=inset? && <length>(2,4) && <color>?
    1. 第一个参数为inset,如果设置就代表内部阴影,一般不使用。
    2. 第二个可以设置4个length
      1. 第1个<length>:水平方向上的偏移,正数向右偏移
      2. 第2个<length>:垂直方向上的偏移,正数向下偏移
      3. 第3个<length>:模糊半径(blur radius),往四周扩散
      4. 第4个<length>: 延伸距离
    3. 第三个为color,阴影的颜色
  3. 代码举例:

     body {
         background-color: #ddd;
         padding-left: 100px;
         padding-top: 100px;
     }
     div {
        width: 100px;
        height: 150px;
        background-color: #fff;
        /* 阴影向右边偏移10px 向下偏移20px 阴影颜色为红色 */
        /* box-shadow: 10px 20px #f00; */
        /* box-shadow: 0 0 30px 5px #f00; */
        /* 半透明阴影 */
        box-shadow: rgba(100, 100, 100, 0.3);
     }
    

text-shadow

  1. text-shadow用法类似于box-shadow,用于给文字添加阴影效果
  2. text-shadow同样适用于::first-line/::first-letter

     div{
         text-shadow: 0 0 15px #f00;
     }
    

box-sizing

  1. box-sizing用来设置盒子模型中宽高的行为
    1. content-box
      1. padding、border都布置在width、height外面
    2. border-box
      1. padding、border都布置在width、height里面
  2. 图文解释
    1. content-box

      pic

    2. border-box

      pic

  3. 盒子模型 pic

    W3C发现IE8之前的方式有自己的优点,又来就出现了box-sizing属性,专门用于用户选择

  4. 代码举例

     div{
         width: 50px;
         height: 50px;
         background-color: #f00;
         padding: 20px;
         border: 5px solid #ff0;
    
         /* 
         box-sizing用来控制width、heiht的行为
         1. content-box:只包含width、height不包括padding和border
         2. border-box:包括width、height、padding和border
          */
          /* padding/border向内扩展向外扩展 */
         box-sizing: content-box;
         /* padding/border向内扩展 */
         box-sizing: border-box;
     }
    

width/height的百分比值

  1. 给width/height设置百分比值,那么这个百分比参考的是谁呢? 父元素的的widht/height吗?
  2. 查看W3C官方文档:
    1. width的百分比:refer to wdith of containing block,containing block可以认为是父元素
    2. height: 也可以认为参考的是父元素的height

元素的水平居中显示

  1. 在一些需求中,需要元素(不是文字)在父元素中水平居中显示(父元素一般都是块级元素、inline-block)
  2. 子元素是:行内级元素、inline-block元素
    1. 水平居中:在父元素中设置text-align:center
    2. 可以这么理解为什么text-align针对bolck元素无效
      1. text-align是为了让父元素内部的内容居中显示,居中的条件是父元素与子元素之间有空隙
      2. 行内、inline-block都符合
      3. 但是block尽管也可以设置width,表面看起来与父元素之间有了空隙,但是由于block的特性是占据父元素的整行,即时宽度设置有剩余也不允许其他元素占据,因此实际上还是占据了父元素整行,所以无法居中
  3. 子元素是:块级元素
    1. 水平居中: 给自己(子元素)设置:margin-left: auto; margin-right: auto;
    2. 理解:由于block占据父元素整行,那么从父元素无法设置,只能从当前子元素来设置
  4. 代码举例:

     <style>
         div {
             background-color: #f00;
             width: 200px;
             height: 100px;
             /* 让元素的内容在元素里面水平居中 */
             /* 文字、行内、行内块级 水平居中 */
             /* text-align: center; */
         }
         srong {
             display: inline-block;
             width: 50px;
             height: 50px;
             background-color: #ff0;
         }
         p {
             width: 50px;
             height: 50px;
             background-color: #ff0; 
             /* 块级标签在父元素中居中 */
             /* margin-left: auto;
             margin-right: auto; */
             /*上下为0,左右为auto*/
             margin: 0 auto;
         }
     </style>
     <body>
     <!-- 文字内容 -->
     <!-- <div>22222</div> -->
     <!-- 行内元素 -->
     <!-- <div>
         <span>我是span</span>
     </div> -->
     <!-- inline-block元素 -->
     <!-- <div>
         <srong></srong>
     </div> -->
     <!-- 块级 -->
     <div>
         <p></p>
     </div>
     </body>
    
Table of Contents