惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
Lohrmann on Cybersecurity
Martin Fowler
Martin Fowler
Engineering at Meta
Engineering at Meta
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
TaoSecurity Blog
TaoSecurity Blog
博客园_首页
Vercel News
Vercel News
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
The Exploit Database - CXSecurity.com
量子位
Project Zero
Project Zero
A
Arctic Wolf
小众软件
小众软件
NISL@THU
NISL@THU
C
CERT Recently Published Vulnerability Notes
有赞技术团队
有赞技术团队
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
News and Events Feed by Topic
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
P
Privacy & Cybersecurity Law Blog
Security Latest
Security Latest
B
Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
Schneier on Security
Schneier on Security
The Hacker News
The Hacker News
K
Kaspersky official blog
C
Check Point Blog
Hacker News: Ask HN
Hacker News: Ask HN
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Webroot Blog
Webroot Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
人人都是产品经理
人人都是产品经理
AI
AI
Cisco Talos Blog
Cisco Talos Blog
MyScale Blog
MyScale Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
S
Schneier on Security
P
Palo Alto Networks Blog

Ahmad Shadeed

Better fluid sizing with round() Use Cases for Field Sizing The Basics of Anchor Positioning Item Flow CSS Relative Colors Balancing Text In CSS Should masonry be part of CSS grid? CSS display contents CSS Grid Areas CSS Cap Unit An Interactive Guide to CSS Container Queries CSS :has() Interactive Guide CSS Nesting UX in DevTools CSS Nesting Future CSS: State Container Queries Rebuilding a comment component with modern CSS Conditional CSS with :has and :nth-last-child CSS Text balancing with text-wrap:balance CSS Masking Do we need CSS flex-wrap detection? My CSS Wishlist Conditional CSS CSS Style Queries Inside the mind of a frontend developer: Article layout Inside the mind of a frontend developer: Hero section CSS container queries are finally here The CSS behind Figma First Look At The CSS object-view-box Property Learn CSS Subgrid CSS :has Parent Selector Aligning Content In Different Wrappers Flexbox Dynamic Line Separator Hello, CSS Cascade Layers Building UI Components With SVG and CSS A Deep CSS Dive Into Radial And Conic Gradients Defensive CSS Building Real-life Components: Facebook Messenger Conditional Border Radius In CSS CSS Container Query Units Less Absolute Positioning With Modern CSS Aligning a Button Label Vertically Comparing Design Mockups To Code Result Using HSL Colors In CSS Custom Scrollbars In CSS Let CSS Container Queries For Designers The State of CSS Cross-Browser Development Overflow Issues In CSS Inspect Element As A Way To Increase Your Curiosity Handling Text Over Images in CSS Digging Into CSS Logical Properties Clipping Scrollable Areas On The inline-start Side Understanding Clip Path in CSS The Art of Building Real-life Components Handling Short And Long Content In CSS CSS Scroll Snap A Deep Dive Into CSS Grid minmax() CSS Variables 101 Finding The Root Cause of a CSS Bug Learn CSS centering How to detect browser support for Flexbox Gap CSS Mistakes While On Autopilot Digging Into the Flex Property Understanding CSS Multiple Backgrounds Aligning Logo Images in CSS Grid for layout, Flexbox for components Colors in CSS Thinking About The In-between Design Cases min(), max(), and clamp() CSS Functions Image Techniques On The Web Everything About Auto in CSS Learn Box Alignment Let Learn CSS Positioning Intrinsic Sizing In CSS CSS Grid Template Areas In Action Creating a Variable Color Font From Scratch Building a Football Ticket With CSS and SVG Blending Modes in CSS CSS Variables With Inline Styles Implementing Dark Mode For My Website Rebuilding Apple Music Header in HTML & CSS Accessible Checkbox Layout Flickering On Browser Resize Enhancing The Clickable Area Size Custom Underlines with SVG Part 3: The Process of Implementing A UI Design From Scratch Part 2: The Process of Implementing A UI Design From Scratch Building An Old Nav Design CSS Flexbox: 5 Real World Use Cases I Used CSS Inline Flex For The First Time The Process of Implementing A UI Design From Scratch Common CSS Issues For Front-End Projects Handling Long and Unexpected Content in CSS How to Build Web Form Layouts With CSS Grid Grid Layout Ah-ha Moment Enhancing Our Components with CSS :empty Building Resizeable Components with Relative CSS Units CSS Writing Mode The Journey of Learning Front End Web Development on a Daily Basis
Hiding Elements On The Web
Ahmad Shadeed · 2020-01-12 · via Ahmad Shadeed

The Layout Maestro

I spent years teaching CSS layout on this blog. I put everything I know into The Layout Maestro course: 70+ lessons and 150+ interactive examples that teach you how to think CSS layouts, not just memorize syntax.

Get the course

Through our work as web developers, we need to hide elements for many reasons. For example, a button that should be visible in a mobile viewport, and hidden in a desktop viewport. Or, a navigation element that is hidden on mobile and shown on the desktop. There are three different states when hiding an element:

  • An element is completely hidden and removed from the document flow.
  • An element is hidden visually only, and still accessible to assistive technology (AT) like screen readers.
  • An element is visible, but is only hidden for screen readers.

In this article, we will learn about hiding elements in HTML&CSS and covering the aspects of accessibility, animation and use cases for hiding. Let’s dive in!

Table of Contents

  • HTML5 Hidden Attribute
  • CSS Display Property
    • Do Resources Load If They Were Hidden With CSS?
    • The Style Element
  • Opacity
  • Visibility
  • Positioning
  • Clip Path
  • Manipulating Color and Font Size
    • Color Transparent
    • Font Size
  • Aria Hidden
  • Animation and Interactivity
    • Menu Animation - Bad Example
    • Menu Animation - Good Example
    • Custom Checkbox
  • Hiding Content From Screen Readers
    • Hiding Buttons
    • Hiding Decorative Content
  • Related Reads

It’s a boolean HTML attribute that hides the element attached to it. When the browser loads a web page, it won’t render the elements with hidden attribute unless that is overridden manually from CSS. It’s similar to the effect of applying display: none for an element.

Consider the following example.

We have a title, a figure, and a description. The figure should be only shown if the viewport width is larger than 400px. I added the hidden attribute to the <img> element.

In CSS, I used the hidden attribute to show the element only in the desired viewport size.

img[hidden] {
  display: none;
}

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

Demo

Well, you might be wondering, why not use display: none? Good question. When the image selector is called via its hidden attribute, we can be sure that even if CSS didn’t load for some reason, the element will be hidden.

Accessibility Implications For hidden

From an accessibility perspective, hidden hides the element completely from a web page, so it won’t be accessible to screen readers. Be sure to avoid using it to hide elements for presentational purposes only.

CSS Display Property

Each element has a default display value like inline-block, block, table..etc. To hide an element with the display property, we should use display: none. When an element is hidden with display: none, all of its descendants will be removed along with it.

Consider that we have the same example as above, and we want to hide the image.

img {
  display: none;
}

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

This will hide the image completely from the document flow, and from screen readers. Maybe you’re wondering what’s the document flow? See the below illustration:

Notice when the blue book is hidden, it has been removed completely from the stack. The space that was preserved for it is gone. The same concept applies when hiding elements in the HTML. The reserved space for the element is gone, and it changes the document flow, or in our example, the stack of books flow.

Here is an animation showing what happen when a book is removed:

Do Resources Load If They Were Hidden With CSS?

Yes, this is the short answer. For example, if an <img> is hidden with CSS, and we show it at a certain breakpoint, it will be loaded already. The image will cause an HTTP request even if it’s hidden with CSS.

In this demo, I added an image only and hide it with CSS. Then, I opened DevTools and checked the networks tab which shows that the image is loaded.

We will come back to this later to explain how to reduce HTTP requests when they’re not needed in a specific breakpoint or viewport size.

The Style Element

It’s worth mentioning that there are elements with display: none as their default value. The <style> element can be added inside an HTML page, and we can change its display property to block so it can be visible.

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

This is useful in case you want to have the style block always visible and editable. It can be editable by adding the attribute contenteditable=true to the style tag.

Demo

Accessibility Implications For display: none

When using display: none, it hides the element completely from screen readers.

Opacity

By setting the opacity to 0, the element and all of its descendants will be hidden, and it’s not inherited. However, it hides them only from a visual perspective. Adding on that, an element with opacity value other than 1 will create a new stacking context.

In the figure above, the blue book is hidden visually only. Its space is still reserved for it, and the stack order didn’t change, compared to what happened when we used display: none.

img {
  opacity: 0;
}

Based on our initial example, if we want to hide the image with opacity, the result will look like this:

The image is still there and its space is reserved. It’s hidden only from a visual perspective.

UppubDate: 13 Jan 2020

Dusan Milovanovic pointed out that pointer-events: none | auto can be used to disable mouse events on elements hidden with opacity: 0. This is important as it might be confusing to the user to click, hover, or select the text of a hidden element.

Demo

Accessibility Implications For opacity: 0

An element is hidden with opacity: 0 will still be accessible to screen readers, and focusable with the keyboard.

Visibility

By using visibility: hidden, we can show or hide elements similar to using opacity: 0, without affecting the visual flow of the document.

Notice how the blue book is hidden from the visual flow, but it didn’t affect the order of the book stack.

However, when visibility: hidden is used on the parent element, everything is hidden, but when a child element of this parent has visibility: visible applied to it, that child will be shown.

<article>
  <h1>Spring is on the way</h1>
  <img src="landscape.jpg" alt="" />
  <p><!-- Desc --></p>
</article>
article {
  visibility: hidden;
}

img {
  visibility: visible;
}

In the example above, the <article> element has visibility: hidden with it. However, adding visibility: visible to the image made it visible. Again, that’s because visibility applies to element’s descendants, but it can be overridden from a child element with that element.

Demo

Accessibility Implications For visibility: hidden

The element is hidden and its descendants will be removed from the accessibility tree, and it won’t be announced by screen readers.

Positioning

To hide an element with the position property, we should move it off-screen, and set its size to zero (width and height). An example of that is a skip navigation link. Consider the following figure:

To position the link off-screen, we should add the following:

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

The value -100% will push the element 100% of the viewport height. As a result, it will be hidden completely. Once it’s focused on the keyboard, it can be shown like this:

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

Demo

Accessibility Implications For position: absolute | fixed

The element is accessible to screen readers, and keyboard focusable. It’s only hidden visually from the viewport.

Clip Path

When clip-path is used on an element, it creates a clipping region that defines what the parts should be shown and hidden.

In the above example, the transparent black region has clip-path. When the clip-path is applied to the element, anything under the transparent black area won’t be shown.

To demonstrate the above in a more visual way, I will use clippy tool for that. In the GIF below, I have the following clip-path:

img {
  clip-path: polygon(0 0, 0 0, 0 0, 0 0);
}

Setting the polygon values to 0 0 for each direction will resize the clipping region to zero. As a result, the image won’t be shown. Also, this can be done using a circle instead of a polygon:

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

Accessibility Implications For clip-path

An element is only hidden visually. It’s still accessible to screen readers and keyboard focus.

Demo

Manipulating Color and Font Size

While those two techniques are not common as the previous one we discussed, they might be useful for some use cases.

Color Transparent

By making the color transparent for a text, it will be hidden visually. This can be useful for an icon-only button.

Font Size

Also, it can be useful to set the font size to zero as this will hide the text visually.

Consider the following example where we have a button with the below structure:

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

Our goal is to hide the text in an accessible way. To do that, I added the following CSS:

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

And with that, the text is hidden. It can even work without changing the color, but I added it for explanation purposes.

Demo

When adding aria-hidden attribute to an element, it removes that element from the accessibility tree, which can enhance the experience for screen reader users. Note that it doesn’t hide the element visually, it’s only for screen reader users.

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

In the example above, we have a menu button with a label and an icon. To hide the icon from screen readers, aria-hidden is added for that purpose.

According to Mozilla Developer Network (MDN), the below are uses cases for the attribute:

  • Hide decorative content like icons, images.
  • Hide duplicated text.
  • Hide off-screen or collapsed content.

Accessibility Implications For aria-hidden="true"

It’s designed for screen readers as it hides content from screen readers only. However, the content is still visible for sighted users and keyboard focusable.

Animation and Interactivity

Before we start with the examples, I want to highlight the properties mentioned previously to compare them and pick the appropriate method based on our needs. The cheatsheet is inspired by this great article on CSS-Tricks.

See the Pen Hiding On The Web by Ahmad Shadeed (@shadeed) on CodePen.

When we want to animate an element that is hidden, for example, show hidden mobile navigation, it needs to be done in an accessible way. In order to make an accessible experience, we will explore some good examples to learn from, and bad examples, to avoid making mistakes that could lead to a bad experience for screen reader users.

We have a menu that needs to have a sliding or off-canvas animation when it’s expanded. The easiest thing to do is to add the following to the menu:

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

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

With the above, the menu will expand and collapse based on the class .active that will be added via JavaScript as below.

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

The result might seem good, but it has a big mistake. Using opacity: 0 won’t hide the navigation from the accessibility tree. Even if the navigation is hidden visually, it’s still focusable via keyboard, and accessible for screen readers. It must be hidden to avoid confusing the user.

Here is a screenshot of the accessibility tree from Chrome’s DevTools:

In short, the accessibility tree is a list of everything a screen reader user can access. In our case, the navigation list is there while it’s visually hidden. There are two issues we need to solve:

  1. Avoid focusing with keyboard when the menu is hidden
  2. Avoid announcing the navigation by a screen reader when it’s hidden

The screenshot below shows how the VoiceOver rotor on Mac OS sees the page. The navigation list there while it’s hidden visually!

Demo

To fix that mistake, we need to use visibility: hidden for the navigation menu. This will ensure that the menu is hidden visually and for screen readers.

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

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

Once that is added, now the menu is hidden from screen readers. Let’s test again and see what VoiceOver will show:

Demo

Custom Checkbox

The default checkbox design is hard to customize, and as a result, we need to create a custom design for a checkbox. Let’s see the basic 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>

To customize the checkbox, we need to hide the input in an accessible way. To do so, position along with other properties should be used. There is a common CSS class called sr-only or visually-hidden, that hides an element only visually, and keep it accessible for keyboard and screen reader users.

.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;
}

With that, the custom checkbox is accessible. If you want to learn more, I wrote an article about that topic.

Demo

Hiding Content From Screen Readers

In the cheatsheet title, I added an Emoji after the heading element. If this is not hidden properly, here is how a screen reader will read it:

Hiding On The Web grinning face with open mouth

Since each Emoji has a specific description attached to it, the screen reader will try to announce that. Now, imagine that you are browsing the web and suddenly, you hear that title! It’s very confusing. To avoid such confusion for the user, aria-hidden should be used. I will wrap the Emoji in a <span> element, and then hide it for screen readers only.

<h1>Hiding On The Web <span aria-hidden="true">😃</span></h1>

Small change, big win!

Hiding Buttons

On Twitter, there is a button labeled “See New Tweets” that is hidden for screen readers with aria-hidden, and is shown only visually when new tweets are available.

Hiding Decorative Content

The dot between the user handle and the date is decorative. As a result, it has aria-hidden="true" to avoid announcing “dot” for screen readers.

The End

And that’s a wrap. Do you have a comment or a suggestion? Please feel free to ping me on @shadeed9.