Dom盒子模型

301 阅读6分钟

本文正在参加「金石计划」

一、CSS盒子模型

1.标准盒模型(传统盒模型)

对应css样式:box-sizing:content-box;(默认值)

  • 盒子本身大小=内容宽高(width/height)+内边距(padding)+边框(border)

    • 例如:width:100px不是盒子大小,如果有内边距或者边框 宽度也会进行更改

2.怪异盒模型(IE盒模型)

就是设置css样式:box-sizing:border-box;

  • 盒子大小=内容宽高(width/height);
    • width=内容+padding+border;

二、JS中盒子模型

JS盒子模型属性:JS中提供了一些对应的API属性方法,可以让我们在JS中获取盒子的相关样式

1.client 系列

1) clientWidth/clientHeight

定义

获取盒子可视区域的宽度(内容+左右padding)

特点

  • 内容有溢出对其是没有影响的 在不设置高度的情况下 内容撑满+padding
  • 基于JS盒子模型属性获取的结果都是整数(可能会和实际的值产生一些偏差)
  • 如果加上了滚动条 获取的宽度是减去滚动条的宽度
  • 获取的结果是没有单位的(其余的盒模型属性也是)

使用

  • box.clientWidth
  • box.clientHeight

扩展

  • 获取浏览器可视窗口(浏览器一屏幕的宽高)
  • 注意:前面 documentElement 在低版本浏览器下不兼容
//=>document.documentElement 获取HTML元素对象
//=>兼容IE低版本浏览器document.documentElement.clientWidth||document.body.clientWidth
document.documentElement.clientWidth;
document.documentElement.clientHeight;

2) clicentTop 和 clicentLeft

没有获取右边框和下边框的盒子模型属性

定义

  • box.clientLeft获取盒子左边框的大小
  • box.clientTop获取盒子上边框的大小

2.offset 系列

1) offsetWidth/offsetHeight

定义

获取当前元素的总宽度/高度

  • 相当于在 client 的基础上加上 border == 盒子本身的宽高

特点

与 client 一致

  • 1.内容溢出与否对他无影响
  • 2.获取的结果是没有单位的(其余的盒模型属性也是)
  • 3.获取的结果是整数,它会自己进行四舍五入(其余的盒模型属性也是)

使用

box.offsetWidth / Height

2) offsetLeft / Top

定义

当前元素距离其父参照物的左偏移/上偏移

  • =>父级参照物不是父级元素 offsetParent
  • =>距离其父参照物的内边框(从当前元素外边框开始,到父参照物的内边框)

使用

box.offsetLeft/Top

注意

  • 不支持css3   
    • transform:translateX(100px);//唯一改变元素的位置 box.offsetLeft是获取不到的

outer/box 不加定位

outer定位-加定位后

但是这种方式 不识别:css3

3) offsetParent

定义

获取它的父参照物(不一定是父元素)

  • 父参照物和它的父元素没有必然的联系

父参照物查找:同一个平面中,最外层元素是内层所有元素的父参照物

  • 默认情况下,所有的元素都在同一个文档流(同一个平面)中,这样他们的父参照物都是BODY,所获取的偏移也都是距离BODY的
  • 但是一旦某些元素设置了position (relative/absolute/fixed)就会形成一个新的平面,那么其内部元素的父参照物就不再是BODY,而是当前元素本身

注意

document.body.offsetParent === null;

使用

box.offsetParent

拓展

封装一个方法获取一个元素距离body的左、上偏移量(不论其父参照物是谁

  • 真实项目中搭建结构和样式的时候,为了方便布局开发 我们会大量使用定位
  • 封装一个方法获取一个元素距离body的左、上偏移量(不论其父参照物是谁)

思路

1.获取当前元素的父参照物,再获取父参照物的父参照物...一直获取到找不到父参照物了(说明已经找到BODY了)则结束查找offsetParent

2.每—次找到对应的父参照物

  • 距离其父参照物的偏移(左偏移和上偏移) offsetLeft/offsetTop+父参照物的边框(左边框和上边框) clientLeft/clientTop

【注意】兼容问题:在标准的IE8浏览器中,偏移值是当前元素外边框距离父参照物的外边框的距离(其它浏览器都是距离父参照物内边框),所以我们计算偏移值的时候,如果是IE8浏览器,则边框不需要在加了

window.navigator.userAgent 获取当前浏览器的版本信息

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>JS盒子模型属性</title>
    <link rel="stylesheet" href="css/reset.min.css" />
    <style>
        .outer {
            box-sizing: border-box;
            margin: 20px auto;
            width: 500px;
            height: 500px;
            background: lightcoral;
            border: 10px solid orangered;
            /* position: relative; */
        }

        .box {
            box-sizing: border-box;
            margin: 20px auto;
            padding: 15px;
            width: 300px;
            height: 300px;
            border: 10px solid lightblue;
            background: lightcyan;
            font-size: 18px;
            line-height: 30px;
            overflow: auto;
        }
    </style>
</head>

<body>
    <div class="outer" id="outer">
        <div id="box" class="box">
            君不见黄河之水天上来,奔流到海不复回。
            君不见高堂明镜悲白发,朝如青丝暮成雪。
            人生得意须尽欢,莫使金樽空对月。
            天生我材必有用,千金散尽还复来。
            烹羊宰牛且为乐,会须一饮三百杯。
            岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。
            钟鼓馔玉不足贵,但愿长醉不用醒。
            古来圣贤皆寂寞,惟有饮者留其名。
            陈王昔时宴平乐,斗酒十千恣欢谑。
            主人何为言少钱,径须沽取对君酌。
            五花马、千金裘,呼儿将出换美酒,与尔同销万古愁。
        </div>
    </div>
</body>
</html>
考虑IE8版本
function offset(element) {
            // 1.首先获取当前元素的父参照物和其距离父参照物的偏移
            let parent = element.offsetParent,
                top = element.offsetTop,
                left = element.offsetLeft;
            // 2.循环依次向上查找父参照物(一直到找不到为止)
            while (parent) {
                // 不是IE8l浏览器 才加边框
                if (!/MSIE 8.0/.test(navigator.userAgent)) {
                    left += parent.clientLeft;
                    top += parent.clientTop;
                }
                // 加上父参照物的偏移
                left+=parent.offsetLeft;
                top+=parent.offsetTop;
                // 继续向上查找
                parent = parent.offsetParent;
            }
            // 3.把查找的结果返回
            return {
                // top:top left:left
                top,
                left
            }
        };
不考虑IE8版本
 /* 
        *   offset:获取当前元素距离body的左偏移和上偏移
        *       @params
        *           element[element object]:要操作的元素
        *       @return
        *           [object]:{top:xxx,left:xxx}
        * by 2021-05-07
        */
        function offset(element){
            // 1.首先获取当前元素的父参照物和其距离父参照物的偏移
            let parent=element.offsetParent,
                top=element.offsetTop,
                left=element.offsetLeft;
            // 2.循环依次向上查找父参照物(一直到找不到为止)
            while(parent){
                // 加上父参照物的边框(非IE8浏览器中才加)
                left+=parent.clientLeft+parent.offsetLeft;
                top+=parent.clientTop+parent.offsetTop;
                // 加上父参照物的偏移
                // left+=parent.offsetLeft;
                // top+=parent.offsetTop;
                // 继续向上查找
                parent=parent.offsetParent;
            }
            // 3.把查找的结果返回
            return{
                // top:top left:left
                top,
                left
            }
        };

3.scroll 系列

1) scrollWidth / scrollHeight

定义

  • 在没有内容溢出的情况下,scrollWidth/scrollHeight获取的结果和 clientWidth/clientHeight结果是一样的
  • 在内容有溢出的情况下,它的结果包含了溢出内容宽高(但是这个值是一个约等于的值,不完全准确的:在不同浏览器中,因为对内容渲染机制的差异,结果是不一样的,而且我们设置的overflow的值也对最后的结果有影响)

使用

  • box.scrollWidth
  • box.scrollHeight

拓展

获取当前页面真实的宽度和高度,包括那部分溢出的内容

  • document.documentElement.scrollWidth|| document.body.scrollWidth
  • document.documentElement.scrollHeight|| document.body.scrollHeight

2) scrollTop / scrollLeft

定义

竖向 / 横向 滚动条卷去的高度/宽度

特点

边界值
  • 最小值 0
  • 最大值 =(整个的高度scrollHeight) - (一屏幕高度可视区域clientHeight)

利用边界值:

  • 快速定位到顶部:box.scrollTop=0;
  • 快速定位到底部:box.scrollTop = box.scrollHeight-box.clientHeight

可读写
  • 13个盒子模型属性,只有这两个是“可读写”的属性(既可以获取也可以设置对应的值)
  • 其余的都是“只读”属性(不能设置值,只能获取)

使用

  • box.scrollTop
  • box.scrollLeft

实例

回到顶部
  • window.onscroll

    • 滚动条 手动拖动,鼠标滚轮 上下键 JS中赋值滚动
    • 无论我们基于了什么方式,控制了滚动条的滚动,都会触发这个事件,让绑定的方法执行
<!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>
    <link rel="stylesheet" href="./css/reset.min.css">
    <style>
        html,
        body {
            height: 1000%;
            background: -webkit-linear-gradient(top left, red, green, blue, orange, pink);
        }

        #btn {
            width: 100px;
            height: 50px;
            position: fixed;
            right: 20px;
            bottom: 50px;
            display: none;
        }
    </style>
</head>

<body>
    <button id="btn">回到顶部</button>
    <script>
        // 一开始不显示回到顶部按钮,当随着滚动条滚动,卷去的高度超过了一屏幕的大小,我们再显示这个按钮
        let btn = document.querySelector("#btn");
        //滚动条 手动拖动,鼠标滚轮 上下键 JS中赋值滚动
        window.onscroll = function () {
            // 无论我们基于了什么方式,控制了滚动条的滚动,都会触发这个事件,让绑定的方法执行
            let sT = document.documentElement.scrollTop,
                cH = document.documentElement.clientHeight;
            if (sT >= cH) {
                btn.style.display="block";
            }else{
                btn.style.display="none";
            }
        }
        btn.onclick = function () {
            document.documentElement.scrollTop = 0;
        }
    </script>
</body>
</html>
   this.$nextTick(() => {
        // 监听到事件后执行的业务逻辑
        // 使echarts尺寸重置
      let ss = document.getElementsByClassName('ivu-menu')[0].clientWidth
      console.log(ss)
    })