当前位置: 首页 > Web前端 > HTML5

找出答案——你对隐藏元素了解多少?

时间:2023-04-05 01:54:27 HTML5

最常见的显示方式:无相信大家都被问过这个问题:隐藏一个元素有多少种方式?一般来说,我们有display:none、opacity:0和visibility:hidden三种方法。基于display:none的副作用,已经是很糟糕的问题了。主要缺点如下:1.显示和隐藏切换时,会引起回流(reflow),进而引起重绘(redraw),当页面中的回流增加到一定程度时,会导致cpu占用翱翔。2、无法为元素设置过渡动画,也无法进行方向测量(包括clientWidth、clientHeight、offsetWidth、offsetHeight、scrollWidth、scrollHeight、getBoundingClientRect()、getComputedStyle())。原因是浏览器会解析HTML标签生成DOMTree。CSS生成CSSOM,然后合并DOMTree和CSSOM生成RenderTree,最后根据RenderTree的信息布局渲染界面。但是带有display:none的元素是不会加入到RenderTree中的,自然也就渲染不出来了。过渡动画。3、使用它设置显示隐藏开关时,会因为与display:flex和display:grid冲突而造成混乱。你真的了解不透明度和可见性吗?这样一来,当我们将元素设置为可见或隐藏时,使用opacity或visibility似乎是更好的选择,但是你有没有想过opacity:0和visibility:hidden是不一样的?具体有什么区别?既然标题说的是追根究底,那我们就通过几轮PK来深挖一下两者的具体区别吧:第一轮:动画属性在常见的动画效果中,淡入淡出应该是最多的了广泛使用。这时候我们应该只有一个选择:opacity和animation,因为visibility这个属性是不能做动画的。要满足动画过渡,两个值之间必须有连续的值,也就是连续的区间。Visibility显然不是Satisfied,因为可见/不可见两种状态之间没有中间状态,是“booleanhidden”。第二轮:子元素的表现设置opacity:0,visibility:hidden的元素。它们的子元素将如何受到不同的影响?首先,opacity属性不能被子元素继承,但是visibility属性是可以继承的。详见CSS3规范opacity和visibility中的属性介绍。其次,一旦设置了父元素的不透明度,子元素的最大透明度不会超过父元素,也就是说如果父元素的不透明度为0.5,那么即使子元素的不透明度设置为1,它的实际透明度会是0.5*1=0.5,所以,只要parent的透明度为0,child就没办法重新设置为visible;但是visibility的子元素还是有机会“翻身”的,即使父元素设置了visibility:hidden,子元素仍然可以用visibility:visible再次让子元素可见。第三轮:堆叠上下文(StackingContext)HTML中的元素都有自己的堆叠层次,但在某些情况下,元素会形成一个堆叠上下文(接下来被SC取代),直接“抬高”自身及其子元素的堆叠等级。元素之间不同的堆叠层次,当它们重叠时,将决定谁在Z轴上会更高,也就是谁会更靠近用户的眼睛。至于什么情况下元素会形成SC,可以参考MDN文档的详细描述。在这篇文档中,我们可以看到当一个元素的opacity属性值小于1时,就会形成SC。我们可以观察下面的代码:style="background:red;width:100px;height:100px">

本例中设置了绝对定位的绿色方块形成SC,其层叠层次自然高于红色正方形,所以此时我们看不到红色正方形:而当我们为红色正方形设置不透明度属性时,例如:
此时,红色方块会叠加在绿色方块之上。因为红色方块的opacity小于1,形成了SC,而且两者都没有设置z-index,属于同一个stackinglevel,所以根据从后而来的原则,红色方块会被stackedontop,如图:同理,opacity值为0的元素也会创建SC,而visibility属性则不会创建SC,也不会影响元素的层叠层次。说了半天,有人会问了,既然元素是隐藏的、看不见的,谁管它是上还是下呢?通常情况下都是如此,但是第四轮PK之后你就会知道,有时候真的不能忽视这个问题。第四轮:Interactivity/Accessibility这一轮我们比较的是interactivity/accessibility。先说可见性:先隐藏。对于具有此属性集的元素,绑定到它们的侦听器事件将忽略事件。target为自己的事件开火。这句话有点啰嗦。通俗地说,这个元素会接收到子元素的事件冒泡,但是不能触发自己的事件。您可以通过此在线演示体验这种效果。当然,除了无法触发自身的事件外,也无法通过tab键访问,即无法获得焦点;另外会失去accessibility,即不能访问,比如读屏软件就不能访问这个元素。另一方面,对于设置了opacity:0的元素,则完全没有上述限制。现在你知道为什么我们不能忽略上一轮提出的问题了吧,因为即使一个opacity:0的元素不可见,它仍然可以被点击访问,有时会导致意想不到的bug。既然两者各有优缺点,可不可以结合起来取长补短呢?答案是当然可以。但首先,我们要清楚自己要利用什么,要弥补什么。一般来说,我们希望元素可以使用淡入淡出的动画效果,希望元素消失后不保留交互性/可访问性。其实方法很简单:.box{animation:fade0.5slinear0sforwards;}@keyframesfade{0%{opacity:1;}100%{不透明度:0;可见性:隐藏;}}我们仍然使用opacity进行动画过渡,但是在最后一个动画帧中,我们添加visibility:hidden,我们达到了预期的效果。此时,当元素淡出时,不会意外触发事件。而且,在使用动画效果的opacity属性时,浏览器还会将元素提升为复合层(syntheticlayer),使用gpu进行硬件加速渲染,两全其美~当然如果你真的需要这个元素要保留页面中的占位符,您不能这样做。总结总而言之,如果你没有动画需求,使用visibility来切换可见和隐藏可能更省心,但如果你有动画需求,最好两者结合使用。另外,追根问题系列后续还会有更多文章,目的是对小知识点进行深入分析,从而获得更系统的理解,而不是停留在表面。ps:欢迎关注微信公众号——前端漫游攻略,会定期发布优质原创文章和翻译,关注公众号福利:回复666获取前端高级电子书精选,谢谢~