Learning Objectives
- 用 overflow 的 visible、hidden、scroll、auto 處理比盒子大的內容
- 用 white-space、overflow 與 text-overflow 讓過長的單行文字顯示刪節號
- 分辨 display: none、visibility: hidden、opacity: 0 對版面、操作與螢幕閱讀器的影響
- 用 object-fit 讓圖片在固定尺寸的框裡不變形
- 用 float 與 clear 做出文繞圖,並說明為什麼整頁排版改用 Flexbox 與 Grid
內容和盒子不一樣大的時候
固定大小的盒子遇上不固定長度的內容,是網頁最常見的排版問題:
| 狀況 | 這一課的工具 |
|---|---|
| 公告框高度固定,公告卻越寫越長,文字跑到框外面蓋住下面的內容 | overflow |
| 課程名稱太長,把卡片撐成兩三行 | text-overflow: ellipsis |
| 某些內容要暫時藏起來(答案、廣告、展開前的選單) | display、visibility、opacity |
| 照片比例和框不同,被壓扁或拉長 | object-fit |
| 想讓文字繞著圖片排 | float |
最後一項的 float 曾經是整頁排版的主要工具,這一課也會說明它為什麼被 Flexbox 取代。
overflow:內容超出盒子時怎麼辦
盒子設了固定的 height(或 width),內容又比盒子大,超出的部分叫做溢位(overflow)。
| 值 | 超出的內容 | 捲軸 |
|---|---|---|
visible(預設) |
照樣畫在盒子外面,可能蓋住下面的內容 | 沒有 |
hidden |
被裁掉,看不到 | 沒有(使用者沒辦法捲動) |
scroll |
被裁掉,可以捲動 | 一直顯示,就算內容沒有超出 |
auto |
被裁掉,可以捲動 | 只在超出時顯示 |
大多數情況用 auto:內容短的時候沒有多餘的捲軸。也可以只管一個方向:overflow-x、overflow-y,
例如寬的表格放在 overflow-x: auto 的容器裡,手機上可以左右捲動,整頁不會被撐寬。
用 hidden 要小心:被裁掉的內容使用者看不到也捲不到。重要的文字不要用 hidden 藏起來。
單行文字太長顯示刪節號,三個屬性缺一不可:
.title {
white-space: nowrap; /* 不換行,維持一行 */
overflow: hidden; /* 超出的部分裁掉 */
text-overflow: ellipsis; /* 被裁的地方顯示「…」 */
}
被截斷的文字最好有其他地方能看到完整內容(例如點進去的頁面),不要讓重要資訊只剩一半。
隱藏元素的三種方式
| 寫法 | 版面上的空間 | 能不能點、能不能用 Tab 移到它 | 螢幕閱讀器 |
|---|---|---|---|
display: none; |
不佔空間,後面的內容補上來 | 不能 | 讀不到 |
visibility: hidden; |
保留空間,只是看不到 | 不能 | 讀不到 |
opacity: 0; |
保留空間 | 可以(看不見卻點得到) | 讀得到 |
- 要整個拿掉(收起的選單、不適用的欄位):
display: none。HTML 的hidden屬性(<div hidden>)效果相同。 - 要藏起來但不讓版面跳動(例如答案揭曉前先佔好位置):
visibility: hidden。 opacity: 0只是「看不見」,元素還在:滑鼠點得到、鍵盤可以移過去、螢幕閱讀器照樣唸出來。 它常用在淡入淡出的動畫(第 22 課);動畫結束後若要真的隱藏,要再配合visibility: hidden或display: none。 用 opacity 0 藏一個按鈕,鍵盤使用者會移到一個看不見的東西上,不知道自己在哪裡。
另外有一種「畫面上看不到、螢幕閱讀器讀得到」的寫法,用在只給螢幕閱讀器的說明文字,第 24 課會介紹。
小測驗:溢位與隱藏
一個 height: 100px; overflow: hidden; 的盒子,裡面的文字有 300px 高。結果是?
寫了 overflow: hidden; text-overflow: ellipsis;,過長的課名卻換成兩行,沒有出現「…」。少了什麼?
想讓一段答案暫時看不到,但它的位置要空著保留,版面不要跳動,該用?
用 opacity: 0 把一個「刪除」按鈕藏起來,可能造成什麼問題?
object-fit:圖片在固定的框裡不變形
<img> 同時設了 width 與 height,而比例和原圖不同時,圖片預設會被拉伸填滿(object-fit: fill),人像會變胖或變瘦。
| object-fit | 效果 |
|---|---|
fill(預設) |
拉伸到剛好填滿,比例會變 |
cover |
保持比例、蓋滿整個框,超出的部分裁掉 |
contain |
保持比例、整張放進框裡,比例不同時留白 |
none |
維持原始大小,只顯示框裡的部分 |
.avatar {
width: 120px;
height: 120px;
object-fit: cover; /* 縮圖、頭像最常用 */
object-position: center; /* 裁切時保留哪一部分,預設就是中央 */
}
這和上一課的 background-size: cover、contain 是同一個概念:background-size 用在背景圖,object-fit 用在 <img>、<video> 這類元素。
float 與 clear:文繞圖
float: left(或 right)把元素推到父元素的左邊(右邊),後面的文字會繞著它排,就像報紙的文繞圖:
.cover { float: left; margin-right: 12px; } /* 圖片靠左,文字在右邊繞著排 */
.next { clear: both; } /* 這個元素不繞圖,從浮動元素的下方開始 */
- 浮動元素離開一般流,但旁邊的文字會避開它;
clear: left、right、both讓某個元素不再繞著它。 - 父元素裡只有浮動的子元素時,父元素的高度不會把它們算進去,可能變成 0,背景與邊框都縮成一條線。
在父元素加
display: flow-root;就會把浮動的子元素包進來。
在 Flexbox 出現之前,網頁的多欄排版(側邊欄、一排卡片)幾乎都靠 float,再加上一堆 clear 與修正高度的技巧,很容易出錯。 現在:文繞圖用 float,整頁與元件的排版用 Flexbox 和 Grid(第 17~20 課)。看到舊網站的原始碼滿是 float,就是那個時代留下來的寫法。
小測驗:object-fit 與 float
一張 600×300 的圖片,設定 width: 120px; height: 120px; object-fit: cover;。結果是?
圖片設了 float: left,後面的標題也繞著圖片排在右邊。想讓標題從圖片下方開始,該怎麼做?
一個有邊框的 <div> 裡只有兩張 float: left 的圖片,結果邊框縮成一條線。原因是?
重點整理
overflow:visible(預設,溢出到外面)、hidden(裁掉、不能捲)、scroll(一直有捲軸)、auto(需要時才有捲軸)。- 單行刪節號:
white-space: nowrap+overflow: hidden+text-overflow: ellipsis。 - 隱藏:
display: none不佔空間、讀不到;visibility: hidden保留空間、讀不到;opacity: 0只是看不見,還能點、還讀得到。 object-fit: cover讓圖片在固定的框裡保持比例、裁切填滿;contain整張放進去。float做文繞圖,clear讓後面的元素從浮動元素下方開始;父元素用display: flow-root包住浮動的子元素。- 整頁與元件的排版不再用 float,改用 Flexbox 與 Grid。
下一課開始 Flexbox:用主軸與交叉軸的概念,一行 CSS 就能把一排元素排整齊、垂直置中。