盒模型与元素尺寸

从一个矩形div开始

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    #container {
      width: 200px;
      height: 200px;
      background-color: gray;
      padding: 20px;
      margin: 20px;
      border: 10px dashed #333;
    }
  </style>
</head>

<body>
  <div id="container">hohoho</div>
</body>

</html>
复制代码

页面上显示的结果如下: image.png

该div的标准盒模型如下图:

image.png

盒子由四个属性组成,从内到外分别是:content 内容padding 内填充border 边框外边距 margin

最终元素的总宽度计算公式是:

总元素的宽度=宽度+左填充+右填充+左边框+右边框+左边距+右边距

元素的总高度最终计算公式是:

总元素的高度=高度+顶部填充+底部填充+上边框+下边框+上边距+下边距

clientWidth,clientHeight

这些属性提供了元素边框内区域的大小。包括了 “content width” 和 “padding”,但不包括滚动条宽度。所以上述例子中的clientWidth,clientHeight都是240(200+20+20)。当我们加上一个300 * 300的内部元素之后:

<style>
  * {
    margin: 0;
    padding: 0;
  }

  #container {
    width: 200px;
    height: 200px;
    background-color: gray;
    padding: 20px;
    margin: 20px;
    border: 10px dashed #333;
    overflow: auto;
  }

  #text {
    width: 300px;
    height: 300px;
    background: #f5f5f5;
  }
</style>

<body>
  <div id="container">
    <div id="text">hohoho</div>
  </div>
</body>
复制代码

image.png

此时的 clientWidth = clientHeight = 200 + 20 + 20 - 17 = 223,chrome浏览器滚动条默认宽度为17

image.png

在进行页面布局的时候尽量使用 document.documentElement 元素的 clientWidth/clientHeight 属性来替换window.innerWidth/innerHeight,大多数情况下我们的排版、绘制是在除滚动条以外的可见区域;

在某些场景下会在 overflow 显示和隐藏间切换,页面会因为有滚动条和没滚动条带来的宽度不同而跳动,这时可以使用 clientWidth/clientHeight 加上一个padding(滚动条的宽度)重新生成没有滚动条的 width/height 来解决跳动问题;

scrollWidth,scrollHeight

该属性也是提供了元素边框内区域的大小,但它们还包括滚动出(隐藏)的部分,也包括滚动条宽度在内。上述例子中的 scrollWidth = scrollHeight = 300 + 20 + 20 = 340

image.png

可以发现 scrollWidth 只有320,在页面上可以找到原因(右内边距失效了),而window.getComputedStyle(div).padding = window.getComputedStyle(div).paddingRight = '20px',具体失效的原因请参考css规范中的 #### 10.3.3. Block-level, non-replaced elements in normal flow

image.png

里面提到当"over-constrained"时如果 'dir' 是 'ltr' 时就会忽略右填充或右边距而重新计算一个值(但是不清楚为何重新计算了而 window.getComputedStyle(div).paddingRight 获取到的值仍然是 '20px' ),如果我们改为 'rtl' 时左边也会出现这种情况:

image.png image.png

可以通过设置内部元素的 display,或者加伪元素的方式来使其显示正常,不展开讨论

offsetWidth,offsetHeight

这两个属性相对较简单。它是元素的完整大小(包括边框),元素的大小除了描述盒模型时一般不会包括外边距,例子中的 offsetWidth = offsetHeight = 200 + 20 + 20 + 10 + 10 = 260

image.png

clientLeft,clientTop,offsetLeft,offsetTop,scrollLeft,scrollTop

clientLeft,clientTop:是元素内到边框外的距离(不等于边框),例如 'dir' 特性为 'rtl' 的值还包括滚动条的宽度,如:

image.png image.png offsetLeft,offsetTop:是相对于 offsetParent(是最接近的祖先:position 为 absoluterelative 或 fixed; 或 <td><th><table>;或 <body>) 的边缘的坐标,所以元素的外边距被计算在内,如:

image.png

scrollLeft,scrollTop:从元素的左上角开始,滚动出元素的左半部分/上半部分的值,如:

image.png image.png

通过以上示例可以实现 文字过长时截断隐藏(悬停时完全显示),未超长时没有悬停效果

image.png

image.png

猜你喜欢

转载自juejin.im/post/7034025744737632286