獲取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、自勉

很久不寫文章了,草稿箱裏存了好多代碼片斷,要加油了。資源

不得不說,這種小代碼片斷仍是頗有分享價值的,一次研究(居然花了一個小時),將來到處複製,走向人生巔峯。

相關文章
相關標籤/搜索