HTML+CSS+JS實(shí)現(xiàn)完美兼容各大瀏覽器的TABLE固定列
BS架構(gòu)的企業(yè)級(jí)應(yīng)用中,當(dāng)一個(gè)表格列數(shù)較多時(shí),用戶一個(gè)常見的需求就是把前面幾個(gè)重要的列固定住,這樣拖動(dòng)滾動(dòng)條時(shí)固定的列會(huì)方便用戶查看數(shù)據(jù),用戶體驗(yàn)很好。一些重量級(jí)的JS組件庫也都有這個(gè)功能,那么有沒有更簡(jiǎn)單的方法實(shí)現(xiàn)這個(gè)功能呢?
這個(gè)需求常見的解決方案是使用表格拼接的方法,這個(gè)方案如果要制作靜態(tài)的網(wǎng)頁,或者功能簡(jiǎn)單的動(dòng)態(tài)頁面,邏輯比較簡(jiǎn)單,技術(shù)上也不復(fù)雜,很容易實(shí)現(xiàn),但是如果要做成組件,動(dòng)態(tài)功能較多的話,就需要寫大量的冗余代碼,難以維護(hù),甚至于一個(gè)簡(jiǎn)單的功能,都需要寫很多的代碼,比如事件處理等,這個(gè)方法就顯得比較笨拙,靈活性很差,不是一個(gè)好的方案。
經(jīng)過長(zhǎng)時(shí)間的分析研究,各種場(chǎng)景的試驗(yàn),我們找到了一個(gè)兼容性非常好的解決方案,總體上來講采用的是定位計(jì)算的方法,下面貼出代碼,然后做個(gè)解讀。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>無標(biāo)題文檔</title> <script type="text/javascript"> function divScroll(scrollDiv){ var scrollLeft = scrollDiv.scrollLeft; document.getElementById("tableDiv_title").scrollLeft = scrollLeft; document.getElementById("tableDiv_body").scrollLeft = scrollLeft; } function divYScroll(scrollYDiv){ var scrollTop = scrollYDiv.scrollTop; document.getElementById("tableDiv_y").scrollTop = scrollTop; } function onwheel(event){ var evt = event||window.event; var bodyDivY = document.getElementById("tableDiv_y"); var scrollDivY = document.getElementById("scrollDiv_y"); if (bodyDivY.scrollHeight>bodyDivY.offsetHeight){ if (evt.deltaY){ bodyDivY.scrollTop = bodyDivY.scrollTop + evt.deltaY*7; scrollDivY.scrollTop = scrollDivY.scrollTop + evt.deltaY*7; }else{ bodyDivY.scrollTop = bodyDivY.scrollTop - evt.wheelDelta/5; scrollDivY.scrollTop = scrollDivY.scrollTop - evt.wheelDelta/5; } } } </script> <style type="text/css"> body { margin:0; padding:0; } table { border-collapse:collapse; border:0; border:none; } table td { border:1px solid #000; overflow:hidden; padding:0 2px; } </style> </head> <body> <div style="width:500px; position:relative; padding-right:18px;"> <div style="position:relative;height:368px;overflow:hidden;width:100%"> <div style="padding-left:108px; width:auto; overflow:hidden; background:#f00;" id="tableDiv_title" > <table border="0" cellspacing="0" cellpadding="0" > <tr> <td style="min-width:30px; max-width:30px; left:0; top:0; width:30px; overflow:hidden; background-color:#f00;position:absolute;z-index:1;">000</td> <td style="min-width:74px; max-width:74px; left:30px; top:0; width:74px; overflow:hidden; background-color:#f00;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> </table> </div> <div style="overflow:hidden; position:absolute;height:128px; width:100%;" id="tableDiv_y" onmousewheel="onwheel(event);" onwheel="onwheel(event);"> <div style="padding-left:108px; width:auto;overflow:hidden;" id="tableDiv_body"> <table border="0" cellspacing="0" cellpadding="0" > <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">001</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff; position:absolute; z-index:1;">002</td> <td style="min-width:74px; max-width:74px; left:30px; width:74px; overflow:hidden;background-color:#fff; position:absolute; z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">003</td> <td style="min-width:74px; max-width:74px;left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">004</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">005</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">006</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">007</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">008</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">009</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">010</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自動(dòng)表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自動(dòng)</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> </table> </div> </div> <div style="background-color:#eee;overflow:hidden;top:150px; width:100%; z-index:2;position:absolute;"> <div style="margin-left:108px; width:auto;overflow-x:scroll;overflow-y:hidden;" onscroll='divScroll(this);'> <div style="width:630px; height:1px;"></div> </div> </div> </div> <div id="scrollDiv_y" style="display:block; overflow-x:hidden; overflow-y:scroll; position:absolute; top:22px; right:0px; height:118px; padding-bottom:10px;" onscroll='divYScroll(this);'> <div style="width:1px; height:194px;"></div> </div> </div> </div> </body> </html>
一、總體結(jié)構(gòu):
頁面基本元素為DIV+TABLE,固定的列采用絕對(duì)定位的方式固定,每一列都要指定固定寬度,為了解決橫豎滾動(dòng)條的問題,表頭和表體的外面分別包裹兩層DIV,滾動(dòng)條采用虛擬的方式,固定在固定位置通過JS控制模擬正常DIV滾動(dòng)條的效果。
二、定位:
固定的列要絕對(duì)定位,通過left屬性控制左側(cè)位移,為了保證固定列浮動(dòng)在上方,設(shè)置z-index為1,。為了保證有豎滾動(dòng)條時(shí)的正常顯示,表體的外層DIV為絕對(duì)定位,由此導(dǎo)致滾動(dòng)條也都要絕對(duì)定位。還有,表頭和表體以及滾動(dòng)條的內(nèi)層DIV通過margin-left屬性控制左側(cè)外邊距,把固定列的偏移量空余出來。
二、寬度計(jì)算:
每一列的寬度都要指定固定的值,并且要注意一個(gè)關(guān)鍵點(diǎn),就是還要加上min-width和max-width屬性,這兩個(gè)屬性和width值相等,表頭表體的內(nèi)層DIV,寬度為auto,自適應(yīng)表格寬度,外層DIV寬度為100%,最外層的DIV通過padding-right屬性控制右側(cè)內(nèi)邊距,將豎滾動(dòng)條的位置空余出來。
三、高度計(jì)算:
因?yàn)榻^對(duì)定位的存在,整個(gè)表格組件的高度要指定,可以通過計(jì)算得出,豎滾動(dòng)條的top值也需要進(jìn)行計(jì)算。
四、滾動(dòng)條:
本方案一個(gè)突出特點(diǎn),就是虛擬的滾動(dòng)條,就是通過一個(gè)和表格一樣寬、高度為一個(gè)像素的DIV模擬出表體DIV的橫向滾動(dòng)條,豎滾動(dòng)條同理。之所以采用這個(gè)形式,一個(gè)是橫向滾動(dòng)條這樣處理比較美觀,豎滾動(dòng)條這樣處理之后,表頭和表體的外層DIV寬度不用計(jì)算了,都為100%,否則存在滾動(dòng)條時(shí),表頭和橫向滾動(dòng)條要空出豎滾動(dòng)條寬度的位移,否則無法對(duì)齊,這個(gè)計(jì)算倒不復(fù)雜,但是某些情況下存在問題,在此不展開了。
五、滾動(dòng)事件:
因?yàn)楸眢w的滾動(dòng)條都隱藏了,導(dǎo)致鼠標(biāo)滾輪不起作用了,這樣就需要用JS處理鼠標(biāo)滾輪事件,本文的樣例代碼兼容常見瀏覽器。這里的重點(diǎn)是同時(shí)寫了onmousewheel和onwheel事件,onmousewheel兼容IE,在計(jì)算滾動(dòng)距離時(shí),注意deltaY和wheelDelta屬性的差異即可。
六、優(yōu)缺點(diǎn)分析:
本文的解決方案已經(jīng)經(jīng)過精簡(jiǎn),重點(diǎn)是講清楚原理,在我們的實(shí)際中,非常的復(fù)雜。這個(gè)設(shè)計(jì)考慮了非常多的兼容性,包括了瀏覽器的兼容性和各種場(chǎng)景的兼容性,如果需求簡(jiǎn)單,還有簡(jiǎn)化的空間。
這個(gè)方案的優(yōu)點(diǎn)是,如果要做組件的話,因?yàn)镠TML結(jié)構(gòu)簡(jiǎn)單,表頭和表體都是一個(gè)TABLE,JS控制代碼非常干凈,維護(hù)容易。缺點(diǎn)就是計(jì)算過多。我們認(rèn)為該方案比較適用于開發(fā)組件的情況,靜態(tài)頁面就有點(diǎn)小題大作了。
以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。
相關(guān)文章
javascript設(shè)計(jì)模式Constructor(構(gòu)造器)模式
這篇文章主要為大家詳細(xì)介紹了javascript設(shè)計(jì)模式Constructor(構(gòu)造器)模式 ,感興趣的小伙伴們可以參考一下2016-08-08Javascript獲取頁面元素的絕對(duì)位置實(shí)現(xiàn)
這篇文章主要為大家介紹了Javascript獲取頁面元素的絕對(duì)位置實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11firefo xml 讀寫實(shí)現(xiàn)js代碼
firefo xml 讀寫實(shí)現(xiàn) 不過要是你的xml要編碼成功還得在str前面加上xml頭,千萬別忘了啊。2009-06-06利用JavaScript實(shí)現(xiàn)靜態(tài)圖片局部流動(dòng)效果
如果你有玩過《王者榮耀》、《陰陽師》?等手游,一定注意到過它的啟動(dòng)動(dòng)畫、皮膚立繪卡片等場(chǎng)景,經(jīng)常采用靜態(tài)底圖加局部液態(tài)流動(dòng)效果的簡(jiǎn)單動(dòng)畫,本文將利用JavaScript實(shí)現(xiàn)這一效果,需要的可以參考一下2022-08-08js猜數(shù)字小游戲的簡(jiǎn)單實(shí)現(xiàn)代碼
這篇文章介紹了js猜數(shù)字小游戲的簡(jiǎn)單實(shí)現(xiàn)代碼,很好玩的游戲哦,可以看看你的智商 是否驚人額2013-07-07JavaScript 代碼分割的實(shí)現(xiàn)步驟
JavaScript代碼分割是一種優(yōu)化策略,通過將代碼拆分成較小的塊,只在需要時(shí)加載,可以降低初始加載時(shí)間,減小頁面體積,本文主要介紹了JavaScript代碼分割的實(shí)現(xiàn)步驟,感興趣的可以了解一下2024-01-01IE 下Enter提交表單存在重復(fù)提交問題的解決方法
這篇文章主要介紹了IE 下Enter提交表單存在重復(fù)提交問題的解決方法,需要的朋友可以參考下2014-05-05原生JS實(shí)現(xiàn)左右箭頭選擇日期實(shí)例代碼
原生JS 左右箭頭選擇日期,就是用左右尖括號(hào)可改變中間日期的值,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-03-03