Skip to main content
Start of main content.

So many ways to hide

by rikki.bochow /

Share this post on social media

Generally speaking hiding content goes alongside a bit of javascript that unhides the content under certain circumstances (think hamburger menu). Sometimes the content improves accessibility but is considered visual noise (says the designer). So as the developer you have a lot of ways to approach this.

Hiding with Javascript

jQuery gives us .hide(), .fadeOut() and .slideUp() to use, which all use the CSS rule display:none.

Now display:none is a very effective way of hiding things but it has some caveats;

  • Screen readers cannot see it or any of it's children.
  • Any focusable children (like fields or links) are no longer focusable.
  • When used inline, as these jQuery functions do, it can only be undone by disabling Javascript or using .hide(), .fadeOut() or .slideUp(). **plus inline CSS = yuck!**

Hiding with Classes


Drupal 7 provides the .element-hidden class which also uses display:none but having it on a class means we have more control.

Disabling Stylesheets will show what was hidden, though disabling Javascript will only show the hidden element if the .element-hidden class was added by Javascript in the first place.

Using classes in jQuery is super easy, instead of .show() and .hide() you can do it all in one line with .toggleClass()

.element-hidden {


The Zen themes starterkit gives us the .hidden class which is EXACTLY the same as .element-hidden but shorter and easier to remember. The simplified class name also reflects a change in Drupal 8 core.

.hidden {


Zen also adds the .js-hidden class which is also the same as .element-hidden but uses the .js class that Drupal adds to the HTML element to check that Javascript is enabled in the browser.

So .js-hidden will ONLY hide something if Javascript is enabled, which solves caveat 3!

html.js .js-hidden {

But what about screen readers and focus?

Hiding without hiding


So Drupal 7 also provides the .element-invisible class which DOES NOT use display:none but instead hides the element with CSS by more or less making it really really small so you just can't see it.

But screen readers completely ignore this CSS and can read the content normally. This is great for hidden text content like in inactive Tabs, and even better for those social media icons which really should have some "Follow me I'm amazing" content.

Anything focusable inside it is also still focusable! Also great for those links in your hamburger menu. Though extra care does need to be taken here...

Focusing on something that is visually hidden creates a "keyboard trap" for any sighted keyboard navigators, because they cannot see where the focus has gone.

They have to continue tabbing past the hidden element to get it back. One workaround is to use Javascript to remove the .element-invisible class if it or any of it's children have focus.

It's also worth noting that unless the class was added by Javascript, disabling Javascript will have no affect on the hidden element.

.element-invisible {
 position: absolute !important;
 clip: rect(1px, 1px, 1px, 1px);
 overflow: hidden;
 height: 1px;


This one, like .hidden is provided by Zen and is basically the same as .element-invisible but again, easier to remember and matches Drupal 8.

It also describes the behaviour a bit better, in that is really is only visually hidden, and not hidden in any other way.

.visually-hidden {
 position: absolute !important;
 clip: rect(1px, 1px, 1px, 1px);
 overflow: hidden;
 height: 1px;
 width: 1px;


Another Drupal 7 class, this one requires the .element-invisible class to also be on the same element, and uses CSS to make is visible again but only on focus.

Perfect for "Skip links" and the like. Though a child element that is focusable (like a hidden forms fields) is still hidden, we still need Javascript to fix that.

.element-invisible.element-focusable:focus {
  position: static !important;
  clip: auto;
  overflow: visible;
  height: auto;


A simplification of .element-focusable, provided by Zen, that moves everything to one class. This one differs from the changes in Drupal 8 slightly by combining the classes but follows the BEM Modifier naming pattern.

.visually-hidden--focusable {
 @extend .visually-hidden;
 &:focus {
   position: static !important;
   clip: auto;
   height: auto;
   width: auto;
   overflow: auto;


Avoid using the jQuery functions entirely. If fading or sliding animations are needed your friendly front-end team can do them in CSS.

Overall the ones in Zen should be used over the ones provided by Drupal for consistency sake, and that they can be configured.

  • If you are toggling visibility in Javascript and you know it shouldn't be focusable use .js-hidden
  • If you are toggling visibility in Javascript and it's content DOES need to be focusable make sure you remove the class from the parent on focus.
  • If you are hiding text content but want unsighted people to access it use .visually-hidden
  • If you are hiding a focusable element itself, and want sighted keyboard users to interact with it use .visually-hidden--focusable