九宮格經典面試題
1. 前言
其實面試有時候并不像大家想象的那樣問一些很基礎的問題,比如:
- 請談一下你對CSS盒模型的理解
- 你對flex布局了解的怎么樣
- 了解過grid布局嗎
- 當元素的外邊距為負值時會有什么樣的行為
- 當元素重疊在一起時如何控制上下層級
- 如何水平垂直居中
- 什么是事件冒泡
- 怎么控制特定位置的元素樣式(比如偶數位置的樣式)
- 如何判斷事件是從哪個元素冒泡過來的
- 哪個CSS屬性值可以減少重復定義顏色值
這樣問的話效率會比較低,而優秀的面試題只需要一道,就可以考察上述所有的這些問題。
2. 面試題
即使候選者對上面這些問題全部都對答如流,也不一定能夠靈活的運用這些知識。
而這道面試題不僅考察了候選人的基礎,更考察了候選者對基礎知識的靈活運用,來看看這道面試題:
要求如下:
- 邊框九宮格的每個格子中的數字都要居中
- 鼠標經過時邊框和數字都要變紅
- 格子中的數字居中用flex實現
- 點擊九宮格會彈出對應的數字
具體實現如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 清除默認樣式 */
* { padding: 0; margin: 0; }
/* 全屏顯示 */
html, body { height: 100% }
body {
/* 網格布局 */
display: grid;
/* 子元素居中 */
place-items: center;
}
/* 父元素 */
ul {
width: 300px;
/* 清除默認樣式 */
list-style: none;
/* 設置為flex布局 */
display: flex;
/* 設置換行 */
flex-flow: wrap;
}
/* 子元素 */
li {
/* 顯示為網格布局 */
display: grid;
/* 子元素水平垂直居中 */
place-items: center;
/* 寬高都是100像素 */
width: 100px;
height: 100px;
/* 設置盒模型 */
box-sizing: border-box;
/* 設置兩像素的邊框 */
border: 2px solid black;
/* 負邊距 */
margin: -2px 0 0 -2px;
}
/* 第1、4、7個子元素 */
li:nth-child(3n+1) {
/* 取消左負邊距 */
margin-left: 0
}
/* 前三個子元素 */
li:first-child, li:nth-child(2), li:nth-child(3) {
/* 取消上負邊距 */
margin-top: 0
}
/* 當鼠標經過時 */
li:hover {
/* 紅色字體 */
color: red;
/* 紅色邊框 */
border: 2px solid;
/* 調高層級 */
z-index: 1;
}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
<script>
// 選擇ul元素
const ul = document.getElementsByTagName('ul')[0]
// 監聽ul元素的點擊事件
ul.addEventListener('click', e => alert(e.target.innerText))
</script>
</body>
</html>
3. 面試題都考察了哪些上述知識呢
負邊距:
li {
margin: -2px 0 0 -2px;
}
- 利用負邊距可以消除邊框粗的bug
flex
ul {
/* 設置為flex布局 */
display: flex;
/* 設置換行 */
flex-flow: wrap;
}
grid布局、水平垂直居中
li {
/* 網格布局 */
display: grid;
/* 子元素居中 */
place-items: center;
}
減少重復定義顏色值
li:hover {
/* 紅色字體 */
color: red;
/* 紅色邊框 */
border: 2px solid;
}
可以看到定義紅色邊框的時候并沒有寫紅色(red或#f00),那是因為如果你不寫的話,默認是currentColor,這個關鍵字代表的就是你當前的color值。
有些同學可能會覺得納悶:這單詞這么長,還不如直接寫個red多方便啊,其實這個單詞相當于一個變量,指向color值,而別忘了color是可以繼承的!
如果在一個外層元素中定義了一個顏色,里面的子元素都可以繼承,用JS來控制的話只需要獲取外層DOM元素然后修改它的color樣式即可,currentColor能做的事情很多,這里為了不跑題就先不展開講,有興趣的同學可以去搜一下。
CSS盒模型
li {
/* 設置盒模型 */
box-sizing: border-box;
}
如果不寫這個屬性的話,每個格子的邊框也會計算在內,最終會超過父元素的三分之一,導致提前換行。
大家可以在案例中去掉這個屬性,感受一下沒有了它會發生什么樣的后果。
上下層級
li:hover {
z-index: 1;
}
如果沒有這個屬性,在鼠標經過時邊框的樣式會產生錯亂。
特定位置的元素樣式
/* 第1、4、7個子元素 */
li:nth-child(3n+1) {
xxx: xxx;
}
/* 前三個子元素 */
li:first-child, li:nth-child(2), li:nth-child(3) {
xxx: xxx;
}
事件冒泡
// 監聽ul元素的點擊事件
ul.addEventListener('click', e => alert(e.target.innerText))
4. 小結
怎么樣,沒想到就這一道九宮格居然能考察出這么多的基礎知識吧?
同學們課下一定要好好練習一下這道題,親自動手敲一遍代碼,看看能不能在不參照案例代碼的情況實現這個功能。