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


2013-11-05 13:29:04




