深入理解 CSS 中的溢出問題
大家好,我是CUGGZ。又到周五啦,提前祝大家周末愉快!今天來看看導致 CSS 溢出問題的原因以及該如何修復它們。
一、什么是溢出問題?
在平時開發中,我們可能會遇到水平滾動條的問題,尤其是在移動設備上。因為滾動條問題的原因有很多,所以沒有直截了當的解決方案。有些問題可以很快解決,有些需要一點調試技巧。、
那什么是溢出問題呢?當水平滾動條無意中出現在網頁上,允許用戶水平滾動時,就會出現溢出問題,它可能由不同的原因導致。
二、如何發現溢出問題?
下面來看看發現溢出問題的常用方法。
1. 向左或向右滾動
第一種方法是水平滾動頁面。如果能夠滾動,那就說明頁面有問題。
2. 使用 JavaScript 查找比正文更寬的元素
我們可以在瀏覽器控制臺添加如下代碼片段,來顯示比主體更寬的元素。這對于包含大量元素的頁面來說是很方便的。
var docWidth = document.documentElement.offsetWidth;
[].forEach.call(
document.querySelectorAll('*'),
function(el) {
if (el.offsetWidth > docWidth) {
console.log(el);
}
}
);
3. 使用CSS outline屬性
我們可以將CSS的outline屬性添加到頁面上的所有元素,這樣就可以看到哪些元素發生了溢出。
也可以將以下JavaScript代碼片段添加到瀏覽器的控制臺中,以給頁面上每個元素添加隨機顏色的outline。
[].forEach.call($$("*"),function(a){a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)})
效果如下:
這樣就能輕松看出頁面上哪個元素發生了溢出。
4. Firfox 中的溢出標簽
Firefox 有一個很有用的功能,可以告訴我們哪些元素發生了溢出。
5. 刪除頁面元素
另一種常見的方法是打開瀏覽器的DevTools,開始逐個刪除頁面元素。一旦問題消失,那么剛剛刪除的部分可能就是導致溢出問題的原因。我這種方法在你發現問題但不知道為什么會發生的情況下是很有用的。
三、常見的溢出問題
1. 固定寬度元素
溢出的最常見原因之一是固定寬度的元素。一般來說,不要固定會在多個視口大小下顯示的元素的寬度。
.element {
width: 400px;
}
2. Flex 布局
在使用 Flexbox 布局時,當沒有可用空間時,如果不允許項目換行,那么就可能會發生溢出。
.parent {
display: flex;
flex-wrap: wrap;
}
在這里,如果空間不足以將它們全部放在一行中,Flex 布局的項目就會導致水平溢出:
當 flex 的父對象需要在不同的視口大小下顯示時,確保使用 flex-wrap: wrap
.parent {
display: flex;
flex-wrap: wrap;
}
3. Grid 布局
在使用CSS grid 布局時,響應式設計是很重要。以下面代碼為例:
.wrapper {
display: grid;
grid-template-columns: 1fr 300px 1fr;
grid-gap: 1rem;
}
如果視口小于300px,上面的示例將是有效的。否則就會發生溢出。
為了避免這樣的問題,只有在有足夠的可用空間時才使用 grid 布局。我們可以使用如下 CSS 媒體查詢:
.wrapper {
display: grid;
grid-template-columns: 1fr;
grid-gap: 1rem;
}
@media (min-width: 400px) {
.wrapper {
grid-template-columns: 1fr 300px 1fr;
}
}
4. 長單詞
溢出的另一個常見原因是不適合視口寬度的長單詞。由于視口的寬度,這種情況在移動設備上發生得更多。
要解決這個問題,我們需要使用 overflow-wrap 屬性:
.article-content p {
overflow-wrap: break-word;
}
此修復對于用戶輸入的內容特別有用。一個常見的例子就是評論內容,用戶可能會在評論中粘貼一個很長的 URL,我們就應該通過 overflow-wrap 屬性來處理。
5. CSS Flex 中的最小內容大小
另一個導致溢出的原因是 Flexbox 中的最小內容大小。這是什么意思?
默認情況下,Flex 項目不會縮小到其最小內容大小(最長單詞或固定大小元素的長度)以下。要更改此設置,需要設置 min-width 或者 min-height 屬性。
為了解決這個問題,我們可以使用visible之外的 overflow 值,或者在flex項上設置min-width:0
.card__name {
min-width: 0;
overflow-wrap: break-word;
}
6. CSS Grid 中的最小內容大小
與 Flexbox一樣,CSS grid 布局的也有最小內容大小的概念。但是,解決方案有所不同。
假設有一個帶有側邊的 wrapper 和一個帶有 CSS grid 的 section。
.wrapper {
display: grid;
grid-template-columns: 248px 1fr;
grid-gap: 40px;
}
此外,在 section 有一個滾動部分,這里使用了flexbox。
.section {
display: flex;
gap: 1rem;
overflow-x: auto;
}
這里沒有添加flex-wrap,因為希望 flex 項目位于同一行。然而,這并沒有起作用,卻導致了水平溢出。
我們需要使用 minmax() 來代替 1fr,這樣,主元素的最小內容大小就不會是 auto 了。
.wrapper {
display: grid;
grid-template-columns: 248px minmax(0, 1fr);
grid-gap: 40px;
}
7. 負邊距
位于屏幕外的元素可能會導致溢出。通常,這是因為元素的外邊距為負。在下面的示例中,我們有一個帶有負邊距的元素,文檔的語言是英語(即從左到右)。
.element {
position: absolute;
right: -100px;
}
有趣的是,當元素定位在左側時,就沒有發生溢出。這是為什么?
根據 CSS 規范:
UAs 必須在框的 block-start 和 inline-start 側剪切滾動容器的可滾動溢出區域。
對于英文文檔,inline-start 側是左側,因此位于左側屏幕外的任何元素都將被剪裁,因此不會溢出。
如果確實需要將元素放置在屏幕外,請確保將 overflow: hidden 應用于父元素以避免任何溢出。
8. 沒有設置 max-width 的圖片
如果你不提前處理大圖像,就可能會看到溢出。確保在所有圖像上設置 max-width: 100%
img {
max-width: 100%;
}
9. 視口單位
使用 100vw 有一個缺點,那就是當滾動條可見時,它可能會導致溢出。在macOS上,100vw 不會導致水平滾動。
在 Windows 上,默認情況下滾動條總是可見的,因此會發生溢出。
這是因為當值為100vw時,用戶不知道瀏覽器垂直滾動條的寬度。因此,寬度將等于100vw加上滾動條的寬度。然而,對此 CSS 并沒有解決方案去修復它。
我們可以使用 JavaScript 來計算視口的寬度,不包括滾動條。
function handleFullWidthSizing() {
const scrollbarWidth = window.innerWidth - document.body.clientWidth
document.querySelector('myElement').style.width = `calc(100vw - ${scrollbarWidth}px)`
}
原文:https://www.smashingmagazine.com/2021/04/css-overflow-issues/
作者:Ahmad Shadeed
譯者:CUGGZ