CSS复习--- 深入理解CSS盒子模型

335 阅读10分钟

CSS复习--- 深入理解CSS

  • 在写 css 样式时通常效果和我们的预期是不一致的,深入了解盒子模型和常用的计算规则才能做到精准布局到每一个像素,而不是通过控制台1像素1像素去调整。
  • 遇到不确定的属性推荐多去阅读官方MDN文档,里面明确指出每一个属性的特定和运用,包括了适用元素、初始值、是否可以被继承,基本语法使用、兼容性等
  • 官网网址:margin - CSS(层叠样式表) | MDN (mozilla.org)

盒子模型

盒子概念

  • 在 CSS 中,所有的元素都被一个个的“盒子(box)”包围着,理解这些“盒子”的基本原理,是我们使用CSS实现准确布局、处理元素排列的关键。

盒子分类

image-20220528202212815

css盒子模型

  • 组成部分
    • 外边距 margin
    • 边框 border
    • 内边距 padding
    • 内容 content (width,height)
  • 高度为 行高撑起的高度
  • 宽度为 具体盒子模型对应不同计算公式
  • 宽度和高度默认为 auto

标准盒子模型 (IE盒模型)

  • 默认盒模型 box-sizing :content-box

  • 设置 width、height 其实是给content 设置宽高

  • 计算公式:

    • 盒子的宽高通常指的范围是从内容到边框的区域的宽高,margin 不计算在内 但影响盒子的排排布

    • width = 内容的宽度

      height = 内容的高度

    • 根据公式 设置 padding 和 border 会导致 盒子占用空间扩张

  • 在布局的时候就要计算一个盒子的真正占用的空间大小比较麻烦

  • 例如 设置 width 为 200 ,现在加了边框 盒子占用空间变成了 202 为了让盒子 宽度不变 必须要设置 width 为 198

代替IE标准盒模型

  • box-sizing: border-box

  • 计算公式

    • width = border + padding + 内容的宽度**
    • height = border + padding + 内容的高度*
  • 根据公式 宽度固定 , 设置padding 和 border占用的空间会从 content中 掠夺 ,就是压缩内容的宽度 来填补 padding 和 border占据的空间

  • 这样 要设置的宽高就是盒子占用的宽高了,就不用计算了。

margin

margin作用

  • margin的所有初始值为 0 不是 auto

  • 作用把其他元素从盒子旁边推开

  • 一般是处理兄弟元素之间的间距

margin 的折叠

  • margin 折叠设计初中是用来处理文章段落间距问题

  • 上下会折叠 左右不会折叠

  • 两个外边距相接的元素,这些外边距将合并为一个外边距,即最大的单个外边距的大小。

  • 简单将就是两个上下排布的块级盒子 设置上面盒子的margin-bottom 同时设置下面盒子的margin-top 实际产生的空间是 max(margin-bottom,margin-top)

  • 解决方案

    • 只设置一个盒子的margin

margin 负值

  • 包含块的计算公式

    • margin-left + border-left+padding-left+widht+border-right+margin-right = 包含块的宽度
  • margin负值会导致和其他内容重叠 俗称 盒子凹陷 凹陷的部分区域会其他盒子被视为不存在,

  • 同时 原理根据公式: margin 为负值 其实就是代表 包含块的宽度变大变相增加盒子宽度

  • 通常用于解决布局中的边框合并问题

    • 利用盒子凹陷 让边框重叠只显示一个像素解决重叠变粗问题,同时设置内容宽度(加1或者减1与盒子模型有关)将失去的宽度补回来 保证原来宽度不变

margin 设置 % 的问题

  • margin 设置百分比 的参照对象是 父盒子宽度 不是高度
    • margin-top:50%; 是移动父盒子宽度的50%

margin的传递性

  • 上下会传递 左右不会传递

  • 上下margin的传递 子盒子传递父盒子

    • margin-top传递
      • 子元素和父元素顶部线重叠 的情况下设置子盒子的margin-top 会传递到父盒子 ,形成 父子盒子一起移动的现象
    • margin-bottom 传递
      • 子元素与父元素底部线重叠父元素的高度为auto的情况下设置子盒子的margin-bottom 会传递到父盒子 ,形成 父子盒子一起移动的现象
  • 解决方案

    • 触发BFC 最优解解决方案
    • 不要设置margin 改为设置padding
    • 设置父元素边框,从而让子元素无法与父元素顶部线重叠
    • 设置父元素padding 从而让子元素无法与父元素顶部线重叠

利用margin 水平居中原理

  • margin 0 auto;
    • 居中原理分析
      • 剩余空间总是分给 auto 属性
      • margin-left、 margin-right 默认值为 0
      • margin-left、 margin-right 都为 0 剩余空间不分配给margin
      • 如果一个为auto ,一个为0,剩余空间就全部分给auto一边
      • 如果都是 auto就平分剩余空间
      • 盒子默认的占用空间是 margin + border + padding + width 其中 border 为 0, padding 为 0 ,margin 也是0, 剩余空间就不会在分配给margin了,只要设置margin-left、margin-right为都是auto,盒子剩余的空间就会平分给margin,所以盒子会水平居中。
  • 为什么 margin auto;不会上下左右居中?
    • margin-top 、 margin-buttom 设置为 auto的时候 他们的值会变成 0 而不是 auto 官方文档有明确说明 那就能理解为什么不会垂直居中了

BFC 补充

  • 概念描述:

    • 每一个BFC区域都是独立隔绝的,互不影响 形成一个结界与外界隔离不在受到外部影响

    • 每一个BFC区域只包括其子元素,不包括其子元素的子元素。

  • 触发BFC条件

    • 是body根元素
    • 设置浮动,不包括none
    • 设置定位,absoulte或者fixed
    • 行内块显示模式,inline-block
    • 设置overflow,即hidden,auto,scroll
    • 表格单元格,table-cell
    • 弹性布局,flex
  • BFC解决的问题

    • 内外边距塌陷问题 就是margin的折叠现象
    • 包含塌陷问题 就是 margin的传递性现象
    • 浮动产生影响 一般使用伪元素来解决
    • 标准流元素被浮动元素覆盖 利用这个特性可以实现宽度自适应

padding

  • 一般是处理父子元素之间的间距

  • 值为 0 或者是正值 没有负值和重叠现象

  • 作用是将内容 推离边框

  • 无论是内容或是背景颜色等 开始填充的位置都是在 padding之后 也就是内容区域

#line-height 原理

image-20220528103724684

  • 根据图可知 行距是等分的 这也就说明 文字距离上面和下面的距离是相同的那就是文字垂直居中了 当行高等于盒子的高度时 文字自然就居中了 这就是行高的居中原理

    • 其知识补充
      • 一个常见的问题 图片底部多出的几个像素 由于基线对齐产生的问题
      • 可以被继承
      • 盒子默认对齐方式是基线对齐 基线就是 X 的底部位置位置
      • line-height:1.5 为元素的字体大小 * 1.5(推荐使用 无单位数值)

常用的元素水平居中

  • 文本居中、行内元素

    • text-align:center;
  • 行内替换元素 img、input ....

    • text-align:center
  • 行内块元素 span inline-block

    • text-align:center
  • 块级元素

    • margin:0 auto;

    • 利用定位 + 元素位移

      .box {
          position: absolute // or  relative ;
          left: 50%; // 父元素宽度的50%
          transform: translate(-50%); // 自己宽度的50%
      }
      
    • 利用 flex 弹性盒模型

      .parent{
        diplay:flxe;
        justify-content:center;
      }
      
      

浏览器 对 auto处理

  • 只存在一个auto
    • 剩余空间 会分配 auto
  • 存在 多个 auto
    • 剩余空间均分给auto
  • margin-top 、margin-bottom 设置为 auto 时默认会变成 0

设置% 的问题

  • 不同属性设置 % 参照的对象是不同的,具体参照谁要查官方文档,尽量不要使用 %,除非自己非常明确百分比参照对象是谁。

垂直居中

  • 内容居中 line-height
  • 定位
  • flex 盒模型

常用布局处理方案

背景图随浏览器缩放始终居中显示问题

  • 公式 移动距离 = 图片自身宽度一半 + 父容器盒子宽度的一半 就是
    • 使用定位属性 position:relative
    • 父容器宽度 : left:50%
    • 自身宽度 transform: translate(-50%);

实现图片完美居中问题

  • vertical-align: middle; 无法实现图片居中 会偏下一些 使元素的中部与父元素的基线加上父元素x-height

image.png

  • middle指的是基线往上1/2 "x-height"高度

  • vertical-align: middle并不是绝对的垂直居中对齐,我们平常看到的middle效果只是一种近似的效果。原因很简单,因为不同的字体,其在行内盒子中的位置是不一样的,比方说’微软雅黑’就是一个字符下沉比较明显的字体,所有字符的位置相比其他字体要偏下一点。要是vertical-align: middle是相对容器中分线对齐,你会发现图标和文字不在一条线上,而相对于字符x的中心位置对齐,我们肉眼看上去就好像和文字居中对齐了。

  • 使用绝对定位实现

    img{
      position:relative;// or absolute
      top:50%;
      transform:translate(0,-50%);
    }
    

彻底解决边框重叠问题

  • 边框合并重叠的边框是一个非常麻烦的事情,最简单的无脑做法就是 一个一个去合并

    • 利用 margin 负值合并重叠边框 标准做法

      • 使用的是 标准盒子模型如果要使用border-box 每个li的内容就要+1 原因参考不同盒模型的宽度计算公式

      • ul 为 宽度1000px

      • 每个li的宽度是 249 px + 2个边框 为 251 px

      • 每个 li 为 显示宽度为 251px 实际上一个右边框是塌陷的 所以是 宽度是250px

      • 最终效果图

image-20220601224154913.png

解决元素等间距布局,最后一个元素如何处理问题

  • 常见的布局中通常需要处理一下中间保留间距,两端对齐贴边对齐的问题,最后一个通常不好处理

    • 利用 flex 布局 虽然可以解决,但我们是无法控制中间间隔的大小,flex是弹性盒模型不好控制
    • 使用类找到最后一个不设置间距 ,单行比较好处理,多行就要使用伪类去找到每行的最后一个去除间距
    • 同样可以利用margin 负值处理
      • 整个ul盒子宽度为990 ,每个li宽度为240 加上每一个都有一个右边距为10 所以会占据1000 ,有一个必定是会被挤下来
      • 可以利用margin负值原理,通过给ul加上margin-right:-10px来宽度ul的宽度,ul就变成了 1000 同时由于负值增加的区域是不显示的所以可以达到理想的效果
  • 效果图

image-20220602133021836.png

css 书写规范

  • 其目的是减少浏览器reflow(回流),从而提升浏览器渲染dom的性能

  • CSS 书写顺序:

    1. 位置元素定位;
    2. 自身属性;
    3. 文字样式;
    4. 文本属性;
    5. c3中新增属性.
  • 1.布局定位属性:display、position、float、visibility、overflow、left、top、right、bottom、clear、z-index...... (建议display第一个写)

  • 2.自身属性:width、height、margin、padding、border、background......

  • 3.文本属性:color、font、text-decoration、text-align、vertical-align、white-space、break-word

  • 4.其他属性(CSS3):content、cursor、border-radius、box-shadow、text-shadow......

    .box{
        display:block;
        position:relative;
        float:left;
        z-index
        width:100px;
        height:100px;
        margin:0 10px;
        padding:20px 0;
        font-family:Arial;
        color:#333;
        background:rgba(0,0,0,.5);
        border-radius:10px;
        transform: translate(50%);
    }