获取height固定折叠元素真实高度方法

假设,DOM 被设置了 height:20px 和 overflow:hidden,如何计算它的真实高度呢?css

1、问题背景

最近在优化折叠组件,须要在窗口宽度变化的时候从新判断展开收起状态。若是段落高度大于给定高度,则隐藏超高内容,展现【展开】按钮。若是段落高度小于给定高度,则不限制最大高度,隐藏【展开】按钮。node

但如何计算【段落高度小于给定高度】呢?好比,段落被设置了 height="20px",如何计算它的真实高度呢?浏览器

2、干货,计算元素真实高度函数

方法以下,直接传入要计算的目标 dom 就行了。dom

function getHeightUnfold (dom) {
    var fakeNode = dom.cloneNode(true);
    fakeNode.style.position = 'absolute';
    // 先插入再改样式,以防元素属性在createdCallback中被添加覆盖
    dom.parentNode.insertBefore(fakeNode, dom);
    fakeNode.style.height = 'auto';
    fakeNode.style.visibility = 'hidden';

    var height = fakeNode.getBoundingClientRect().height;
    dom.parentNode.removeChild(fakeNode);

    return height;
}

这个方法的核心是,建立一个不可见元素,摘除高度限制,最终计算它的高度。函数

3、发散思考

1. 复制元素的必要性

Jenny_L 给复制出来的元素增长了 postiion: absolute 属性,为了避免触发后面元素的重拍重绘,节省浏览器资源。若是直接快速地给目标元素设置 height: auto + 获取高度 + height: 20px,虽然能达到目的,但会形成全部后续元素的(不必定可见)抖动,尽可能避免。post

2. Node.cloneNode 与 document.createElement('div') 的选择

后者与innerHTML配合使用,虽然可以模仿目标元素的内层内容,但不能继承目标元素的样式。即便使用document.createElement(dom.nodeName)也会有问题,不能继承内联样式。而使用cloneNode不但能够继承 class,css,还能触发 createdCallback(若是有的话),继承 js 中添加的内联样式。优化

3. fakeNode.getBoundingClientRect().height 与 getComputedStyle(fakeNode).height 的选择

都是计算高度的,但前者计算的是占位高度,包括 padding+border;后者计算的是单纯高度,通过多层 css 优先级竞争以后的 height 取值(px),获取纯数值还须要parseInt()。本次状况,须要计算占位高度,因此选择getBoundingClientRect()code

4. removeChild 的必要性

虽然 fakeNode 不可见,但终究在文档流中,display 不是 none,重拍的时候会参与计算。除此以外,若是原先 dom 带有 id="someID" 的话,删除 fakeNode 以前,文档中就会存在两个 id="someID" 的元素。将来浏览器再作选择的时候,就懵逼了。继承

4、自勉

很久不写文章了,草稿箱里存了好多代码片断,要加油了。资源

不得不说,这种小代码片断仍是颇有分享价值的,一次研究(居然花了一个小时),将来到处复制,走向人生巅峰。

相关文章
相关标签/搜索