看到一篇來自 @shadeed9 關於 CSS 的文章內容,整體來說主要在編寫 CSS 時可能需要注意到的一些帶有保護性的處理方式,以避免頁面佈局上出現錯位等情況。CSS 屬性有些還是很常見的,只不過深感在細節上的把控真的很不錯。
原文很長,取部分內容簡單分享,並非原文翻譯,圖片和程式碼來自原文,具體的可檢視原文。原文地址:https://ishadeed.com/article/defensive-css/
目錄
- flexbox 內容換行
- 間距
- 長文字內容
- 防止影像被拉伸或壓縮
- 鎖定滾動連結
- CSS 變數回退
- 使用固定寬度或高度
- 被忽略的 background-repeat
- 垂直方向的媒體查詢
- 使用 justify-content: space-between
- 圖片上的文字
- 使用 CSS 網格中的固定值需注意
- 僅在需要時顯示滾動條
- 滾動條裝訂線
- CSS flexbox 中的最小內容大小
- CSS 網格中的最小內容大小
- 自動適合與自動填充
- 圖片最大寬度
- 位置:粘性css網格
- 分組選擇器
內容
flexbox 內容換行
當我們使用 flexbox 佈局的時候,預設情況下,在容器寬度不夠時,可能就會出現這樣的情況。
這個主要是因為 flex-wrap
的預設值是 nowrap
,所以我們需要這樣改變一下值。
.options-list {
display: flex;
flex-wrap: wrap;
}
間距
設計師在提供的設計稿中,很容易忽略文字在極限情況下與其他元素之間的間距,最終可能會出現這樣的情況,文字與 icon 緊挨。
要處理這個情況,就是需要考慮是在文字還是 icon 部分,根據實際情況分析後選擇新增 margin
值來增加間距。
.section__title {
margin-right: 1rem;
}
不過這個情況,我一般會考慮在 icon 上加 margin-left
,這樣的話,在沒有 icon 的時候,文字還是可以頂到容器邊緣。
長文字內容
這個就簡單,就是文字過長的處理方式,一般情況下就是換行或者截斷並已 ... 的形式出現。至於選擇什麼方式就要看當前頁面模組的設計風格來決定了。
文中的處理方式是採用了截斷出 ... 這種。
.username {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
防止影像被拉伸或壓縮
這種情況一般是在是圖片由使用者上傳,或者圖片未按規定比例使用導致的。
處理方式就是直接使用 object-fit
屬性:
.card__thumb {
object-fit: cover;
}
鎖定滾動連結
主要出現的情況是在當頁面中點選彈出 modal 彈層時,頁面內容本身很長的時候。
.modal__content {
overscroll-behavior-y: contain;
overflow-y: auto;
}
overscroll-behavior
雖好,但目前存在很大的相容性問題。
CSS 變數回退
這個 CSS 變數回退,說白了,其實就是當 CSS 變數值無效時而使用一個“安全值”來保證某個屬性值還是可用的。
.message__bubble {
max-width: calc(100% - var(--actions-width, 70px));
}
不過結合小志在做獵頭之前寫前端頁面時的處理方式,可能還會去考慮一下瀏覽器對 var()
的相容性問題,那麼就會再加上一個屬性。不過現在的瀏覽器來看,好像普遍性不存在這個問題。
.message__bubble {
max-width: 70px;
max-width: var(--actions-width, 70px);
}
使用固定寬度或高度
這個沒啥說的,主要就是對內容過長時,溢位容器時的一個保護措施。比如當我們把高度固定為 350px
之後,內容過長就會溢位。
而如果我們把 height
換成 min-height
的話,那情況就有所不同了。
同理,在寬度的處理上也是一樣。
被忽略的 background-repeat
在使用背景圖的時候,如果沒加上 no-repeat
的話,預設就會把背景圖平鋪開。
所以,隨手加上 no-repeat
還是一個好習慣,除非你已知這張背景圖是否要平鋪。
.hero {
background-image: url('..');
background-repeat: no-repeat;
}
垂直方向的媒體查詢
這個場景目前小志在頁面中還未見過,一般在中後臺頁面出現的概率比較多,比如作者提供的頁面效果。
左下角是通過 position: sticky;
定位的,可能通過 fixed
定位也是一樣吧,然後當瀏覽器的高度變小的時候,就會疊在左側的導航上面。
顯然,這樣的頁面效果就不對了。而如果這個時候,通過 @media
方式判斷頁面高度,在某個安全區外我們才讓左下角這部分通過 sticky
來定位。
@media (min-height: 600px) {
.aside__secondary {
position: sticky;
bottom: 0;
}
}
使用 justify-content: space-between
原文中這部分標題是 Using Justify-Content: Space-Between,但看起來更應該是 Using gap。使用什麼標題不是關鍵,這部分主要是提到當使用 justify-content: space-between;
時,如果元素不夠,元素與元素之間的間距就會拉長,因為要平均分佈元素之間的間距。
比如原本是想要這樣的一個效果,間距的值是固定的:
在元素數量足夠的情況下,元素與元素之間的間距還是比較理想的,通過下面這個 CSS 處理方式:
.wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
但,元素的數量總是會不足的時候,那麼就會這樣了。
可見,其實並不是想要平均分佈,而只是想要在最大的極限情況下和內容不足的時候,元素之間的間距是可控的。一般來說,這個處理方式挺多的,用 margin
之類的也是可以處理,不過目前有一個相容性並不是十分好的 gap
能完美解決這個問題。
.wrapper {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
圖片上的文字
使用者體驗上的一個細節處理問題,如果在圖片上有文案,但圖片沒載入出來,或者載入失敗的時候,新增一個背景色,以保證圖片載入失敗的情況下,文字與背景能區分開。
使用 CSS 網格中的固定值需注意
grid
網格佈局現在開始慢慢被關注了,grid
與 flex
一樣都可以做自適應的效果,也可以使用固定值的情況。在使用固定值的時候,最好是通過 @media
判斷一下寬度,以便於滿足最小寬度時的處理。
@media (min-width: 600px) {
.wrapper {
display: grid;
grid-template-columns: 250px 1fr;
gap: 1rem;
}
}
不過一般這種情況下,可能就直接改變頁面佈局了,感覺作者在這個方面上擔憂是多餘的。或者主要是自己未遇到過他所遇到的場景吧。
僅在需要時顯示滾動條
這個沒啥說的,一般大家都是把 scroll
設定為 auto
。不過在個別情況下,可能這個 auto
會讓元素的寬度變小,然後導致內容或者佈局出現一點小瑕疵。
.element {
overflow-y: auto;
}
滾動條裝訂線
這個所謂的裝訂線,主要就是 scrollbar-gutter
屬性,保留滾動條的空間。在上面那個 overflow
例子中提到,如果設定為 auto
的時候,可能會導致頁面佈局出現非意料的情況,那麼 scrollbar-gutter
就可以處理這個問題了。
相容性還是一個不可避免的話題。
假設不考慮相容性的問題,那麼我們就可以使用這個方法保留滾動條的空間。
.element {
scrollbar-gutter: stable;
}
CSS flexbox 中的最小內容大小
在使用 flex 佈局的時候,很有可能其中某個 item 的文字內容很長,最終導致沒有換行而溢位容器之外。
這種情況也並不是說沒有可能,就算是使用 overflow-wrap: break-word;
也不會有效果,那麼這個時候需要加上 min-width: 0;
來處理。
.card__title {
overflow-wrap: break-word;
min-width: 0;
}
對於這點,小志心中有一個疑惑,為什麼要考慮使用
overflow-wrap
的方式,而不使用word-wrap
或者word-break
呢?通過 demo 對比之後發現,效果上
word-break: break-word;
與上述的例子是相同的結果,僅僅只是從文字換行的 demo 效果來看。但從 MDN 中對這兩個屬性的介紹來看,還是有區別的。
word-break
The word-break CSS property sets whether line breaks appear wherever the text would otherwise overflow its content box.
overflow-wrap
The overflow-wrap CSS property applies to inline elements, setting whether the browser should insert line breaks within an otherwise unbreakable string to prevent text from overflowing its line box.
CSS 網格中的最小內容大小
與 flexbox 類似,CSS 網格的子項有一個預設的最小內容大小,即 auto
,這意味著,如果存在大於網格項的元素,它將溢位。
@media (min-width: 1020px) {
.wrapper {
display: grid;
grid-template-columns: 1fr 248px;
grid-gap: 40px;
}
}
.carousel {
display: flex;
overflow-x: auto;
}
對於網格這塊,瞭解的不夠深入,直接延用作者的意思就是將grid-template-columns
的值改變一下,改為:minmax(0, 1fr) 248px
就可以得到下面這個效果。
自動適合與自動填充
當時看到效果圖的時候,我還以為是 flex 佈局中的情況,結果是 grid 網格佈局中使用的情況。
在使用 grid 佈局時,如果是這樣寫,利用 auto-fit
的話,就會是上面這個效果,item 不夠時會被拉長。
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-gap: 1rem;
}
而如果改為 auto-fill
的話就是下面這個效果。
對於 auto-fit
和 auto-fill
的區別可以看這張圖。
圖片最大寬度
作者建議可以在 reset 部分中對 img
加上最大寬度的設定,但沒說具體是為什麼。個人猜想是考慮圖片在容器中的展示吧,同時還有一個 object-fit
屬性。?
img {
max-width: 100%;
object-fit: cover;
}
位置:粘性css網格
在使用 CSS 網格佈局時,如果子元素使用了 position: sticky
的話,由於網格子元素的預設對齊方式是 stretch
,所以會被拉伸。
而其實我們想要的是,左側邊欄並非拉伸效果的,所以,需要通過 align-self: start;
改變一下子元素自身的對齊方式。
aside {
align-self: start;
position: sticky;
top: 1rem;
}
這樣的話,效果就不一樣了。
簡單測試了一下,在 flex 佈局中也是同樣的情況,主要就是因為子元素的特性是拉伸的。
分組選擇器
/* Don't do this, please */
input::-webkit-input-placeholder,
input:-moz-placeholder {
color: #222;
}
現在寫 CSS 的時候基本上都不會去寫帶字首的屬性,而是通過構建工具來自動完成。所以平時也不會在意這個。按照作者的說法是,如果把這兩個寫在一起,會導致整個規則失效,建議分開寫。
input::-webkit-input-placeholder {
color: #222;
}
input:-moz-placeholder {
color: #222;
}
最後
以上內容看著其實都是挺簡單,挺初級的內容,但是在日常開發過程中,對於 CSS 的注意的確有一些還是不夠到位。畢竟有一些內容過於細節了。