难度级别:初级及以上 提问概率:70%
在前端开发中,隐藏元素并不是一个陌生的话题。根据业务场景不同,实现方案也多种多样,在面试中,应该尽可能多的描述自己遇到过的场景,使用过的方案。而不应该吝啬描述,只是单纯的说出一些解决点子,给面试官一种指导型回复。这一章中,我们将整理总结一些关于隐藏元素的方案,但需要强调的是,这一章重点并非是要记忆这些隐藏或移除一个元素的解决方案,而是掌握根据一个点发散的去整理相关知识体系的过程,这对面试来说是非常重要的。
目录
1 display隐藏
2 visibility隐藏
3 opacity隐藏
4 z-index设置为更低级别
5 宽高设置为0
6 clip裁剪
8 scale缩放
9 font-size设置为0
10 Vue中的v-if和v-show
10的小结
1 display隐藏
使用display:none的CSS属性设置,可以将元素隐藏,虽然用户在页面中看不见这个元素,但它却还存在于页面DOM树中。需要注意的是,这种方式将会在页面中瞬间留出空白区域,也就是说需要其他元素进行补位,这势必引起页面的重排。
HTML代码:
<div class="box"></div>
CSS代码:
<style>
.box {
display: none;
width: 100px;
height: 100px;
background: red;
}
</style>
2 visibility隐藏
通过visibility:hidden;的CSS属性设置,虽然用户看不见这个元素,但元素所占的位置仍然存在,也就是宽和高并没有改变。这种方式与display隐藏有明显的区别,并不会引起重排。
HTML代码:
<div class="box"></div>CSS代码:
<style>
.box {
visibility: hidden;
width: 100px;
height: 100px;
background: red;
}
</style>
3 opacity隐藏
将CSS的opacity属性值设置为0,又是一种截然不同的实现方案,这种方式可以理解为一种相对用户的假隐藏,而非相对于浏览器的隐藏。这个元素是真实存在的,只是将内容设置为透明,给用户一种不存在的感觉。但需要注意的是,如果这个元素自身带有点击事件,用户仍然可以无意间点中元素区域,并触发事件。
HTML代码:
<div class="box" onclick="opaClick()"></div>
CSS代码:
<style>
.box {
opacity: 0;
width: 100px;
height: 100px;
background: red;
}
</style>
Javascript代码:
<script>
function opaClick () {
alert(‘真的隐藏了吗?’);
}
</script>
4 z-index设置为更低级别
当给元素设置CSS样式position:absolute;绝对定位后,再辅助以z-index更低的级别,也可以实现元素的隐藏。采用这种实现方案后,使元素脱离的原本的DOM文档流,使其可以隐藏于其他元素的背部。但需要注意的是,这个方案的重点在于隐藏于其他元素背部,但如果当前上下文环境没有其他元素内,很显然这种方式就不成立了。不过结合真实业务场景来看,当前上下文环境没有其他元素的情况应该是很少吧。
与此类似的方案还有,为元素设置绝对定位,然后将left属性值设置为超小的负数;还有为父元素设置overflow:hidden属性,然后为元素设置绝对定位,再辅助以超大负数的left属性值,这些做法基本都是相似的,都是为了通过使元素脱离用户网页视野,来达到隐藏的效果。
HTML代码:
<div class="box-show"></div>
<div class="box"></div>
CSS代码:
<style>
.box-show {
position: absolute;
width: 100px;
height: 100px;
background: yellow;
}
.box {
position: absolute;
width: 100px;
height: 100px;
background: red;
z-index: -1;
}
</style>
5 宽高设置为0
我们知道页面中一个元素之所以能被用户看见,是因为浏览器在渲染之初,通过对CSS样式的计算,为元素预留出了相应的区域,然后再逐步渲染区域内的内容。但如果把元素的宽和高设置为0,也就不符合浏览器渲染的区块规则,自然也就达到了隐藏的效果。但一般来说一个块元素内会包含其他子元素,即便父元素的宽高设置为0,达到了隐藏效果,但也不能保证子元素不会超出显示。所以还需要辅助以overflow:hidden的上下文边界规范设置。
HTML代码:
<div class="box">
<div class="inner"></div>
</div>
CSS代码:
<style>
.box {
overflow: hidden;
width: 0;
height: 0;
background: red;
}
.inner {
width: 200px;
height: 200px;
background: yellow;
}
</style>
6 clip裁剪
clip裁剪功能,提供了一个rect属性函数,可以传入上、右、下、左4个参数值,表示显示区域距离元素远点的距离。试想一下,如果把元素内容全部裁剪掉,是不是也可以达到隐藏的效果呢。但需要注意的是,这种裁剪方案只针对绝对定位的元素有效果。
HTML代码:
<div class="box"></div>
CSS代码:
<style>
.box {
position: absolute;
width: 100px;
height: 100px;
background: red;
clip: rect(0 0 0 0);
}
</style>
7 为元素添加hidden属性
也可以采用直接在HTML标签上添加hidden属性的方式,实现效果类似于display:none的方案。
HTML代码:
<div class="box" hidden></div>
8 scale缩放
缩放可以使元素缩小或者放大,这取决于scale函数内参数的数值。但如果传入参数值为0,也可以达到完全隐藏元素的效果。需要注意的是,scale缩放功能对行内元素不起作用,这意味着要么是块元素,要么是行内块元素才可以使用这种方案。虽然scale函数内传入0可以达到完全隐藏的效果,缩放的原点却是元素的中心原点,这就导致虽然用户看不见真实的元素内容了,但元素却还类似于visibility:hidden的实现方案,占据着一定的区域。
HTML代码:
<div class="top-box"></div>
<div class="box"></div>
<div class="bottom-box"></div>
CSS代码:
<style>
.top-box {
width: 100px;
height: 100px;
background: yellow;
}
.box {
width: 100px;
height: 100px;
background: red;
transform: scale(0);
}
.bottom-box {
width: 100px;
height: 100px;
background: green;
}
</style>
9 font-size设置为0
在浏览器中,一般情况下设置字体样式font-size小于12px的时候,就不容易识别了,而是以最小的12px来渲染。但如果是块元素,为字体设置font-size属性值为0的时候,便可以将文字隐藏;而如果是行内元素字体设置font-size属性值为0的时候,则整个行内元素都会被隐藏掉。
HTML代码:
<div class="box">隐藏一个元素</div>
CSS代码:
<style>
.box {
display: inline;
width: 100px;
height: 100px;
background: red;
font-size: 0;
}
</style>
10 Vue中的v-if和v-show
在说Vue的v-if和v-show这两个指令之前,我们先来看一下,如果不使用第三方框架,做一个自定义弹框的过程。
假如当前的业务需求场景是,点击按钮,生成一个弹框,要求弹框包含背景遮罩层、标题、提示内容展示、关闭按钮等元素,点击“关闭按钮”,执行关闭弹出事件,代码如下:
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>弹出提示</title><style>* {margin: 0;padding: 0;}
.cover {display: flex;align-items: center;justify-content: center;position: fixed;left: 0;top: 0;width: 100vw;height: 100vh;background: rgba(0, 0, 0, 0.2);z-index: 10;}.dialog-box {overflow: hidden;width: 360px;height: 190px;background: #FFF;border-radius: 4px;}.dialog-title {height: 40px;padding-left: 20px;line-height: 40px;font-size: 18px;background: blue;color: #FFF;font-weight: 600;}
.dialog-txt {height: 100px;line-height: 100px;text-align: center;}.dialog-btn {margin: 0 auto;width: 120px;height: 38px;line-height: 38px;background: blue;text-align: center;color: #FFF;border-radius: 4px;cursor: pointer;}</style></head> <body><button onclick="showDialog('提示文字内容')">显示弹框</button><script>function showDialog(txt) {let dialogDom = document.querySelector('#coverId');// 如果创建过弹框,则直接进行展示if (dialogDom) {dialogDom.style.display = 'flex';
} else { // 如果未创建过弹框,则进行创建// 定义弹框DOM内容let newDom = `<div class="dialog-box"><p class="dialog-title">提示</p><div class="dialog-txt">${ txt }</div><div class="dialog-btn" onclick="hideDialog()">知道了</div></div>`;// 定义弹框背景遮罩层let coverDom = document.createElement('div');coverDom.setAttribute('class', 'cover');coverDom.setAttribute('id', 'coverId');coverDom.innerHTML = newDom;let bodyDom = document.querySelector('body');// 将弹框插入body元素底部bodyDom.appendChild(coverDom);}}// 关闭弹出,只是做隐藏操作function hideDialog() {let dialogDom = document.querySelector('#coverId');dialogDom.style.display = 'none';}</script></body>
</html>
弹框展示效果如图
10的小结
以上案例通过简单的代码,实现了日常业务开发中比较常见的弹框功能。本案例重点并非想要描述如何实现一个弹框,而想要表达的是,这个按钮只是页面众多元素其中的一个,或许是一个重点功能,用户会频繁的点击,又或许只是一个弱化的功能,用户一直到离开网页都不会去点击这个按钮。所以弹框也不应该是页面初始化就需要加载的,必要的做法是当用户第一次需要使用弹框功能的时候,再去创建弹框,而一旦第一次创建后,关闭只是隐藏。当用户需要再次打开弹框的时候,就不需要做创建操作了,而是直接将之前隐藏的弹框再次展示即可。
通过以上这种方式最大限度节约浏览器的开销,那么在Vue项目中使用v-if和v-show也是同样的道理。我们知道v-if是通过依赖数据判断是否需要创建或移除对应的组件,而v-show则是在初始化过程中就已经将组件创建完成,只是通过依赖数据的改变,进而判断是否需要对组件进行隐藏或者显示。这就需要在项目场景中,根据页面中组件显示与隐藏切换的频次,以及切换后组件内容是否需要继续保持等因素,判断两种指令更适合使用的场景,而绝对不是项目全篇的使用v-if这一个指令。
刷题思考
这是一道非常经典而又高频的CSS面试题,它体现了CSS面试题中一个非常大的特点,那就是几乎每个问题都会有非常多的解决方案。但问题的症结就在于每种解决方案都不会很难,而细节却很多。所以,CSS面试题的考察点并不是要看求职者掌握的多么
有深度,而是考察在日常工作中,对于某一类问题是否有一个知识点聚合的意识。
我们知道,一旦接触的项目多了,同一类问题有时候使用同一种方案却不能很好的得到解决,这个时候就需要通过这种知识聚合的意识,变换不同的思路,快速找到解决方案。
类似考点
因为CSS细节知识点非常多,所以这道题非常有代表性,它可以通过一个问题点,让人发散的去思考非常多相关联的知识点,最终通过最初的问题点聚合到一起,形成一个知识体系。面试官还可能会问,例如请你说一下垂直居中的解决方案都有哪些?例如请你说一说清楚浮动的方案都有哪些等。