健壯的 CSS

前言

Ahmad Shadeed 的原創(chuàng)文章 Defensive CSS 非常的干貨和實(shí)用,在你每次動(dòng)鍵盤寫 CSS 之前,都應(yīng)該把它拿出來溫習(xí)一遍,作為你寫 CSS 的指導(dǎo)。

如果你沒有把這些作為寫 CSS 的指導(dǎo),雖然完成業(yè)務(wù)需求,但你就像造人的上帝,只造了骨架沒有填充血液,人面對(duì)龐雜的世間,難免跑蹦跳,摔了是需要肉來減震的,只有一副骨架豈不分分鐘散架了。

業(yè)務(wù)往往是最理想的 CSS 運(yùn)行環(huán)境,部署到服務(wù)器面對(duì)復(fù)雜的網(wǎng)絡(luò)環(huán)境,我們對(duì) CSS 的要求,就像生活對(duì)人的要求,一個(gè)健壯完整的人才能承載生活的苦難,而只有健壯 CSS 才能面對(duì)復(fù)雜的網(wǎng)絡(luò)環(huán)境。

間距(Spacing)

我們開發(fā)人員需要考慮不同的內(nèi)容長(zhǎng)度。這意味著,即使看起來不需要,也應(yīng)該向組件添加間距。

image

在上圖示中,左側(cè)有一個(gè)標(biāo)題右側(cè)一個(gè)操作按鈕。目前,看起來還可以。但是讓我們看看當(dāng)標(biāo)題更長(zhǎng)時(shí)會(huì)發(fā)生什么。

image

注意到文本離操作按鈕太近了嗎?您可能正在考慮換行展示,這個(gè)我們先不討論?,F(xiàn)在,讓我們關(guān)注間距。

如果你讓標(biāo)題有間距同時(shí)文本截?cái)?,我們不?huì)看到這樣的問題。

.section__title {
    margin-right: 1rem;
}

對(duì)于這個(gè)組件,標(biāo)題可以是一個(gè)詞或多個(gè)詞,甚至是一個(gè)長(zhǎng)句子。為避免標(biāo)題卡在右側(cè)的圖標(biāo)上,最好添加margin-right: 1rem,以防標(biāo)題變長(zhǎng)。

image

說到文本溢出截?cái)?,還有一個(gè)最常見的就是——長(zhǎng)內(nèi)容。

長(zhǎng)內(nèi)容(Long Content)

在構(gòu)建布局時(shí)考慮長(zhǎng)內(nèi)容很重要。正如您在前面看到的,部分標(biāo)題過長(zhǎng)時(shí)會(huì)被截?cái)啵?dāng)然你也可以換行。

這是一個(gè)人名列表,現(xiàn)在看起來很完美。

image

但是,由于這是用戶生成的內(nèi)容,因此我們需要注意如何防御布局,以防萬一太長(zhǎng)。

見下圖:

image

在這樣的布局中,一致性很重要。為了實(shí)現(xiàn)這一點(diǎn),我們可以簡(jiǎn)單地通過 usingtext-overflow和它的朋友來截?cái)嗝Q。

.username {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
image

提示,當(dāng)文本截?cái)嗟臅r(shí)候千萬不要忘了處理提示,不然用戶怎么看到全部?jī)?nèi)容來。

如果您有興趣提高處理 CSS 中長(zhǎng)內(nèi)容的技能,我寫了一篇關(guān)于該主題的詳細(xì)文章。

卡片上的文字(category tag)

還有一個(gè)長(zhǎng)文本的例子:

對(duì)于卡片組件,您可能需要一個(gè)類別標(biāo)簽。您將如何處理內(nèi)容的不同變化?考慮下圖。

image

右邊的卡片有一個(gè)很長(zhǎng)的標(biāo)題,這看起來不太好,因?yàn)樗采w了縮略圖的很大一部分。對(duì)于食品網(wǎng)站,圖像非常重要。

這里有一些可能的解決方案,以防萬一標(biāo)簽變得更長(zhǎng)。

image

第一個(gè)解決方案是使用文本截?cái)嗉夹g(shù),max-width在 CSS 中使用 a 。第二個(gè)只使用max-width,但如果標(biāo)簽有很長(zhǎng)的文本,它可能會(huì)失敗。

.tag {
  max-width: 6.25rem;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

按鈕(Buttons)

image

在某些情況下,您需要并排放置兩個(gè)按鈕。我們?nèi)绾谓忉屵@種情況,而不margin默認(rèn)添加按鈕?

多虧了相鄰兄弟組合器,讓這很容易做到。它是說:“如果一個(gè)按鈕與另一個(gè)按鈕相鄰,則為第二個(gè)按鈕添加一個(gè)左邊距,以防萬一”。

.button + .button {
  margin-left: 1rem;
}

可滾動(dòng)元素(Scrollable Element)

overflow 可拆分為 overflow-x 和 overflow-y 兩者默認(rèn)都是 visible,也就是說當(dāng)內(nèi)容溢出盒子不會(huì)產(chǎn)品滾動(dòng)條。

當(dāng)您需要使元素可滾動(dòng)時(shí),可能很想執(zhí)行以下操作:

.element {
  height: 20rem;
  overflow-y: scroll;
}
image

這種方法的問題在于它會(huì)始終顯示 scrollbar,即使內(nèi)容不夠長(zhǎng)無法滾動(dòng)。最好是使用auto關(guān)鍵字。這樣,它可以通過以防萬一的概念。

.element {
  height: 20rem;
  overflow-y: auto;
}

圖片上的文字(HTML Image Fallback)

如果您用 <img> 來展示圖片,而圖片上有文字內(nèi)容,但圖片可能由于某種原因無法加載。在這種情況下,如果有后備怎么辦?

image
img {
  background-color: #525252;
}

以防萬一圖像無法加載,background-color它將作為后備。

頭像圖片(Avatar Image)

這是一個(gè)非常常見的用例,其中頭像可能看起來被拉伸壓縮。
年度人氣創(chuàng)作者榜單:

可以通過使用來避免object-fit: cover。它將充當(dāng)以防萬一的事情。沒有它,圖像會(huì)看起來很糟糕。

掘金的 2021 最佳創(chuàng)作者活動(dòng)就是一個(gè)例子:

圖片最大寬度(Image maximum width)

防止圖片被拉伸,作為一般規(guī)則,不要忘記設(shè)置max-width: 100%所有圖像。這可以添加到您使用的 CSS 重置中。

img {
    max-width: 100%;
    object-fit: cover;
}

flex 布局換行(Flexbox Wrapping)

CSS flexbox 是當(dāng)今最有用的 CSS 布局功能之一。

添加display: flex 布局在而是以世界已經(jīng)是常見操作,但問題是當(dāng)空間不足時(shí),默認(rèn)情況下這些子項(xiàng)不會(huì)換行。我們需要使用 flex-wrap: wrap。

這是一個(gè)典型的例子。我們有一組應(yīng)該并排顯示的選項(xiàng)。

.options-list {
    display: flex;
}
image

當(dāng)空間較少時(shí),將發(fā)生水平滾動(dòng)。這應(yīng)該是意料之中的,實(shí)際上并不是一個(gè)“問題”。

image

請(qǐng)注意這些項(xiàng)目如何仍然彼此相鄰。為了解決這個(gè)問題,我們需要允許 flex wrapping。

.options-list {
    display: flex;
    flex-wrap: wrap;
}
image

使用 flexbox 時(shí)的一般經(jīng)驗(yàn)法則是允許換行,除非您想要滾動(dòng),但那是另一回事,所以盡量使用flex-wrap以避免意外的布局行為(在我們的例子中是水平滾動(dòng))。

鎖定滾動(dòng)鏈接(Lock scroll chaining)

您是否曾經(jīng)打開一個(gè)模態(tài)并開始滾動(dòng),然后當(dāng)您到達(dá)末尾并繼續(xù)滾動(dòng)時(shí),模態(tài)下方的內(nèi)容(主體元素)會(huì)滾動(dòng)?這稱為滾動(dòng)鏈接。

在過去的幾年里,有一些技巧可以使這項(xiàng)工作發(fā)揮作用,但是現(xiàn)在,由于overscroll-behaviorCSS 屬性,我們只能使用 CSS 來做到這一點(diǎn)。

在下圖中,您會(huì)看到默認(rèn)的滾動(dòng)鏈接行為。

image

為了提前避免這種情況,我們可以將其添加到任何需要滾動(dòng)的組件(例如:聊天組件、移動(dòng)菜單等)。這個(gè)屬性的好處是它在滾動(dòng)之前不會(huì)產(chǎn)生影響。

.modal__content {
    overscroll-behavior-y: contain;
    overflow-y: auto;
}
image

如果您想了解更多信息,我寫了一篇詳細(xì)的文章

CSS 變量的默認(rèn)值(CSS Variable Fallback)

CSS 變量在網(wǎng)頁設(shè)計(jì)中得到越來越多的使用。我們可以應(yīng)用一種方法以不破壞體驗(yàn)的方式使用它們,以防 CSS 變量值由于某種原因?yàn)榭铡?/p>

這在通過 Javascript 提供 CSS 變量的值時(shí)特別有用。下面是一個(gè)例子:

.message__bubble {
    max-width: calc(100% - var(--actions-width));
}

該變量--actions-width正在calc()函數(shù)中使用,其值來自 Javascript。讓我們假設(shè) Javascript 由于某種原因失敗了,會(huì)發(fā)生什么?在max-width將計(jì)算到none。

我們可以提前避免這種情況,并向var().

.message__bubble {
    max-width: calc(100% - var(--actions-width, 70px));
}

這樣,如果未定義變量,則將使用回退 ( 70px)。如果變量可能失敗(例如:來自 Javascript),則可以使用此方法。否則,它是不需要的。

使用固定寬度或高度(Using fixed width or height)

破壞布局的常見事情之一是對(duì)具有不同長(zhǎng)度內(nèi)容的元素使用固定寬度或高度。

固定高度(The fixed height)

我經(jīng)??吹揭粋€(gè)固定高度的部分和大于該高度的內(nèi)容,這導(dǎo)致布局損壞。不知道這看起來如何?

.hero {
    height: 350px;
}
image

為了避免內(nèi)容溢出,我們需要使用 min-height 代替 height。

.hero {
    min-height: 350px;
}
image

這樣,如果內(nèi)容變大,布局就不會(huì)中斷。

固定寬度(The fixed with)

您是否見過標(biāo)簽離左右邊緣太近的按鈕?這是由于使用了固定寬度。

.button {
    width: 100px;
}

如果按鈕的標(biāo)簽長(zhǎng)于100px,它將靠近邊緣。如果太長(zhǎng),文本會(huì)漏出來。這不好!

image

為了解決這個(gè)問題,我們可以簡(jiǎn)單地替換widthmin-width.

.button {
    min-width: 100px;
}

忘記 Background-Repeat(Forgetting background-repeat

通常,當(dāng)使用一張大圖作為背景時(shí),我們往往會(huì)忘記考慮在大屏幕上查看設(shè)計(jì)的情況。默認(rèn)情況下,該背景將重復(fù)

這在筆記本電腦屏幕上通??床坏剑谳^大的屏幕上可以清楚地看到。

image

為了提前避免這種行為,請(qǐng)確保重置background-repeat。

.hero {
    background-image: url('..');
    background-repeat: no-repeat;
}

使用 Justify-Content: Space-Between(Using justify-content: space-between)

在 flex 容器中,您可能會(huì)使用justify-content將子項(xiàng)彼此隔開。使用一定數(shù)量的子項(xiàng),布局看起來不錯(cuò)。但是,當(dāng)它們?cè)黾踊驕p少時(shí),布局會(huì)看起來很奇怪。

考慮以下示例。

image

我們有一個(gè)包含四個(gè)項(xiàng)目的 flex 容器。每個(gè)項(xiàng)目之間的間距不是gapmargin,它在那里是因?yàn)槿萜饔?code>justify-content: space-between.

.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

當(dāng)項(xiàng)目數(shù)少于四個(gè)時(shí),將發(fā)生以下情況。

image

這不好。對(duì)此有不同的解決方案:

  • margin
  • flex gap(謹(jǐn)慎使用)
  • Padding(可以應(yīng)用于每個(gè)子元素的父元素)
  • 添加空元素作為間隔。

為簡(jiǎn)單起見,我將使用gap.

.wrapper {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
image

小心使用 CSS 網(wǎng)格中的固定值(Be careful with fixed values in a CSS grid)

假設(shè)我們有一個(gè)包含 aside 和 main 的網(wǎng)格。CSS 看起來像這樣:

.wrapper {
    display: grid;
    grid-template-columns: 250px 1fr;
    gap: 1rem;
}

由于空間不足,這將在小視口尺寸上中斷。為避免此類問題,請(qǐng)?jiān)谑褂蒙鲜?CSS 網(wǎng)格時(shí)始終使用媒體查詢。

@media (min-width: 600px) {
    .wrapper {
        display: grid;
        grid-template-columns: 250px 1fr;
        gap: 1rem;
    }
}

滾動(dòng)條槽(Scrollbar Gutter)

與滾動(dòng)相關(guān)的另一件事是scrollbar gutter。以前面的例子為例,當(dāng)內(nèi)容變長(zhǎng)時(shí),添加滾動(dòng)條會(huì)導(dǎo)致布局偏移,發(fā)生布局偏移的原因是為滾動(dòng)條占用布局寬度。

考慮下圖。

image

請(qǐng)注意當(dāng)內(nèi)容因顯示滾動(dòng)條而變長(zhǎng)時(shí)如何移動(dòng)。我們可以通過使用scrollbar-gutter屬性來避免這種行為,滾動(dòng)條不占用布局寬度,可以理解為滾動(dòng)條槽變?yōu)楦?dòng)。

.element {
    scrollbar-gutter: stable;
}
image

兼容不太好,作為增強(qiáng)屬性可以:

CSS Flexbox 中的最小內(nèi)容大?。∕inimum content size in CSS flexbox)

下面的例子省略了細(xì)節(jié),可以看這個(gè)我講的案例 讓 overflow-wrap 失效的 flex-wrap,更好理解。

如果一個(gè) flex 項(xiàng)目有一個(gè)文本元素或一個(gè)比項(xiàng)目本身長(zhǎng)的圖像,瀏覽器不會(huì)縮小它們。這是 flexbox 的默認(rèn)行為。

考慮以下示例。

.card {
    display: flex;
}

當(dāng)標(biāo)題有一個(gè)很長(zhǎng)的詞時(shí),它不會(huì)換行。

image

即使我們使用overflow-wrap: break-word,它也不起作用。

.card__title {
    overflow-wrap: break-word;
}

要更改該默認(rèn)行為,我們需要min-width將 flex 項(xiàng)的 設(shè)置為0。那是因?yàn)?code>min-width默認(rèn)值是auto,就會(huì)發(fā)生溢出。

.card__title {
    overflow-wrap: break-word;
    min-width: 0;
}

同樣的事情適用于列 flex 包裝器,但我們將使用它min-height: 0

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,189評(píng)論 1 92
  • 盒子模型(CSS重點(diǎn)) 其實(shí),CSS就三個(gè)大模塊: 盒子模型 、 浮動(dòng) 、 定位,其余的都是細(xì)節(jié)。要求這三部分,...
    xlystar閱讀 2,034評(píng)論 0 1
  • 1.實(shí)現(xiàn)不使用 border 畫出 1px 高的線,在不同瀏覽器的標(biāo)準(zhǔn)模式與兼容模式下都能保持一致的效果。 2.介...
    蒙面超人zrh閱讀 441評(píng)論 0 1
  • 學(xué)會(huì)使用CSS選擇器熟記CSS樣式和外觀屬性熟練掌握CSS各種選擇器熟練掌握CSS各種選擇器熟練掌握CSS三種顯示...
    七彩小鹿閱讀 6,446評(píng)論 2 66
  • 課程目標(biāo): 學(xué)會(huì)使用CSS選擇器熟記CSS樣式和外觀屬性熟練掌握CSS各種選擇器熟練掌握CSS各種選擇器熟練掌握C...
    桃花蘭島主閱讀 612評(píng)論 0 1

友情鏈接更多精彩內(nèi)容