Tab functionality for a hover state

I am working on a component that displays a button and a link when hovered over. This is not a conventional menu, but rather a box located in the center of the page.

Considering accessibility guidelines, I want users to be able to tab into the container, which currently reveals its content with the .HiddenUntilHover class, and then continue tabbing to reach the button and link displayed during hover/focus state.

Presently, focusing on the container triggers the hover state; however, tabbing just moves to the next element without allowing access to the button or link WITHIN the hover state.

Here is a pseudo code example:

/* My component .jsx */
<div tabIndex="0" className="MainContainer">
 <div className="SomeOtherClass">
   <div className="HiddenUntilHover">
     /* Tabbable clickable items */
     <button>Click me!</button>
     <a href="...">I am also clickable</a>
   </div>
 </div>
</div>

And here's my SCSS snippet:

.HiddenUntilHover {
  display: none;
}

MainContainer:focus,
MainContainer:hover,
> .HiddenUntilHover {
    display: block
}

Answer №1

A few days back, I encountered a problem and resolved it by utilizing CSS classes to ensure that the content is accessible via keyboard navigation when hovered.

To achieve this functionality, I made use of CSS pseudo-classes to guarantee that the buttons inside the div element are displayed when active and focused. Specifically, incorporating :focus-within and :focus-visible ensures that the contents become visible and keyboard-accessible as you navigate through the list items using the tab key.

.MainContainer  {
  &:not(:hover, :focus, :active, :focus-visible, :focus-within) {
    .HiddenUntilHover {
      visibility: hidden;
    }
  }
}
<body>
    <div tabIndex="0" className="MainContainer">
        Content
        <div className="SomeOtherClass">
          <div className="HiddenUntilHover">
            <button>Click me!</button>
            <a href="...">I am also clickable</a>
          </div>
        </div>
      </div>
  </body>

For those interested, check out the Codesandbox demo showcasing this feature in action

Answer №2

When the box is in focus, tabbing to the button will cause the box to blur and hide, with its contents disappearing, so that focus can shift to the next accessible element. This seems to be the behavior you are encountering.

To address this issue, consider incorporating an aria-activedescendant or tabindex attribute when the box gains focus. Implementing this solution may require a bit of JavaScript.

It's important to note that you don't necessarily have to rely on the hover state to make that control accessible. One alternative approach involves including an offscreen (or clipped) button/link that is not a direct child of the hidden (display:none) box. If you opt for this method, be sure to familiarize yourself with the aria-owns attribute.

As long as the button or link is properly marked up (or has a tabindex="0" set), and isn't truly hidden from accessibility tools, it should be feasible to navigate to it using the tab key.

Answer №3

Consider adjusting the attributes within the MainContainer class to achieve the desired effect.

.MainContainer {
  width: 100%;
  height: 100px;
}
.MainContainer .HiddenUntilHover {
  display: none;
}
.MainContainer:hover .HiddenUntilHover, .MainContainer:focus .HiddenUntilHover {
  display: block;
}

Answer №4

Hover effects can pose accessibility challenges, as elements that appear on hover may not be easily accessible to all users. This becomes particularly problematic for keyboard navigation and touch screen devices like smartphones or tablets.

To address this issue, one approach is to use focusin and focusout events instead of relying solely on hover effects. By structuring your HTML code differently and adding some JavaScript, you can create a more accessible solution:

<div id="outer">
<div id="hover">
...
</div><!--hover-->
<button>Your button which only appears on hover</utton>
</div><!--outer-->

And in the JavaScript:

$('#outer').on('focusin', __=>$('#hover').classNames.add('keep-visible'));
$('#outer').on('focusout', __=>$('#hover').classNames.remove('keep-visible'));

This script will toggle a "keep-visible" class when an element within #outer receives focus, making the hidden element visible. The class is removed when focus leaves the last element within #outer.

While onfocusin/out events are not standard, they are widely supported by major browsers, including IE. Firefox introduced support in version 52.0, indicating their importance for accessibility and usability.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring NextJS with Typescript

Struggling to incorporate Typescript with NextJS has been a challenge, especially when it comes to destructured parameters in getInitialProps and defining the type of page functions. Take for example my _app.tsx: import { ThemeProvider } from 'styled ...

What is the best way to determine the width of a device, rather than just the

I'm currently working on my debut website and I’ve encountered a minor setback with the meta tag. It seems to be defining a fixed width instead of adapting to the device screen, which is hindering my CSS animation endeavors. Most of the design displ ...

Automatically remove the entered data

Let's say I have a text input field with the initial value of "insert text here" coded like this: <input type="text" value="insert text here" /> What I want is for the text inside the input field to disappear automatically when the user clicks ...

Can Page Transitions be implemented when linking to an external website?

I am aiming to create a login page that, when the user clicks the login button, redirects them to a web application via a different URL. I've observed that elaborate full-page transitions (like those shown in this example) are typically achieved by ma ...

Guide on adjusting the height of the material ui popover that appears when an option is selected

I'm looking to adjust the height of a popover that opens when an item is selected in material ui. I attempted to apply styles using the classes property, but it didn't work. How can I specify styling for a component that appears when clicked on? ...

Performing React axios requests to an Express API on a Heroku server deployment

I have been working on a React todo app that I created using create-react-app. In order to retrieve all the appointment objects, I built a simple express server that queries mongoDB. It functions perfectly when running locally on my machine - with the fron ...

The last image in the Bootstrap 4 carousel maintains a wider width than the slider itself, not resizing to fit within the slider during animations when the screen is adjusted

Check out my Bootstrap 4 carousel slider on this link. The slider consists of 3 slides, but for optimal page speed performance, I've included 5 images of different sizes that load at specific screen widths. This was achieved using the <picture> ...

Is there a way to set the starting position of the overflow scroll to the middle?

Is there a way to have the overflow-x scrollbar scroll position start in the middle rather than on the left side? Currently, it always begins at the left side. Here is what it looks like now: https://i.stack.imgur.com/NN5Ty.png If anyone knows of a soluti ...

What is the best way to vertically center my text on the right and left sides of an image?

I am struggling to align the text on the left and right side of my image to the vertical center. It seems like my containers are not recognizing their height. How can I resolve this issue? Here are the CSS and HTML snippets for your reference: .footer { ...

What is the best way to retrieve the current route or path using typescript?

When using standard React, you would simply use this.props.location.pathname. How can I achieve the same with TypeScript? ...

The FileReader encountered an error because the first parameter is not a 'Blob' type

I seem to be encountering an issue with a javascript FileReader that is throwing the error Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'. This problem occurs intermitt ...

Eliminate the need for pressing the "tab" key on my website

I'm currently working on a horizontal web page layout and I'm looking for a way to disable the "tab" button functionality on my page. The issue arises because I have a contact form with textboxes located in the last div, and when users navigate u ...

Limit the size of images with CSS properties like max-height or max-width

What is the preferred method for restricting the size of an image and why? While max-width can be used to restrict the size of an element, this article recommends using it specifically for images within containers. If you have a web application with a ve ...

Switch background color multiple times on click using JavaScript loop

Hello amazing people! I have a container with 52 small boxes and one large box containing a letter. The smaller boxes are arranged around the larger one using CSS grid, and when hovered over, they turn light grey. My Objective When any of the 52 small b ...

Tips on modifying the background color of a read-only field in an edit form

Changing the background color of a readonly field in the edit form of Free jqgrid can be a challenge. One potential solution involves specifying a style: .jqgrid-readonlycolumn { background-color: #FFFFDD; } This style is then used in the colmodel e ...

Utilizing React to send email communications

My current stack includes Next Js for the front end, Nest Js for the back end, and AWS SES v2 for email services. I am currently sending emails using EJS templates generated in the back end. I am interested in making the switch to React Emails, which are ...

"Experiencing a problem with Next.js 13 where the User Context is not functioning properly outside of _app

When using Next.js 13 and the user context, I've noticed that it doesn't function properly outside of _app.tsx. Any idea why? src>context>UserPositionContext.tsx import { createContext, useContext, useState } from "react"; const ...

What are the consequences of directly modifying prevState in React's setState method?

As I was reviewing some React code examples (from the antd docs), a particular piece caught my eye. It appeared to be equivalent to: this.setState(prevState => { prevState.name = "NewValue"; return prevState; }); At first glance, this approach seemed ...

When implementing javascript_pack_tag in Rails, an EOFError may occur

It seems like the files in public/packs/js are having trouble loading. Here are the javascript tags being used in the view: = javascript_include_tag 'application' = javascript_pack_tag 'application' The error displayed in the browser ...

Is it possible for me to designate a specific class for the rev value?

<a href="img1.jpg" rel="zoom-id:bike" rev="img1.jpg"> <img src="" class="img-thumb"/></a> Shown above is a snippet of HTML code. I wonder if it's possible for the attribute rev="img1.jpg" to have a class that only affects the s ...