• CSS 元素的显示与隐藏


    CSS 元素的显示与隐藏

    使用 CSS 让元素不可见的方法很多,剪裁、定位到屏幕外、明度变化等都是可以的。虽然它们都是肉眼不可见,但背后却在多个维度上都有差别。

    下面是我总结的一些比较好的隐藏实践。

    1. 如果希望元素不可见,同时不占据空间,辅助设备无法访问,同时不渲染,可以使用<script>标签隐藏。例如:
    <script type="text/html">
     <img src="1.jpg"> 
    </script>
    
    • 1
    • 2
    • 3

    此时,图片 1.jpg 是不会有请求的。<script>标签是不支持嵌套的,因此,如果希望在<script>标签中再放置其他不渲染的模板内容,可以试试使用<textarea>元素。例如:

    <script type="text/html"> 
    <img src="1.jpg"> 
    <textarea style="display:none;"> 
    <img src="2.jpg"> 
      </textarea> 
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    图片 2.jpg 也是不会有请求的。另外,<script>标签隐藏内容获取使用 script.innerHTML<textarea>使用textarea.value

    1. 如果希望元素不可见,同时不占据空间,辅助设备无法访问,但资源有加载,DOM 可访问,则可以直接使用display:none隐藏。例如:
    .hidden {
     display: none; 
    }
    
    • 1
    • 2
    • 3
    1. 如果希望元素不可见,同时不占据空间,辅助设备无法访问,但显隐的时候可以有transition淡入淡出效果,则可以使用:
    .hidden {
     position: absolute; 
     visibility: hidden; 
    }
    
    • 1
    • 2
    • 3
    • 4
    1. 如果希望元素不可见,不能点击,辅助设备无法访问,但占据空间保留,则可以使用visibility:hidden隐藏。例如:
    .hidden {
     visibility: hidden; 
    }
    
    • 1
    • 2
    • 3
    1. 如果希望元素不可见,不能点击,不占据空间,但键盘可访问,则可以使用 clip 剪裁隐藏。例如:
    .clip {
     position: absolute; 
     clip: rect(0 0 0 0); 
    } 
    .out { 
     position: relative; 
     left: -999em; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 如果希望元素不可见,不能点击,但占据空间,且键盘可访问,则可以试试 relative 隐藏。例如,如果条件允许,也就是和层叠上下文之间存在设置了背景色的父元素, 则也可以使用更友好的 z-index 负值隐藏。例如:
    .lower {
      position: relative; 
      z-index: -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    1. 如果希望元素不可见,但可以点击,而且不占据空间,则可以使用透明度。例如:
    .opacity {
     position: absolute; 
     opacity: 0; 
     filter: Alpha(opacity=0); 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 如果单纯希望元素看不见,但位置保留,依然可以点可以选,则直接让透明度为 0。例如:
    .opacity {
     opacity: 0; 
     filter: Alpha(opacity=0); 
    }
    
    • 1
    • 2
    • 3
    • 4

    大家可以根据实际的隐藏场景选择合适的隐藏方法。不过,实际开发场景千变万化,上面罗列的实践不足以覆盖全部情形。

    下面我们来介绍两个最为重要是属性:display

    1. display 与元素的显隐

    对一个元素而言,如果 display 计算值是 none 则该元素以及所有后代元素都隐藏,如果是其他 display 计算值则显示。

    display 可以说是 Web 显隐交互中出场频率最高的一种隐藏方式,是真正意义上的隐藏,干净利落。人们对它的认识也比较准确,无法点击,无法使用屏幕阅读器等辅助设备访问,占据的空间消失,但很多人就仅局限于此了,实际上,display:none 的故事并不只有这么一点点。

    在 Firefox 浏览器下,display:none 的元素的 background-image 图片是不加载的,包括父元素 display:none 也是如此;如果是 Chrome 和 Safari 浏览器,则要分情况,若父元素 display:none,图片不加载,若本身背景图所在元素隐藏,则图片依旧会去加载;对 IE 浏览器而言,无论怎样都会请求图片资源。

    CSS 和 HTML 代码如下:

    .bg1 { 
     background: url(1.png); 
    } 
    .bg2 { 
     background: url(2.png); 
    } 
    <div hidden class="bg1"></div> 
    <div hidden><div class="bg2"></div></div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Chrome 浏览器下的网络请求如下图所示。
    1655790822495.png

    我们发现只加载了 1.png,因此,在实际开发的时候,如头图轮播切换效果,那些默认需要隐藏的图片作为背景图藏在隐藏元素的子元素上,微小的改动就可以明显提升页面的加载体验,可以说是非常实用的小技巧。

    另外,如果不是 background-image 图片,而是<img>元素,则设置 display:none 在所有浏览器下依旧都会请求图片资源。

    照理说,display:none 的元素应该是无法被点击的,display:none 可以非常彻底地隐藏,肯定不能点击啊!但是,下面这种情况却例外:

    <form> 
      <input id="any" type="submit" style="display:none;"> 
      <label for="any">提交</label> 
    </form>
    
    • 1
    • 2
    • 3
    • 4

    此处 submit 类型的“提交”按钮设置了 display:none,但是当我们点击“提交”的时候,隐藏的按钮依然会触发 click、触发表单提交,此现象出现在 IE9 及以上版本浏览器以及其他现代浏览器中。

    设置 display:none 的意义在于,当按钮和<label>元素不在一个水平线上的时候,点击<label>元素不会触发锚点定位。但是我并不推荐这么做,因为 submit 按钮会丢失键盘可访问性。

    HTML 中有很多标签和属性天然 display:none,如<style><script>和 HTML5 中的<dialog>元素(如果浏览器支持)。如果这些标签在<body>元素中,设置 display: block 是可以让内联 CSS 和 JavaScript 代码直接在页面中显示的。例如:

    <style style="display:block;"> 
      .l { float: left; } 
    </style>
    
    • 1
    • 2
    • 3

    页面上就会出现 .l { float: left; } 的文本信息;如果再设置 contenteditable= "true",在有些浏览器下(如 Chrome),甚至可以直接实时编辑预览页面的样式。

    还有一些属性也是天然 display:none 的。例如,hidden 类型的<input>输入框:

    <input type="hidden" name="id" value="1">
    
    • 1

    专门用来放置类似 token 或者 id 这样的隐藏信息,这也说明表单元素的显示与隐藏并不影响数据的提交,其真正影响的是 disabled 属性。

    HTML5 中新增了 hidden 这个布尔属性,可以让元素天生 display:none 隐藏。例如:

    <div hidden>看不见我</div>
    
    • 1

    IE11 以及其他现代浏览器都支持它,因此,如果要兼容桌面端,需要如下 CSS 设置:

    [hidden] { 
      display: none; 
    }
    
    • 1
    • 2
    • 3

    display:none 显隐控制并不会影响 CSS3 animation 动画的实现,但是会影响 CSS3 transition 过渡效果执行,因此 transition 往往和 visibility 属性走得比较近。

    对于计数器列表元素,如果设置 display:none,则该元素加入计数队列。举个例子,10 个列表从 1 开始递增,假设第二个列表设置了 display:none,则原来的第三个列表计数变成 2,最后总计数是 9。

    2. **visibility **与元素的显隐

    有一些人简单地认为 display:nonevisibility:hidden 两个隐藏的区别就在于:display:none 隐藏后的元素不占据任何空间,而 visibility:hidden 隐藏的元素空间依旧保留。实际上并没有这么简单,visibility 是一个非常有故事的属性。

    1. **visibility **的继承性

    首先,它最有意思的一个特点就是继承性。父元素设置 visibility:hidden,子元素也会看不见,究其原因是继承性,子元素继承了 visibility:hidden,但是,如果子元素设置了 visibility:visible,则子元素又会显示出来。这个和 display 隐藏有着质的区别。

    我们看一个例子来切实感受一下,HTML 代码如下:

    <ul style="visibility:hidden;"> 
      <li style="visibility:visible;">列表 1</li> 
      <li>列表 2</li>
      <li>列表 3</li>
      <li style="visibility:visible;">列表 4</li>
    </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    列表父元素 visibility:hidden,千万不要想当然地认为此时所有子元素就都不可见了,“列表 1”和“列表 4”依旧 清晰可见。

    这种 visibility:visible 后代可见的特性,在实际开发的时候非常有用。

    1. **visibility **与 CSS 计数器

    visibility:hidden 不会影响计数器的计数,这和 display:none 完全不一样。举个例子,如下 CSS 和 HTML 代码:

    .vh { 
      visibility: hidden; 
    } 
    .dn { 
      display: none; 
    } 
    ol { 
      border: 1px solid; 
      margin: 1em 0; 
      counter-reset: test; 
    } 
    li:after { 
      counter-increment: test; 
      content: counter(test); 
    } 
    <ol> 
      <li>列表</li>
      <li class="dn">列表</li>
      <li>列表</li>
      <li>列表</li>
    </ol> 
    <ol> 
      <li>列表</li>
      <li class="vh">列表</li>
      <li>列表</li>
      <li>列表</li>
    </ol>
    
    • 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

    结果如下图所示。
    image.png
    可以看到,visibility:hidden 虽然让其中一个列表不可见了,但是其计数效果依然在运行。相比之下,设置 display:none 的列表就完全没有参与计数运算。

    1. **visibility **与 **transition **

    下面的 CSS 是会让.box 元素 hover 时显示.target 子元素,但不会有过渡效果:

    .box > .target { 
      display: none; 
      position: absolute; 
      opacity: 0; 
      transition: opacity .25s; 
    } 
    .box:hover > .target { 
      display: block; 
      opacity: 1; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    但是,下面的 CSS 语句却可以让.target 子元素有淡出的过渡效果:

    .box > .target { 
      position: absolute; 
      opacity: 0; 
      transition: opacity .25s; 
      visibility: hidden; 
    } 
    .box:hover > .target { 
      visibility: visible; 
      opacity: 1; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这是为什么呢?因为 CSS3 transition 支持的 CSS 属性中有 visibility,但是并没有 display

    由于 transition 可以延时执行,因此,和 visibility 配合可以使用纯 CSS 实现 hover 延时显示效果,由此提升我们的交互体验。

    下图所示是一个很常见的 hover 悬浮显示列表效果,而且有多个触发点相邻,对于这种 hover 交互,如果在显示的时候增加一定的延时,可以避免不经意触碰导致覆盖目标元素的问题。例如,图中2虽然显示的是第一行的下拉列表,但真相即可能是:我本来想去 hover第二行的“操作”文字,但是由于鼠标光标移动路径不小心经过了第一行的“操作”,结果把第二行本来 hover 的“操作”覆盖了,必须重新移出去,避开干扰元素,重新 hover 才行。如此一来,体验就不好了。
    image.png
    但是有了 visibility 属性和 transition 延时,我们就可以把这种不悦的体验消除掉,关键的 HTML 和 CSS 代码如下:

    <td> 
      <a href>操作▾</a> 
      <div class="list"> 
        <a href>编辑</a> 
        <a href>删除</a> 
      </div> 
    </td> 
    .list { 
      position: absolute; 
      visibility: hidden; 
    } 
    td:hover .list { 
      visibility: visible; 
      transition: visibility 0s .2s; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    transitionhover 时候声明可以让鼠标光标移出的时候列表无延时地迅速隐藏。

    有了上面的 CSS 处理,当我们鼠标光标奔向第二行的“操作”按钮,但不小心经过第一行“操作”按钮时,就不会发生瞬间出现列表而覆盖目标元素的问题了。

    visibility隐藏除了和 transition 友好外,与 display:none 相比,其在 JavaScript 侧也更加友好。存在这样的场景:我们需要对隐藏元素进行尺寸和位置的获取,以便对交互布局进行精准定位。此时,建议使用 visibility 隐藏:

    .hidden { 
      position: absolute; 
      visibility: hidden; 
    }
    
    • 1
    • 2
    • 3
    • 4

    原因是,我们可以准确计算出元素的尺寸和位置,如果使用的是 display:none,则无论是尺寸还是位置都会是0,计算就会不准确。例如,假设element是页面上某个display:none 隐藏元素 DOM 对象,则:

    console.log('clientWidth: ' + element.clientWidth); 
    console.log('clientHeight: ' + element.clientHeight); 
    console.log('clientLeft: ' + element.clientLeft); 
    console.log('clientTop: ' + element.clientTop); 
    console.dir(element.getBoundingClientRect());
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果会显示全部都是 0。

    最后,有必要强调一下:

    1. 普通元素的 title 属性是不会被朗读的,除非辅以按钮等控件元素,这里是因为设置了 role="button"所以才可以朗读。
    2. visibility:hidden 元素是不会被朗读的。
  • 相关阅读:
    Tomcat部署及优化
    leetcode20. 有效的括号 [简单题]
    如何提高系统的可用性/高可用
    node.js知识系列(3)-每天了解一点
    写一个vue前端项目
    娣卞害绁炵粡缃戠粶 ai,AI 绁炵粡缃戠粶
    SSM出租车查询系统毕业设计-附源码220915
    5. 最长回文子串
    第一章 软考架构师之计算机系统组成与体系结构
    d的dip1000仍按域变量对待中引用的副本
  • 原文地址:https://blog.csdn.net/p1967914901/article/details/125390389