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