
透過適當地將相關的輸入欄位群組在一起,我們能讓表單內容變得更井然有序。例如,當表單上有多個互相關聯的欄位(如一組地址資訊需要填寫街道、城市、郵遞區號等多個欄位),或者一道需要多個選項回答的問題(如多個核取方塊或單選按鈕屬於同一題),就非常適合使用 <fieldset> 將它們包起來,並透過 <legend> 標示這組欄位的主題。這麼做不僅讓視覺上表單更容易瀏覽,也有助於提升無障礙體驗,方便使用輔助技術的使用者理解表單結構。相對地,如果表單只需要收集單一資訊(只有一個欄位),那麼直接使用 <label> 搭配輸入框即可,無需特地用 <fieldset>。
<fieldset> 是什麼?
<fieldset> 是 HTML 提供的欄位集容器(fieldset 元素),用途是在表單中將若干相關的輸入元件和其標籤(<label>)歸納在一起。它本身是個區塊級(block)元素,在視覺上會對所包裹的內容繪製出一個方框(預設有 2px 凹槽狀的邊框),彷彿替這組欄位劃分出一個區域。做為一個容器元素,<fieldset> 必須具有開啟和結束標籤,並且一般應置於 <form> 表單元素之內。
所有現代瀏覽器都支援 <fieldset>(這其實是從早期 HTML 就存在的標籤),因此開發者可以放心地加以使用。除了基本的分組功能外,<fieldset> 還提供了一些實用的屬性。例如,在 <fieldset> 標籤上加入 disabled 屬性,便能一次將該分組中所有的表單控制項禁用(瀏覽器通常會將群組中的欄位呈現為灰色且無法編輯或聚焦)。這對於需要動態控制整組欄位是否可填寫的情境很有幫助。此外,<fieldset> 也支援一個可選的 name 屬性,可以為這個欄位群組命名(雖然它不會直接參與表單資料提交,但在腳本中可以用來識別這個群組的用途)。
<legend> 是什麼?
<legend> 元素代表的是其父 <fieldset> 的標題或說明。換言之,<legend> 提供了這一組欄位的敘述性標籤,讓使用者了解該分區的用途。通常我們會將 <legend> 作為 <fieldset> 內的第一個子元素,直接在開頭定義這個群組的名稱。例如,在一組聯絡資訊的欄位集中,可以寫入 <legend>聯絡資訊</legend> 來作為整組欄位的說明標題。
需要注意的是,<legend> 應該和 <fieldset> 搭配使用才有意義。如果單獨放置一個 <legend>(不在 <fieldset> 裡),它不會對任何表單欄位產生作用,只會被視為一般的文字。事實上,每個 <fieldset> 理論上只應包含一個 <legend> 作為該群組的名稱(若在一個 <fieldset> 中編寫多個 <legend>,只有第一個會被當作正式標題,其餘可能會被忽略或當成普通內容)。因此,在建立表單分區時,務必要記得在 <fieldset> 裡頭緊跟著放上一個適當的 <legend>,以清楚地表達該區塊的意義。
如何用 <fieldset> 改善表單分區
現在讓我們來看一個實際範例,示範如何用 <fieldset> 和 <legend> 來替表單區塊分組。在下面的 HTML 程式碼中,我們建立了一個簡單的聯絡資料表單,將「姓名」和「電子郵件」這兩個相關欄位放在一個 <fieldset> 中,並用 <legend> 加上「聯絡資訊」作為該區域的標題:
<form>
<fieldset>
<legend>聯絡資訊</legend>
<label for="name">姓名:</label>
<input type="text" id="name" name="name"><br>
<label for="email">電子郵件:</label>
<input type="email" id="email" name="email">
</fieldset>
</form>
在這段程式碼中,我們利用 <fieldset> 將「姓名」和「電子郵件」這兩個輸入欄位包在一起,並透過 <legend> 提供了一個標題「聯絡資訊」。瀏覽器會自動在這區段周圍繪製方框,並將 <legend> 的文字呈現在方框上方的邊框處,清楚地標示出這些欄位屬於哪個類別。同時,我們也正確地使用了 <label for="..."> 來對應各自的輸入框,確保每個輸入欄位都有明確的標籤。透過這種結構,使用者一目了然地知道「聯絡資訊」區域包含了姓名和電子郵件等欄位,表單閱讀起來更有條理。
無障礙性(Accessibility)觀點
良好的表單結構對於使用輔助技術(例如螢幕閱讀器)或僅使用鍵盤操作的使用者尤為重要。使用 <fieldset> 和 <legend> 進行欄位分組,能夠為這些使用者提供關鍵的語意線索,讓他們理解多個欄位之間的關聯。
舉個例子:假設表單上有一個問題「你有護照嗎?」,下面有兩個選項使用單選按鈕(Radio buttons)表示「有」或「沒有」。如果我們沒有使用 <fieldset> 將這些選項與問題文字綁在一起,螢幕閱讀器在使用者切換到這兩個單選按鈕時只會逐一讀出各選項的標籤(例如「有,單選按鈕」或「沒有,單選按鈕」),而不會讀出問題本身。使用者可能就搞不清楚這些「有/沒有」按鈕是在回答哪一個問題。
相反地,若我們改用 <fieldset> 和 <legend> 來結構化這組選項,程式碼可能如下所示:
<form>
<fieldset>
<legend>你有護照嗎?</legend>
<input type="radio" id="yes" name="passport" value="yes">
<label for="yes">有</label><br>
<input type="radio" id="no" name="passport" value="no">
<label for="no">沒有</label>
</fieldset>
</form>
現在,當螢幕閱讀器使用者跳轉到這組單選按鈕時,它會先讀出 <legend> 的內容。例如,在進入第一個選項時,螢幕閱讀器可能會唸出:「你有護照嗎? 有。單選按鈕,未選取」(實際讀出的句子依軟體而定),如此一來使用者就清楚這個「有」是針對「你有護照嗎?」這個問題的回答。可見,透過 <fieldset>/<legend> 提供的語意結構,視障使用者能夠理解多個表單欄位之間的關係,彌補了無法看到視覺排版的劣勢。
還有另一種常見情況:表單中存在兩組結構相似的欄位(例如「寄送地址」和「帳單地址」各有一套姓名、街道、城市、郵遞區號等欄位)。視覺上我們可以透過在每組欄位上方加上標題來區分,但對螢幕閱讀器而言,只有藉由 <fieldset> 和 <legend> 提供的語意資訊,才能讓程式明確區分「這幾個欄位屬於寄送地址,那幾個屬於帳單地址」。否則,當螢幕閱讀器碰到兩個都叫「姓名」的欄位時,使用者將無從得知哪一個是寄送地址的姓名、哪一個是帳單地址的姓名。有了 <fieldset>,這些資訊架構就變得清楚明瞭。因此,從無障礙角度看,<fieldset> 和 <legend> 能讓表單對所有使用者(不管能否看見畫面)都更加友好。
實際應用情境
接下來,我們看看一個實際應用的例子:假設在線上購物的結帳頁面,需要使用者填寫「付款資訊」和「帳單地址」。這兩組欄位性質不同,非常適合用各自的 <fieldset> 分區。下面的範例程式碼展示了如何利用兩個 <fieldset>,分別搭配 <legend> 說明每個區塊的主題:
<form>
<fieldset>
<legend>付款資訊</legend>
<label for="card-number">信用卡號:</label>
<input type="text" id="card-number" name="card-number"><br>
<label for="card-name">持卡人姓名:</label>
<input type="text" id="card-name" name="card-name"><br>
<label for="exp">有效期限(月/年):</label>
<input type="month" id="exp" name="exp">
</fieldset>
<fieldset>
<legend>帳單地址</legend>
<label for="fullname">收件人姓名:</label>
<input type="text" id="fullname" name="fullname"><br>
<label for="address">地址:</label>
<input type="text" id="address" name="address"><br>
<label for="city">城市:</label>
<input type="text" id="city" name="city"><br>
<label for="zip">郵遞區號:</label>
<input type="text" id="zip" name="zip">
</fieldset>
</form>
如上所示,我們將付款相關的欄位群組在第一個 <fieldset> 之中,並以 <legend>付款資訊</legend> 標示其主題;第二個 <fieldset> 則包含了帳單地址相關欄位,並以 <legend>帳單地址</legend> 作為標題。這樣一來,無論是對一般使用者還是對輔助工具而言,表單都被劃分成了兩個清晰的區塊:第一部分填寫信用卡相關資訊,第二部分填寫帳單地址細節。使用者在視覺上可以很容易地辨識出哪幾個欄位屬於付款資訊、哪幾個欄位屬於帳單地址,整個表單不會顯得雜亂無章。同時,如果將來需要調整表單結構或增減欄位,這種清晰的分區也讓維護工作更加簡便。
CSS 注意事項:客製化樣式與跨瀏覽器差異
雖然 <fieldset> 和 <legend> 本身帶有預設的瀏覽器樣式,但我們可以透過 CSS 來調整它們的外觀以符合設計需求。在預設情況下,多數瀏覽器會以一條帶有凹槽效果的灰色邊框來呈現 <fieldset>,並將 <legend> 的文字顯示在該方框上方(通常有些預設的內邊距)。然而,不同瀏覽器對這些預設樣式的處理細節略有差異。例如,有些瀏覽器會給 <fieldset> 一定的內距(padding)和極小的外距(margin);<legend> 的對齊方式和周圍空間在不同瀏覽器間也可能略有不同。因此,在客製化樣式時,最好明確設定這些元素的 CSS,以確保跨瀏覽器的一致性。
以下是一些對 <fieldset> 和 <legend> 進行樣式調整的建議:
移除或修改預設邊框: 如果不喜歡預設的 3D 溝槽邊框效果,可以透過 CSS 重設。例如,設置 fieldset { border: none; } 可以去除整個邊框,之後再自行加上想要的邊框樣式(實線、虛線、顏色等)。你也可以直接修改邊框的粗細、樣式和顏色,甚至增減圓角,以符合視覺風格。
處理間距與寬度: 瀏覽器預設給 <fieldset> 的內邊距和最小寬度可能會影響版面。我們可以明確指定 padding 和 margin 為所需值,並將 min-width 設為 0 來避免在某些情況下 <fieldset> 自帶的最小寬度限制導致版面走樣。對 <legend> 而言,直接設定 margin 往往不起作用(部分瀏覽器對 <legend> 的 margin 有特殊處理),建議改用 padding 來調整 <legend> 周圍空白。
字體與顏色: 可以像設計標題一樣去設計 <legend> 的字詞。透過 CSS 調整字型大小、顏色、背景或字重等,使 <legend> 看起來更凸顯或更符合整體風格。例如,你可以將 <legend> 的文字加粗,加上底色或邊框來讓它更醒目。
使用 CSS Reset/Normalize: 為了消除各瀏覽器之間的預設差異,可以考慮使用 CSS Reset 或 Normalize.css 等工具。這些重設樣式通常會對 <fieldset> 和 <legend> 做一些統一處理(如移除內建的 margin、padding、邊框等),讓你在此基礎上更輕鬆地客製外觀。
下面是一段範例 CSS,將 <fieldset> 和 <legend> 客製化成我們想要的樣式:
fieldset {
border: 2px solid #aaa; /* 改為 2px 灰色實線邊框 */
border-radius: 5px; /* 邊框圓角半徑 5px */
padding: 1em; /* 內距,確保內容不貼邊框 */
margin: 1em 0; /* 外距,將各群組上下分開 */
min-width: 0; /* 移除某些瀏覽器的最小寬度限制 */
}
legend {
font-weight: bold; /* 粗體字,使標題突出 */
padding: 0 5px; /* 左右內邊距,覆蓋預設的對齊 */
color: #fff; /* 將文字顏色設為白色 */
background-color: #777; /* 灰色背景,讓標題更醒目 */
border-radius: 3px; /* 為標題增加些微圓角 */
}
上述樣式將 <fieldset> 的邊框改為簡單的灰色實線並帶有圓角,<legend> 則呈現為白字配灰底的標籤樣式。調整後,瀏覽器預設的凹槽邊框效果消失,各瀏覽器的顯示更加一致。如果你的表單需要不同的視覺風格,也可以按照需求對這兩個元素進一步客製化。總之,<fieldset>/<legend> 在語意上提供結構劃分,但在外觀上我們有完全的掌控權來讓它們融入整體設計。
實作錯誤範例與修正方式
即使了解了 <fieldset> 和 <legend> 的作用,在實際開發中仍可能出現一些使用上的誤區。以下整理幾個常見的錯誤,以及對應的正確作法:
錯誤 1:忽略使用 <fieldset> 進行分組
有些開發者在處理多個相關欄位或多選項問題時,直接將問題文本放在一個 <p> 或 <div> 裡,下面緊跟著多個輸入欄位,但沒有使用 <fieldset> 來語意化地綁定它們。這樣會導致無障礙資訊缺失。如下面的錯誤範例:
<form> <p>你有護照嗎?</p> <input type="radio" id="yes" name="passport" value="yes"> <label for="yes">有</label><br> <input type="radio" id="no" name="passport" value="no"> <label for="no">沒有</label> </form>
在上述碼例中,問題文字「你有護照嗎?」只是純粹放在段落裡,和下面的選項沒有程式上的從屬關係。螢幕閱讀器讀到這兩個單選按鈕時,使用者可能無法得知它們是在回答哪一個問題。
修正:使用 <fieldset> 和 <legend> 將問題與選項綁定。 正確作法是將問題和其相關選項一起包裝在 <fieldset> 中,並用 <legend> 來描述這組選項所對應的提問,例如:
<form>
<fieldset>
<legend>你有護照嗎?</legend>
<input type="radio" id="yes" name="passport" value="yes">
<label for="yes">有</label><br>
<input type="radio" id="no" name="passport" value="no">
<label for="no">沒有</label>
</fieldset>
</form>
修正後,螢幕閱讀器會將 <legend> 內容「你有護照嗎?」作為該單選按鈕群組的標題來讀,確保使用者在瀏覽選項時能同步得知問題的上下文。
錯誤 2:使用 <fieldset> 但缺少 <legend>
有時候開發者會記得用 <fieldset> 來分組,卻忘了在裡面加入 <legend> 標題。缺少 <legend> 的欄位集在視覺上會出現一個沒有標題的框架,而對螢幕閱讀器而言,這組欄位也沒有名稱描述,相當於建立了一個沒有意義的群組。
修正:補上有意義的 <legend>。 每當使用 <fieldset> 分區時,務必提供對應的 <legend> 作為該區域的說明文字。例如,若有一組欄位是輸入使用者的個人資料,就應在 <fieldset> 開頭添加 <legend>個人資料</legend> 或其他適當的標題,讓人一看(或讓輔助技術一讀)便能了解這組欄位的用途。
錯誤 3:不必要或巢狀的 <fieldset> 使用
另一個問題是過度使用 <fieldset>。例如,有人對每一個單獨欄位都各包一個 <fieldset>,這其實沒有必要,反而讓 HTML 結構變得冗長。還有些情況是將 <fieldset> 巢狀放置(在一個 <fieldset> 裡再嵌一個 <fieldset>),如前所述,巢狀群組會讓螢幕閱讀器難以判斷結構層次,使用者可能無法分辨群組的開始與結束。
修正:精簡分組並避免巢狀。 <fieldset> 應針對相關整組欄位使用,一個群組一個 <fieldset> 即可,沒必要每個欄位外面都包一層。對於只有單一欄位的輸入,直接使用 <label> 搭配適當的說明文字即可,無需多此一舉地額外再加 <fieldset>。而在確實需要多層次分組的罕見情況下,建議重新評估表單結構,將子群組拆分為多個獨立的 <fieldset>,各自使用 <legend> 標明,而不是透過巢狀 <fieldset> 來實現。