🌐Vue 3 表格「表頭固定 + 左欄固定」完整實戰:兩列表頭(rowspan)蓋不住?用 CSS 變數、position: sticky、z-index 一次搞定!
內容
這篇是給「對 CSS 不熟,但需要把表格頭固定」的人看的超清楚指南。
你會學到如何在 Vue 3 中打造「多列表頭(兩列) + 左邊固定欄位 + 水平捲動」的表格,並解決最常見的兩個痛點:
第二列表頭把第一列擋住、或蓋不齊。
左側固定欄(如
SEQ_NO
)在跨兩列表頭時高度不夠、蓋不住導致漏縫。
問題長什麼樣?
-
表格表頭有兩列(第一列是大群組、第二列是子欄位)。
-
表頭與左側第一欄要固定(
position: sticky
)。 -
捲動時會發生:
-
第二列表頭的
top
沒算好,導致重疊或露出縫隙。 -
左側固定欄(常見是
SEQ_NO
)設了rowspan="2"
,但高度只吃到第一列,沒有蓋到第二列。
-
這些問題幾乎都源自
高度(height
/top
)與層級(z-index
)
沒設定好。
解法核心觀念(先理解,後面照貼就成功)
-
兩列表頭要分別 sticky:
-
第一列:
top: 0
-
第二列:
top: <第一列的高度>
-
-
左側固定欄位(跨兩列)要有「兩列加總的高度」 才能把兩列表頭「一次蓋住」。
-
層級順序(
z-index
) 不能打架:-
左上角的「跨兩列」表頭要最高(它蓋兩列)。
-
接著是第二列表頭,再來第一列表頭,再來內文儲存格。
-
-
表格建議用
border-collapse: separate; border-spacing: 0;
這樣position: sticky
在多瀏覽器會更穩。
最小可行範例(Template)
一次貼好就能動的 CSS(重點都有註解)
直接貼,然後只需要微調兩個變數:第一列高度、第二列高度。
小提醒:若你的樣式表中還有其他
thead .sticky-left { z-index: 20; }
之類的舊規則,請把上面第 6 點的規則放在最後(或加!important
),避免被覆蓋。
常見坑與排錯
-
第二列表頭還是擋住第一列?
-
檢查
thead tr:nth-of-type(2) th { top: var(--hdr1) }
,--hdr1
是否正確。 -
檢查有沒有其他 CSS 把
top
或z-index
改掉。
-
-
左上角(跨兩列)沒蓋住第二列?
-
確認該格有
rowspan="2"
,並套用.sticky-left.sticky-span2
或選擇器thead th.sticky-left[rowspan="2"]
。 -
把高度設為
calc(var(--hdr1) + var(--hdr2))
,z-index
調高(如 60)。
-
-
sticky 完全不生效?
-
父層不能
overflow: hidden
(或需小心使用)。 -
table
請用border-collapse: separate
。 -
確認實際有「捲動容器」(通常是外層的
.table-container
)。
-
-
固定欄位邊界變「鋸齒」或看不到邊線
-
幫固定欄位右側加一條假邊線:
border-right: 1px solid #ddd;
。
-
Vue 3 小補充:同步底部水平捲動條(可選)
大寬表格常會做「底部同步捲動條」。概念是兩個容器互相同步
scrollLeft
:
最後的檢查清單(照著對)
-
第一列表頭:
top: 0; height: var(--hdr1); z-index: 11
-
第二列表頭:
top: var(--hdr1); height: var(--hdr2); z-index: 20
-
左上角跨兩列:
height: calc(var(--hdr1) + var(--hdr2)); z-index: 60
-
左側固定欄:
position: sticky; left: 0; background: #fff; z-index: 6
-
table { border-collapse: separate; border-spacing: 0; }
-
需要時加
border-right
讓邊界清楚 -
避免父層把
overflow
設得影響 sticky
結語
只要抓住三個點:高度、top 位移、z-index 層級,多列表頭 + 左欄固定其實一點都不難。把兩列表頭的高度用 CSS
變數控制,再針對左上角的跨兩列格子加總高度與最高層級,就能完美蓋住所有狀況。
有了這套,無論你要做供應鏈看板、報表、管理後台的大寬表格,都能維持
穩定、可讀、好維護!
— 祝你一次就黏住不飄 🎯
留言
張貼留言