防御式CSS是什么?這幾點屬性重點防御
很多時候,我們希望有一種方法可以避免某種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. 防止圖像被拉伸或壓縮
在無法控制圖片高寬比的情況下,如果用戶上傳的圖片與高寬比不符,最好提前考慮并提供解決方案。
在下面的例子中,我們有一個帶有照片的卡片組件。它看起來不錯。
當用戶上傳一個不同大小的圖像時,它將被拉伸。這可不是什么好事??纯磮D像是如何被拉伸的!
最簡單的修復方法是使用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-width 在 calc() 函數中被使用,其值來自 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 容器。每個項目之間的間距不是 gap 或 margin,它之所以存在是因為容器有 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. 圖片上的文字
當在圖片上放置文本時,必須考慮到圖像無法加載的情況。文本會是什么樣子。下面是一個例子:
文本看起來是可讀的,但當圖像加載失敗時,它的可讀性變得很差。
我們通過給元素添加一個背景色來輕松解決這個問題。這個背景只有在圖片加載失敗時才會顯示出來。
12.小心CSS網格中的固定值
假設我們有一個包含aside和main的網格。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;
}
}
Auto Fit Vs Auto Fill
在使用CSS網格 minmax() 函數時,決定使用 auto-fit 還是 auto-fill 的關鍵字很重要。一旦使用不當,會導致意外的結果。
當使用minmax()函數時,auto-fit關鍵字將擴展網格項目以填補可用空間。而auto-fill將保留可用的空間,而不改變網格項的寬度。
也就是說,使用auto-fit可能會導致網格項目太寬,特別是當它們小于預期時??紤]一下下面的例子。
作者:Ahmad Shadeed 譯者:前端小智 來源:ishadeed 原諒:https://ishadeed.com/article/defensive-css/