Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web 隐藏技术:几中隐藏 Web 中的元素方法及优缺点 #229

Open
husky-dot opened this issue May 14, 2020 · 0 comments
Open

Comments

@husky-dot
Copy link
Owner

作者:Ahmad shaded
译者:前端小智
来源:sitepoint

点赞再看,养成习惯

本文 GitHub https://github.com/qq449245884/xiaozhi 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。

在 Web 开发中出于多种原因,我们需要隐藏元素。 例如,一个按钮应该在移动中可见,而在桌面视口中隐藏。 或者,在移动设备上隐藏但要在桌面上显示的导航元素。 隐藏元素时有三种不同的状态:

  • 元素完全隐藏并从文档流中删除。
  • 元素只是隐藏在视觉上,而且仍然可以被辅助技术(AT)访问,比如屏幕阅读器。
  • 元素是可见的,但仅对屏幕阅读器隐藏。

在这篇文章中,我们将学习在htmlcss中隐藏元素,并涵盖易访问性、动画和隐藏用例等方面,让我们开始吧。

HTML5 隐藏属性

它是一个布尔 HTML 属性,隐藏了附加到它的元素。当浏览器加载一个web页面时,它不会渲染带有hidden属性的元素,除非该元素被CSS手动覆盖,这与应用display: none的效果类似。

考虑下面的例子:

我们有一个title、一个figure和一个描述。只有当视口宽度大于400px时,才会显示该图。我向元素添加了hidden`属性。

在CSS中,我使用hidden属性仅在所需的视口大小中显示元素。

img[hidden] {
  display: none;
}

@media (min-width: 400px) {
  img[hidden] {
    display: block;
  }
}

事例源码:https://codepen.io/shadeed/pen/373c8a132e5d72201b935689d6990d16?editors=1100

那么,你可能会问为什么不使用display: none呢?这是个好问题。当通过其hidden属性调用图像选择器时,我们可以确定即使CSS因为某种原因没有加载,元素也会被隐藏。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

可访问性对hidden的影响

从可访问性的角度来看,hidden将元素完全隐藏在web页面之外,因此屏幕阅读器无法访问它。一定要避免使用它来隐藏仅用于表示目的的元素。

CSS display 属性

每个元素都有一个默认的display值,比如inline-blockblocktable等等。要隐藏具有display属性的元素,我们应该使用display: none。当一个元素使用display: none隐藏时,它的所有后代都将被删除。

考虑下面的例子:

img {
  display: none;
}

@media (min-width: 400px) {
  img {
    display: block;
  }
}

这将完全隐藏文档流和屏幕阅读器中的图像。 也许你想知道文档流是什么? 请参见下图:

注意,当蓝皮书被隐藏时,它已被完全从堆栈中删除。为它保留的空间已经消失了。同样的概念也适用于在HTML中隐藏元素时。元素的预留空间已经没有了,它更改了文档流,或者在我们的示例中,更改了图书流堆栈。

下面是一个动画,演示当移除书本时发生的情况:

如果资源隐藏在CSS中,它们会加载吗?

是的,会的。 例如,如果<image>被CSS隐藏,并且我们在某个断点处显示它,则它已经被加载。 即使图片被CSS隐藏,该图片也会引起HTTP请求。

在下面的演示中,我只添加了一个图像,并使用CSS隐藏它。然后,我打开DevTools并检查networks选项卡,它显示图像已加载。

稍后我们将对此进行讨论,以解释如何在特定断点或视口大小中不需要HTTP请求时减少HTTP请求。

style 元素

值得一提的是,有些元素的默认值是display: none。可以将<style>元素添加到HTML页面中,我们可以将其display属性更改为block,这样就可以看到它了。

html

<body>
    <style>
       .title { color: #000; }
    </style>
</body>

css

style {
    display: block;
}

如果您希望样式块始终可见且可编辑,这是非常有用的。可以通过向style 标签添加属性contentteditable =true来编辑它。

事例:https://codepen.io/shadeed/pen/3c1e8d7d69bcf03aa875e3e50d0ffe02?editors=1100

可访问性对display: none的影响

使用display:none时,它将对屏幕阅读器完全隐藏。

Opacity

通过将opacity度设置为0,该元素及其所有后代将被隐藏,并且不会被继承, 但是,它仅从视觉角度隐藏它们。 除此之外,opacity值为1以外的元素将创建一个新的堆叠上下文。

在上图中,蓝皮书仅在视觉上隐藏。 与使用display: none时发生的情况相比,它的空间仍然保留,并且堆栈顺序没有变化。

img {
    opacity: 0;
}

根据最初的示例,如果我们要隐藏不透明的图像,结果将如下所示:

该图像仍然存在,并且已保留其空间。 它仅从视觉角度隐藏。

更新:2020年1月13日

Dusan Milovanovic指出,pointer-events: none | auto可以用来禁用opacity0的隐藏元素上的鼠标事件。这一点很重要,因为用户可能会对单击、悬停或选择隐藏元素的文本感到困惑。

事例:https://codepen.io/shadeed/pen/4900ddd4a4d324cc531c1980088f775a?editors=1100

可访问性对opacity: 0的影响

一个元素以opacity: 0仍然可以被屏幕阅读器访问,并且可以用键盘进行聚焦。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

Visibility

通过使用visibility: hidden,我们可以显示或隐藏类似于使用opacity: 0的元素,而不会影响文档的视觉流。

请注意,蓝皮书是如何从可视流中隐藏的,但是它并没有影响图书堆栈的顺序。

当在父元素上使用visibility: hidden时,所有内容都是隐藏的,但是当该父元素的子元素具有visibility: visible时,将显示该子元素。

html

<article>
  <h1>Spring is on the way</h1>
  <img src="landscape.jpg" alt="">
  <p><!-- Desc --></p>
</article>

CSS

article {
    visibility: hidden;
}

img {
    visibility: visible;
}

在上面的例子中,<article>元素具有visibility: hidden。但是,添加visibility: visible可以让图片显示。同样,这是因为visibility应用于元素的后代,但是可以从具有该元素的子元素重写它。

事例源码:https://codepen.io/shadeed/pen/03caf6b36727accb692eecbc38f95d39?editors=1100

可访问性对visibility: hidden的影响

该元素被隐藏,其后代将从可访问性树中删除,并且屏幕阅读器不会渲染该元素。

Positioning

要隐藏带有position属性的元素,我们应该将它移到屏幕外,并将其大小设置为0(宽度和高度)。个例子就是跳转导航链接。考虑下面的图:

要将链接放置在屏幕之外,我们应该添加以下内容

css

.skip-link {
    position: absolute;
    top: -100%;
}

-100%将推动元素100%的视口高度。结果,它将被完全隐藏。一旦它聚焦在键盘上,它就会像这样显示出来

.skip-link:focus {
    position: absolute;
    top: 0;
}

事例源码:https://codepen.io/shadeed/pen/707992e7c98ea633fc6606e576ef8a04?editors=0100

可访问性对position: absolute | fixed的影响

屏幕阅读器可访问该元素,并且键盘可聚焦。 它只是从视口中隐藏起来。

Clip Path

当在元素上使用clip-path时,它创建一个裁剪区域,该区域定义应该显示和隐藏哪些部分。

在上面的例子中,透明的黑色区域有clip-path。当clip-path应用于元素时,透明黑色区域下的任何内容都不会显示。

为了更直观地演示以上内容,我将使用clippy工具。在下面的GIF中,我有如下的clip-path:

将每个方向的多边形值设置为0 0,则裁剪区域的大小将调整为0。结果,图像将不会显示。同样,这也可以用一个圆来代替多边形:

img {
    clip-path: circle(0 at 50% 50%);
}

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

可访问性对clip-path的影响

元素仅在视觉上隐藏, 屏幕阅读器和键盘焦点仍然可以使用它。

事例源码:https://codepen.io/shadeed/pen/9fdbd7be9fd9dac17a614c96ba7f64b1?editors=0100

控制颜色和字体大小

虽然这两种技术不像我们前面讨论的那样常见,但它们可能对某些用例有用。

颜色透明

通过使文本的颜色透明,它将隐藏在视觉上。这对于只有图标的按钮非常有用。

字体大小

此外,将字体大小设置为0也很有用,因为这会在视觉上隐藏文本。考虑下面的示例,其中有一个具有以下结构的按钮:

<button>
  <svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="false" focusable="false">
    <!-- Path data -->
  </svg>
  <span>Like</span>
</button>

我们的目标是以可访问的方式隐藏文本。为此,我添加了以下CSS

.button span {
    color: transparent;
    font-size: 0;
}

这样,文本就被隐藏了。 它甚至可以在不更改颜色的情况下工作,但是我出于解释目的添加了它。

事例源码:https://codepen.io/shadeed/pen/4eacdf50c3339fced7f787156c569372?editors=1100

Aria Hidden

当向元素添加aria-hidden属性时,它将从可访问性树中删除该元素,这可以增强屏幕阅读器用户的体验。注意,它并没有在视觉上隐藏元素,它只针对屏幕阅读器用户。

<button>
    Menu
    <svg aria-hidden="true"><!-- --></svg>
</button>

在上面的例子中,我们有一个带有标签和图标的菜单按钮。为了向屏幕阅读器隐藏图标,添加了aria-hidden

根据Mozilla Developer Network (MDN),下面是属性的用例

  • 隐藏装饰性的内容,如图标、图像。
  • 隐藏复制文本。
  • 隐藏屏幕外或折叠的内容。

可访问性对aria-hidden="true"的影响

是为屏幕阅读器设计的,因为它只对屏幕阅读器隐藏内容。然而,内容对于有视力的用户仍然是可见的,并且键盘是可聚焦的。

动画与互动

当我们想让一个隐藏的元素动起来时,例如,显示隐藏的移动导航,它需要以一种可访问的方式来完成。为了获得一种可访问的体验,我们将探索一些值得学习的好例子,以及一些不好的例子,以避免犯可能会给屏幕阅读器用户带来不好体验的错误。

#### 菜单动画-不好的例子

我们有一个菜单,在展开时需要有滑动动画。 最简单的方法是在菜单中添加以下内容:

ul {
    opacity: 0;
    transform: translateX(100%);
    transition: 0.3s ease-out;
}

ul.active {
    opacity: 1;
    transform: translateX(0);
}

有了上述内容,菜单将根据.active类展开和折叠,该类将通过 JavaScript 如下添加:

menuToggle.addEventListener('click', function(e){
  e.preventDefault();
  navMenu.classList.toggle('active');
});

结果可能看起来不错,但它有一个很大的错误。使用opacity: 0不会隐藏可访问性树的导航。即使导航在视觉上是隐藏的,它仍然可以通过键盘聚焦,并且可以被屏幕阅读器访问。必须将其隐藏以避免混淆用户。

下面是来自Chrome开发工具的 accessibility tree 的截图:

简而言之,accessibility tree是屏幕阅读器用户可以访问的所有内容的列表。在我们的例子中,导航列表在那里,而它在视觉上是隐藏的。我们需要解决两个问题:

1.菜单隐藏时避免用键盘聚焦
2.当导航隐藏时,避免通过屏幕阅读器告知导航

下面的屏幕截图显示了Mac OS上的VoiceOver转子是如何看到页面的。导航列表在那里,而它是隐藏的

事例源码:https://codepen.io/shadeed/pen/e94f377dae6104fe45a71c80d59bb58d?editors=0100

菜单动画-好的例子

为了修正这个错误,我们需要使用visibility: hidden作为导航菜单。这将确保菜单是隐藏的视觉和屏幕阅读器。

css

ul {
    visibility: hidden;
    opacity: 0;
    transform: translateX(100%);
    transition: 0.3s ease-out;
}

ul.active {
    visibility: visible;
    opacity: 1;
    transform: translateX(0);
}

添加后,菜单将从屏幕阅读器中隐藏。 让我们再次测试,看看VoiceOver将显示什么:

事例源码:https://codepen.io/shadeed/pen/e94f377dae6104fe45a71c80d59bb58d?editors=0110

自定义复选框

默认的复选框设计很难自定义,因此,我们需要为复选框创建自定义设计。让我们看看基本的 HTML:

<p class="c-checkbox">
  <input class="sr-only" type="checkbox" name="" id="c1">
  <label class="c-checkbox__label" for="c1">Custom checkbox</label>
</p>

要自定义复选框,我们需要以一种可访问的方式隐藏输入。为此,应该使用position和其他属性。有一个常见的CSS类,称为sr-onlyvisual -hidden,它只在视觉上隐藏一个元素,并让键盘和屏幕阅读器用户可以访问它。

.sr-only {
  border: 0; 
  clip: rect(0 0 0 0); 
  -webkit-clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
  clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
  height: 1px; 
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
  white-space: nowrap;
}

事例源码:https://codepen.io/shadeed/pen/b722aa72dbe3574617f6506d14e5ac03?editors=1100

#### 隐藏按钮

在Twitter上,有一个名为“查看新推文”(See New Tweets)的按钮,对于带有aria-hidden内容的屏幕阅读器来说是隐藏的,只有在有新推文可用时才会显示出来。


原文:https://www.sitepoint.com/hide-elements-in-css/

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug


交流

文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant