其实面试有时候并不像大家想象的那样问一些很基础的问题,比如:
- 请谈一下你对CSS盒模型的理解
- 你对flex布局了解的怎么样
- 了解过grid布局吗
- 当元素的外边距为负值时会有什么样的行为
- 当元素重叠在一起时如何控制上下层级
- 如何水平垂直居中
- 什么是事件冒泡
- 怎么控制特定位置的元素样式(比如偶数位置的样式)
- 如何判断事件是从哪个元素冒泡过来的
- 哪个CSS属性值可以减少重复定义颜色值
这样问的话效率会比较低,而优秀的面试题只需要一道,就可以考察上述所有的这些问题。
即使候选者对上面这些问题全部都对答如流,也不一定能够灵活的运用这些知识。
而这道面试题不仅考察了候选人的基础,更考察了候选者对基础知识的灵活运用,来看看这道面试题:
要求如下:
- 边框九宫格的每个格子中的数字都要居中
- 鼠标经过时边框和数字都要变红
- 格子中的数字居中用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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
li { margin: -2px 0 0 -2px; }
代码块预览 复制
- 1
- 2
- 3
- 利用负边距可以消除边框粗的bug
ul { /* 设置为flex布局 */ display: flex; /* 设置换行 */ flex-flow: wrap; }
代码块预览 复制
- 1
- 2
- 3
- 4
- 5
- 6
- 7
li { /* 网格布局 */ display: grid; /* 子元素居中 */ place-items: center; }
代码块预览 复制
- 1
- 2
- 3
- 4
- 5
- 6
- 7
li:hover { /* 红色字体 */ color: red; /* 红色边框 */ border: 2px solid; }
代码块预览 复制
- 1
- 2
- 3
- 4
- 5
- 6
- 7
可以看到定义红色边框的时候并没有写红色(red或#f00),那是因为如果你不写的话,默认是currentColor,这个关键字代表的就是你当前的color值。
有些同学可能会觉得纳闷:这单词这么长,还不如直接写个red多方便啊,其实这个单词相当于一个变量,指向color值,而别忘了color是可以继承的!
如果在一个外层元素中定义了一个颜色,里面的子元素都可以继承,用JS来控制的话只需要获取外层DOM元素然后修改它的color样式即可,currentColor能做的事情很多,这里为了不跑题就先不展开讲,有兴趣的同学可以去搜一下。
li { /* 设置盒模型 */ box-sizing: border-box; }
代码块预览 复制
- 1
- 2
- 3
- 4
如果不写这个属性的话,每个格子的边框也会计算在内,最终会超过父元素的三分之一,导致提前换行。
大家可以在案例中去掉这个属性,感受一下没有了它会发生什么样的后果。
li:hover { z-index: 1; }
代码块预览 复制
- 1
- 2
- 3
如果没有这个属性,在鼠标经过时边框的样式会产生错乱。
/* 第1、4、7个子元素 */ li:nth-child(3n+1) { xxx: xxx; } /* 前三个子元素 */ li:first-child, li:nth-child(2), li:nth-child(3) { xxx: xxx; }
代码块预览 复制
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
// 监听ul元素的点击事件 ul.addEventListener('click', e => alert(e.target.innerText))
代码块预览 复制
- 1
- 2
怎么样,没想到就这一道九宫格居然能考察出这么多的基础知识吧?
同学们课下一定要好好练习一下这道题,亲自动手敲一遍代码,看看能不能在不参照案例代码的情况实现这个功能。