
英文 | https://medium.com/frontend-canteen/an-advanced-css-interview-question-implement-if-else-in-css-bb681d786d76
翻譯 | 楊小愛
我的一個朋友在最近的一次面試中遇到了一個有趣的 CSS 面試問題。當我第一次看到這個問題時,我認為這是一個常見的CSS問題。然而,經過仔細研究,我發現了這個問題的有趣部分。
面試題:請用CSS實作如下效果:
頁面上有一些數字顯示文章閱讀的數量。如果數字小于 100,則數字的顔色為灰色。如果數字大于或等于 100,則數字為棕色,而且這種顔色可以動态調整,而不是提前預設。
最後面試官要求用純CSS來解決這個問題,你知道如何達到這個效果嗎?
題目分析
這個問題的本質是什麼?
這個問題的本質很簡單,也就是說,這實際上是一個 if-else 問題。
如果我們用僞代碼描述這個問題,它應該是這樣的:
let color;
if (reads < 100){
color = 'gray'
} else {
color = 'brown'
}
是以現在問題變成了:我們如何在 CSS 中實作這個 if-else 邏輯?請記住,CSS 中沒有 if-else 關鍵字之類的東西。
在 CSS 中實作 if-else
在 CSS 中實作 if-else 的邏輯是本題考查的核心技能。讓我們在下面完成這個邏輯。如果你學會了這個技巧,你可以用它來實作許多強大的 CSS 效果。
首先,讓我們了解一個叫做clamp的函數。
clamp() CSS 函數将一個值限制在上限和下限之間。clamp() 允許在定義的最小值和最大值之間的值範圍内選擇中間值。
基本文法格式:
clamp(min, var, max)
我們可以将clamp函數了解為這樣的僞代碼:
funciton clamp(min, var, max){
if(var <= min){
return min
}
if(var >= max){
return max
}
if(var > min && var < max){
return var
}
}
是以:
clamp(10, 13, 20) → 13
clamp(10, 2, 20) → 10
clamp(10, 30, 20) → 20
用法示例:
font-size 的值不會超過 20px,也不會低于 10px。
這是clamp的基本用法。
如果您對clamp仍有疑問,可以參考 MDN 文檔。
接下來,我們在 CSS 中實作這個功能。
result的值根據 var 的值而變化:
當 var 的值小于 100 時,結果的值為 10;
當 var 的值大于等于 100 時,結果變為 20。
如果我們用僞代碼描述這個問題,它應該是這樣的:
let result;
if(var < 100){
result = 10
} else {
result = 20
}
這個要求和clamp函數類似,但又不一樣。clamp可以将 var 的值限制在一個範圍内,但我們現在希望結果的值是 10 或 20。
那我們怎麼做?
有一個特殊的技巧:我們可以放大 var 的變化,使其值要麼達到區間的上限,要麼達到區間的下限。
于是:
let result = clamp(10, (var-99) * 20, 20)
這會産生一個效果:
- 如果 var 的值為 99,則表達式變為:clamp(10, 0, 20), takes 10.
- 如果 var 的值為 100,則變為:clamp(10, 20, 20), takes 20.
用一張圖解釋:
同樣,如果我們希望:
當 var 的值小于 50 時,result的值為 5。
當 var 的值大于等于 50 時,result的值為 15。
我們隻需要這樣寫:
let result = clamp(5, (var-49) * 15, 15)
你有沒有注意到:這實際上是 if-else 的效果,我們做到了。
在 CSS 中切換顔色
回到最初的面試問題。
為了讓我們後面可以使用 CSS 進行變量計算,我們需要将值放在一個 CSS 變量中,是以 HTML 可以這樣寫:
<num style="--num:1">1<span>reads</span></num>
<num style="--num:99">99<span>reads</span></num>
<num style="--num:102">102<span>reads</span></num>
如果我們不需要考慮 HTML 語義或 SEO 因素,這裡的“數字”和“讀取”都可以由僞元素生成:
<head>
<style>
num::before {
counter-reset: num var(--num);
content: counter(num);
}
num::after {
content: 'reads';
}
</style>
</head>
<body>
<div>
<num style="--num:1"></num>
<num style="--num:99"></num>
<num style="--num:102"></num>
</div>
</body>
如果對 content 和 counter-reset 不熟悉,可以檢視 MDN 文檔。
- content :https://developer.mozilla.org/en-US/docs/Web/CSS/content
- counter-reset:https://developer.mozilla.org/en-US/docs/Web/CSS/counter-reset
具體的示範效果,可以通過以下位址檢視:https://codepen.io/bytefishmedium/pen/VwQrGEb
棕色為#aa540e,用HSL顔色表示為hsl(27, 50%, 36%),如下:
它的飽和度控制顔色的鮮豔程度。飽和度越高,顔色越鮮豔,飽和度越低,顔色越暗。當飽和度降低到0時,就變成了完全的灰色,如下:
在灰色和棕色之間切換顔色,即在 hsl(27, 85%, 36%) 和 hsl(27, 85%, 36%) 之間切換。
于是就有如下代碼:
num{
--s: clamp(0%,(var(--num) - 99) * 99%,85%);/* >100 */
color: hsl(27 var(--s) 36%);
}
最終的示範:https://codepen.io/bytefishmedium/pen/WNMXabm
總結
我們通過clamp函數在CSS中實作if-else效果,最後讓顔色根據變量的值進行切換。
其實原面試題還有另外一部分,簡單來說就是:讓顔色在多個值之間切換。僅使用 if-else 不足以滿足此要求,有興趣的話,可以留言交流學習。