防禦式CSS是什麼?這幾點屬性重點防禦!

前端小智發表於2022-01-31
作者:Ahmad Shadeed
譯者:前端小智
來源:ishadeed

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

很多時候,我們希望有一種方法可以避免某種CSS問題或行為的發生。我們知道,網頁內容是動態的,網頁上的東西可以改變,從而增加了出現CSS問題或奇怪行為的可能性。

防禦式 CSS是一個片段的集合,可以幫助我編寫受保護的CSS。換句話說,就是將來會有更bug出現。

1.Flexbox 包裹

CSS flexbox 是目前最有用的CSS佈局功能之一。在一個包裝器上新增 display: flex,讓子項挨著排序。

問題是,當空間不足時,那些子項預設不會被包裹成一個新的行。我們需要用 flex-wrap: wrap 來改變這一行為。

下面是一個典型的例子。

.options-list {
    display: flex;
}

當空間較少時,會出現水平滾動。這應該是預料之中的,實際上並不是一個 "問題"。

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

使用flexbox時,一般的經驗法則是允許包裹,除非你想要一個滾動的包裹。這是另一回事,但儘量使用 flex-wrap 來避免意外的佈局行為(在我們的例子中,是水平滾動)。

2.間距

我們開發者需要考慮不同的內容長度。這意味著,間距應該新增到元件中,即使它看起來不需要。

在這個例子中,我們在右邊有一個section標題和一個操作按鈕。目前,它看起來還不錯。但是,如果標題再長一些,會發生什麼呢?

注意到文字太靠近按鈕了嗎?這裡,你可能會考慮多行換行,但現在,我們先關注距。

如果標題有空格和文字截斷,我們不會看到這樣的問題。

.section__title {
    margin-right: 1rem;
}

3.長內容

在構建佈局時,考慮到長的內容是很重要的。正如你在前面所看到的,當章節的標題太長時就會被截斷。這是可選的,但對於某些UI來說,考慮到這一點很重要。

對我來說,這是一種防禦性的CSS方法。在 "問題 "真正發生之前就去解決它,這很好。

這裡有一份人名清單,現在看起來很完美

然而,由於這是使用者生成的內容,我們需要小心如何防禦佈局,以防某些內容太長。請看下圖:

在這種佈局中,一致性非常重要。為了實現這一點,我們可以使用 text-overflow和它的好友來簡單地截斷名稱。

4. 防止影像被拉伸或壓縮

在無法控制圖片高寬比的情況下,如果使用者上傳的圖片與高寬比不符,最好提前考慮並提供解決方案。

在下面的例子中,我們有一個帶有照片的卡片元件。它看起來不錯。

當使用者上傳一個不同大小的影像時,它將被拉伸。這可不是什麼好事。看看影像是如何被拉伸的!

最簡單的修復方法是使用CSS object-fit

.card__thumb {
    object-fit: cover;
}

在專案層面上,我傾向於為所有影像新增 object-fit,以避免出現意外的結果。

5.鎖定滾動連結

你是否曾經開啟一個模態並開始滾動,然後當你到達終點並繼續滾動時,模態下面的內容(主體元素)會滾動?這就是所謂的滾動鏈。

預設情況下,當觸及頁面頂部或者底部時(或者是其他可滾動區域),移動端瀏覽器傾向於提供一種“觸底”效果,甚至進行頁面重新整理。你可能也發現了,當對話方塊中含有可滾動內容時,一旦滾動至對話方塊的邊界,對話方塊下方的頁面內容也開始滾動了——這被稱為“滾動鏈”。 。

在過去的幾年裡,有一些黑科技來實現這一點,但現在,我們只需要使用CSS 即可,這要感謝overscroll-behavior CSS屬性。

在下面的圖中,可以看到預設的滾動連結行為。

為了提前避免這種情況,我們可以將其新增到任何需要滾動的元件中(例如:聊天元件、移動選單...等)。這個屬性的好處是,在有滾動之前,它不會產生影響。

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

6. CSS變數回退

CSS變數在網頁設計中得到了越來越多的應用。我們可以應用一種方法,在CSS變數值因某種原因為空的情況下,以一種不破壞體驗的方式使用它們。

通過 JS 輸入CSS變數的值時特別有用。下面是一個例子:

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

變數 --actions-widthcalc() 函式中被使用,其值來自 JS。假設 JS 由於某種原因失敗了,會發生什麼?max-width 會被計算為零。

我們可以提前避免這種情況,在 var() 中新增一個回退值。

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

這樣,如果變數沒有定義,就會使用回退 (70px)。這種方法可以在變數可能失敗的情況下使用。

7.使用固定寬度或高度

破壞佈局的常見情況之一是對一個有不同長度內容的元素使用固定的寬度或高度。

固定高度

我經常看到主內容部分有固定的高度,而內容卻大於這個高度,這就導致了佈局的破壞。如下所示:

.main {
    height: 350px;
}

為了避免這種情況出現,可以使用 min-height 代替 height:

固定寬度

你有沒有見過按鈕,它的標籤離左右邊緣太近?這是由於使用了固定寬度。

.button {
    width: 100px;
}

如果按鈕的標籤大於100px,它將靠近邊緣。如果它太長,文字會洩露出來。這是不好的!

為了解決這個問題,我們可以簡單地用 min-width 代替 width

.button {
    min-width: 100px;
}

8.忘記 background-Repeat

很多時候,當使用一張大的圖片作為背景時,我們往往會忘記考慮設計在大螢幕上觀看時的情況。該背景將預設重複。

這在筆記本螢幕上大多不會看到,但在大螢幕上很常見。

為了提前避免這種行為,請確保使用重置 background-repeat

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

9.垂直媒體查詢

有時,我們很想建立一個元件,只通過調整瀏覽器的寬度進行測試。根據瀏覽器的高度進行測試可以發現一些有趣的問題。

這裡有一個我見過多次的例子。我們有一個帶有主要和次要連結元件。次要連結應該位於旁白部分的最底部。

考慮一下下面的例子。主導航和次導航看起來還不錯。在我看到的這個例子中,開發者給二級導航新增了 position: sticky,這樣它就可以粘在底部了。

然而,如果瀏覽器的高度較小,bug 就來了。注意這兩個導航是如何重疊的。

通過使用CSS垂直媒體查詢,我們可以避免這個問題。

@media (min-height: 600px) {
    .aside__secondary {
        position: sticky;
        bottom: 0;
    }
}

這樣,只有當視口高度大於或等於600px 時,二級導航才會被粘在底部。好多了,對嗎?

可能有更好的方法來實現這一行為(比如使用 margin-auto),但在這個例子中專注於垂直查詢。

10. 使用 justify-content:space-between

在一個 flex 的容器中,我們可能會使用 justify-content 來使子專案之間有一定的間距。如果有一定數量的子專案,佈局看起來會很好。然而,當它們增加或減少時,佈局會看起來很奇怪。

考慮以下例子:

我們有一個有四個專案的 flex 容器。每個專案之間的間距不是 gapmargin,它之所以存在是因為容器有 justify-content: space-between

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

當專案的數量少於4個時,將發生以下情況:

這並不是好事。對此有不同的解決方案:

  • margin
  • flexbox gap(謹慎使用)
  • padding(可應用於每個子元素的父元素)
  • 增加空的元素,作為間隔。

為了簡單起見,我使用 gap

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

11. 圖片上的文字

當在圖片上放置文字時,必須考慮到影像無法載入的情況。文字會是什麼樣子。下面是一個例子:

文字看起來是可讀的,但當影像載入失敗時,它的可讀性變得很差。

我們通過給<img>元素新增一個背景色來輕鬆解決這個問題。這個背景只有在圖片載入失敗時才會顯示出來。

12.小心CSS網格中的固定值

假設我們有一個包含asidemain的網格。CSS看起來是這樣的:

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

由於缺乏空間,這在小的視口尺寸上會出現問題。為了避免這樣的問題,在使用上述CSS網格時,一定要使用媒體查詢。

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

13.只在需要的時候顯示滾動條

我們可以控制顯示滾動條或不只是在有很長的內容的情況下。儘管如此,強烈建議使用auto作為overflow的值。考慮以下例子:

請注意,即使內容很短,也有一個滾動條可見。這對一個使用者介面來說並不是好事。作為使用者,在不需要滾動條的情況下看到滾動條是很混亂的。

.element {
    overflow-y: auto;
}

使用overflow-y: auto,滾動條只有在內容較長時才可見。否則,它就不顯示。

14.Scrollbar Gutter

另一件與滾動有關的事情是 Scrollbar Gutter。以前面的例子為例,當內容變長時,增加一個滾動條會導致佈局的轉移。佈局移動發生的原因是為滾動條保留了一個空間。

Scrollbar Gutter 是內邊框邊緣和外填充邊緣之間的空間。 對於經典滾動條,Scrollbar Gutter 的大小與滾動條的寬度相同。 這些滾動條通常是不透明的,並從相鄰的內容中佔用一些空間。

請看下圖:

請注意,由於顯示了滾動條,當內容變長時,它是如何移位的。我們可以通過使用scrollbar-gutter屬性來避免這種行為。

.element {
    scrollbar-gutter: stable;
}

15. CSS Flexbox中的最小內容尺寸

如果一個 flex 專案中的文字元素或影像大於或長於該專案本身,瀏覽器就不會縮小它們。這是Flexbox 的預設行為。考慮以下例子:

.card {
    display: flex;
}

當標題有一個很長的詞時,它不會被包成一個新行。

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

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

要改變這種預設行為,我們需要將 flex 專案的 min-width 設定為 0。 這是因為 min-width 的預設值是 auto,溢位會發生。

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

同樣也適用於 flex-direction:column 佈局,對應的使用 min-height: 0

16. CSS網格中的最小內容尺寸

與flexbox類似,CSS grid對其子專案有一個預設的最小內容尺寸,即auto。這意味著,如果有一個元素比網格項大,它將溢位。

在上面的例子中,我們在主部分中有一個 carousel

<div class="wrapper">
    <main>
        <section class="carousel"></section>
    </main>
    <aside></aside>
</div>
@media (min-width: 1020px) {
    .wrapper {
        display: grid;
        grid-template-columns: 1fr 248px;
        grid-gap: 40px;
    }
}

.carousel {
    display: flex;
    overflow-x: auto;
}

由於 carousel是一個 flex 佈局,當內容超出時,預設是不會換行的,所以會出現水平滾動的。

為了解決這個問題,我們有三種不同的解決方:

  • 使用 minmax()
  • min-width 應用於網格專案
  • 在網路中新增 overflow: hidden

作為一種防禦性的CSS機制,我會選擇第一種,即使用 minmax() 函式。

@media (min-width: 1020px) {
    .wrapper {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 248px;
        grid-gap: 40px;
    }
}

  1. Auto Fit Vs Auto Fill

在使用CSS網格 minmax() 函式時,決定使用 auto-fit 還是 auto-fill 的關鍵字很重要。一旦使用不當,會導致意外的結果。

當使用minmax()函式時,auto-fit關鍵字將擴充套件網格專案以填補可用空間。而auto-fill將保留可用的空間,而不改變網格項的寬度。

也就是說,使用auto-fit可能會導致網格專案太寬,特別是當它們小於預期時。考慮一下下面的例子。


編輯中可能存在的bug沒法實時知道,事後為了解決這些bug,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原諒:https://ishadeed.com/article/...

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章