🌐Vue 表格篩選視窗被遮住怎麼辦?一次看懂表格空白列高度、下拉篩選框顯示問題與修正方式

Vue 表格篩選視窗被遮住怎麼辦?新手也能看懂的完整教學

在做後台系統、報表頁面或資料查詢頁時,最常見的一種畫面就是「大表格」。
像是生產資料、訂單資料、客戶資料、排程結果,通常都會做成可以搜尋、可以篩選、可以匯出的表格。

但很多人在實作這種功能時,常常會遇到兩個很煩的問題:

  1. 點開欄位篩選時,下拉視窗被切掉,看不到完整內容
  2. 當篩選後沒有資料時,提示訊息那一列太矮,看起來很空、很怪

這篇文章會用完全新手也能理解的方式,帶你一步一步看懂:

  • 為什麼表格篩選框會被遮住
  • 為什麼「查無資料」那一列看起來很醜
  • 怎麼用 Vue + CSS 修正
  • 怎麼讓畫面更像正式商業系統

一、什麼是「表格篩選框被遮住」?

想像你在 Excel 裡面按欄位篩選,會跳出一個可以勾選資料的清單。
在網頁中,我們也常常會做類似的功能,例如:

  • 點「客戶」欄位的小按鈕
  • 跳出所有客戶名稱
  • 勾選你想保留的資料
  • 表格只顯示符合條件的列

問題是,很多人把這個篩選框放在表格容器裡後,因為外層區塊設定了 overflow,所以超出邊界的部分就直接被裁掉了。

你看到的現象通常會像這樣:

  • 篩選框明明有打開
  • 但只露出一小部分
  • 想看完整內容還要拖旁邊的捲軸
  • 使用者會以為功能壞掉

這其實不是 Vue 壞掉,也不是資料沒出來,通常只是 CSS 顯示層級與容器裁切設定 的問題。


二、另一個常見問題:篩選後沒資料,提示列太矮

很多頁面在篩選之後,如果沒有符合條件的資料,會顯示一行字,例如:

符合篩選的資料為空

但是如果這一列只是普通 <td>,就會變成:

  • 高度很小
  • 只有一條細細的訊息
  • 下方大片空白
  • 看起來不像完整介面

對使用者來說,這種畫面很容易造成誤解,會以為:

  • 是資料沒載入完成
  • 是頁面壞掉
  • 是自己操作錯誤

所以實務上,我們通常會把這一列做成比較高的提示區塊,讓使用者一眼就知道:
「不是壞掉,是目前篩選條件下沒有資料。」


三、先用白話文理解問題本質

這類問題,核心其實只有兩件事。

1. 下拉篩選框屬於「浮出來的元件」

它不是表格內正常排版的一部分,而是有點像浮在上面的視窗。
如果外層容器說:「超出我的範圍不准顯示」,那它就會被切掉。

2. 查無資料提示列,本質上只是普通表格儲存格

如果你沒有額外幫它設定高度、置中、背景或版面,它就只會是一個很普通的小格子。

所以要修正這兩個問題,方向也很簡單:

  • 讓篩選框不要被容器裁切
  • 讓空白提示列有足夠高度與視覺重心

四、範例情境:一個可以搜尋與篩選的資料表格

以下是一個重新改寫過的示意範例。
這不是原始對話裡的程式,而是全新整理過、適合教學用途的版本。

這個範例包含:

  • 關鍵字搜尋
  • 欄位篩選按鈕
  • 無資料提示
  • 表格區塊顯示修正

範例模板(Vue)

<template>
<section class="report-page">
<div class="toolbar">
<input
v-model="keyword"
class="keyword-input"
type="text"
placeholder="請輸入關鍵字"
/>
</div>

<div class="grid-wrapper">
<table class="data-grid">
<thead>
<tr>
<th>
編號
<button class="mini-filter" @click="togglePanel('code')">篩選</button>
<div v-if="openedPanel === 'code'" class="filter-panel">
<div class="filter-actions">
<button @click="pickAll('code')">全選</button>
<button @click="clearAll('code')">清空</button>
</div>
<label v-for="item in distinct.code" :key="item" class="option-item">
<input type="checkbox" v-model="selected.code" :value="item" />
{{ item }}
</label>
</div>
</th>

<th>品名</th>
<th>分類</th>
<th>數量</th>
</tr>
</thead>

<tbody>
<tr v-if="visibleRows.length === 0" class="no-data-row">
<td colspan="4">
<div class="no-data-box">
目前沒有符合條件的資料
</div>
</td>
</tr>

<tr v-for="row in visibleRows" :key="row.id">
<td>{{ row.code }}</td>
<td>{{ row.name }}</td>
<td>{{ row.group }}</td>
<td>{{ row.qty }}</td>
</tr>
</tbody>
</table>
</div>
</section>
</template>

範例邏輯(Vue script)

<script setup>
import { ref, computed } from 'vue'

const keyword = ref('')
const openedPanel = ref(null)

const rows = ref([
{ id: 1, code: 'A101', name: '螺絲', group: '五金', qty: 35 },
{ id: 2, code: 'A102', name: '螺帽', group: '五金', qty: 12 },
{ id: 3, code: 'B201', name: '電容', group: '電子', qty: 7 },
])

const distinct = {
code: [...new Set(rows.value.map(x => x.code))]
}

const selected = ref({
code: [...distinct.code]
})

function togglePanel(field) {
openedPanel.value = openedPanel.value === field ? null : field
}

function pickAll(field) {
selected.value[field] = [...distinct[field]]
}

function clearAll(field) {
selected.value[field] = []
}

const visibleRows = computed(() => {
const text = keyword.value.trim().toLowerCase()

return rows.value.filter(item => {
const matchKeyword =
!text ||
Object.values(item).join(' ').toLowerCase().includes(text)

const matchCode = selected.value.code.includes(item.code)

return matchKeyword && matchCode
})
})
</script>

範例樣式(CSS)

<style scoped>
.report-page {
background: #ffffff;
padding: 20px;
}

.toolbar {
margin-bottom: 12px;
}

.keyword-input {
width: 240px;
padding: 8px 10px;
border: 1px solid #cfcfcf;
border-radius: 6px;
}

.grid-wrapper {
position: relative;
overflow-x: auto;
overflow-y: visible;
border: 1px solid #d8d8d8;
}

.data-grid {
width: 100%;
min-width: 900px;
border-collapse: collapse;
}

.data-grid th,
.data-grid td {
border: 1px solid #e1e1e1;
padding: 10px;
text-align: center;
white-space: nowrap;
}

.data-grid th {
background: #f4d000;
position: relative;
}

.mini-filter {
margin-left: 8px;
padding: 2px 6px;
border: 1px solid #d1b400;
border-radius: 4px;
background: #ffef8a;
cursor: pointer;
}

.filter-panel {
position: absolute;
top: calc(100% + 6px);
left: 0;
width: 180px;
max-height: 260px;
overflow-y: auto;
background: #fff;
border: 1px solid #cccccc;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
border-radius: 8px;
padding: 10px;
z-index: 30;
}

.filter-actions {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
}

.option-item {
display: flex;
align-items: center;
gap: 6px;
margin: 6px 0;
}

.no-data-row td {
height: 280px;
padding: 0;
vertical-align: middle;
background: #fafafa;
}

.no-data-box {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #1f5fbf;
font-size: 18px;
font-weight: 700;
}
</style>

五、這段修正到底改了什麼?

很多剛接觸前端的人會想:「不就是一行訊息而已,為什麼還要多包一層 div?」

這裡其實有兩個關鍵。


1. 讓空白列變高

這一段:

.no-data-row td {
height: 280px;
}

意思是:
只要表格出現「沒有資料」那一列,就把它撐高到 280px。

這樣畫面就不會只剩下短短一行字,而是會像一個完整的提示區塊。


2. 讓提示文字水平與垂直都置中

這一段:

.no-data-box {
display: flex;
align-items: center;
justify-content: center;
}

意思是:

  • align-items: center:上下置中
  • justify-content: center:左右置中

所以不管這個提示區塊有多高,文字都會穩穩地出現在正中間,視覺上比較專業。


六、為什麼篩選框會被裁掉?

這通常跟下面這種寫法有關:

overflow: hidden;

它的意思很像:

超出我邊界的東西都不准顯示

但篩選框通常是展開在表頭外面的,所以只要超過邊界,就會直接消失一部分。

因此像這種表格篩選元件,外層容器比較常見的做法會是:

overflow-x: auto;
overflow-y: visible;

這樣的好處是:

  • 水平太寬時,仍然可以捲動
  • 篩選下拉視窗在垂直方向可以正常展開
  • 不會一打開就被切掉

七、為什麼商業系統很常遇到這種問題?

因為企業系統的表格通常都有這些特性:

  • 欄位很多
  • 表頭可能有兩層甚至三層
  • 每欄都有篩選
  • 還要固定表頭
  • 還要支援匯出 Excel
  • 還要記住使用者篩選條件

功能一多,畫面上的元素就會彼此影響。

例如:

  • 固定表頭會用 position: sticky
  • 篩選框會用 position: absolute
  • 外層容器又會有 overflow
  • 再加上 z-index 沒設定好

最後就會出現:

  • 篩選框被切掉
  • 篩選框被表頭蓋住
  • 篩選框顯示在奇怪的位置
  • 查無資料訊息太扁太小

這些都不是少見問題,反而是很多工程師都遇過的典型 UI 細節。


八、如果想讓畫面更像正式系統,還能再優化什麼?

除了修正顯示問題,還可以順手加強幾個地方。

1. 空白提示加上背景色

讓使用者一看就知道這是狀態訊息區,而不是表格壞掉。

例如:

.no-data-row td {
background-color: #f8fbff;
}

2. 加上 icon 或提示說明

例如:

  • 查無符合條件的資料
  • 請調整篩選條件後重新查詢

這樣使用者會更知道下一步該怎麼做。


3. 篩選框加入最大高度與捲動

如果選項很多,不要讓下拉視窗一直變長。

例如:

.filter-panel {
max-height: 260px;
overflow-y: auto;
}

4. 按鈕文案更清楚

像「全選」「清空」「套用」這些文字,可以比只放圖示更容易理解。


九、給完全沒寫過前端的人:你可以怎麼理解這件事?

你可以把整個頁面想成一個辦公桌。

  • 表格容器 就像桌子的範圍
  • 篩選框 就像桌上臨時打開的資料夾
  • 如果桌子規定「超出桌邊的東西都算不見」
  • 那資料夾只要稍微超出去,就會被切掉

而「沒有資料」那一列,就像你在桌子中間貼一張便利貼。
如果便利貼很小,整個桌面看起來就會很空。
所以我們會故意把它放進一個比較大的提示板裡,讓整體看起來更清楚。


十、實務建議:這類頁面開發時要先注意什麼?

如果你未來也要做 Vue 表格頁面,建議一開始就先檢查這幾件事:

畫面層面

  • 表格是否會超寬
  • 篩選框是否需要浮出顯示
  • 空資料狀態是否有良好提示
  • 表頭是否固定

CSS 層面

  • 外層容器有沒有 overflow: hidden
  • Dropdown 有沒有 position: absolute
  • z-index 是否足夠
  • 空白提示列是否有固定高度

使用者體驗層面

  • 沒資料時是否能一眼看懂
  • 篩選選項是否容易操作
  • 是否支援全選與清空
  • 畫面是否需要保留上次篩選結果

十一、簡單總結

這次的問題表面上看起來只是:

  • 篩選框看不到
  • 沒資料那列太矮

但背後其實是前端開發裡非常常見的兩種 UI 細節:

  1. 浮動元件被容器裁切
  2. 空狀態畫面沒有被好好設計

只要掌握這兩個原理,之後不管是 Vue、React,甚至純 HTML/CSS/JavaScript,其實都能用一樣的思路去處理。





如果你正在使用 Vue 3 製作查詢頁、報表頁或企業內部系統,遇到表格篩選框被遮住、查無資料畫面太難看、固定表頭與 dropdown 衝突等問題,這篇教學提供的思路會很實用。重點不是死背某一段程式碼,而是理解 overflow、position、table 高度與空狀態設計 之間的關係。只要搞懂這些觀念,之後在處理大型表格 UI 時就會輕鬆很多。

留言

這個網誌中的熱門文章

🔍Vue.js 專案錯誤排查:解決 numericFields is not defined 與合併儲存格邏輯最佳化

🖥️遠端桌面連線完整新手指南:Windows RDP、Chrome Remote Desktop、AnyDesk、TeamViewer 一次搞懂

🔎EF Core 連 Oracle 出現 ORA-00600 [kpp_concatq:2] 的完整排錯指南(含 EF Core ToString/CultureInfo 錯誤)