I've been stuck with a problem with my custom WordPress theme for a long time.
As you might know, you need to be able to navigate the menu using keyboard only. This is possible in my case.
However, I can't see the submenu while I'm moving through it using tab. I know it moves through the menu because when I've hit tab for every submenuitem there is, the visual cue for being focused moves to next parent menu item.
Also if I remove some of the styling so that I can see all menu items at all times (which isn't very practical), it works just fine.
I hide the submenu by default using left: -999em;. then when I hove over its parent menu item, I bring the submenu to view by using left:0;.
This works perfectly using :hover, but not with :focus. Can anyone tell me why? Here is some of my css.
header .navigation li{
position: relative;
}
header .navigation li .sub-menu {
position: absolute !important;
z-index: 999;
top: 100%;
left: -999em;
background-color: lightgray;
box-shadow: 1px 1px 10px rgba(0,0,0,0.1);
margin: 0;
padding: 0;
list-style-type: none;
width: 200px;
border-radius: .5rem;
}
header .navigation li .sub-menu a{
display: block;
padding: .25rem;
text-align: center;
text-decoration: none;
}
header .navigation li .sub-menu a:hover,
header .navigation li .sub-menu a:focus
{
color: white; /* BOTH WORK*/
}
header .navigation > .menu-item-has-children:hover > .sub-menu,
header .navigation > .menu-item-has-children:focus > .sub-menu
{
left: 0; /* ONLY THE :HOVER WOKRS */
}
Hope I explained this well enough (my first post here lol).
Testing the minimal working example.
header .navigation {
list-style: none;
margin: 0;
display: flex;
justify-content: left;
align-items: center;
width: 900px;
word-break: keep-all;
}
header .navigation li a {
padding: .25rem 1rem;
color: #000;
width: 100%;
}
header .navigation li:first-child a {
padding-left: 0;
}
header .navigation li {
position: relative;
}
header .navigation li .sub-menu {
position: absolute !important;
z-index: 999;
top: 100%;
left: -999em;
background-color: lightgray;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.1);
margin: 0;
padding: 0;
list-style-type: none;
width: 200px;
border-radius: .5rem;
}
header .navigation li .sub-menu:focus {
left: 0;
}
header .navigation li .sub-menu a {
display: block;
padding: .25rem;
text-align: center;
text-decoration: none;
}
header .navigation li .sub-menu a:hover,
header .navigation li .sub-menu a:focus {
color: white;
/*BOTH WORK*/
}
header .navigation>.menu-item-has-children:hover>.sub-menu,
header .navigation>.menu-item-has-children:focus>.sub-menu {
left: 0;
/* ONLY THE :HOVER WOKRS */
}
<header >
<div >
<h1>test</h1>
<div >
<ul id="menu-all-pages" >
<li id="menu-item-1636" ><a href="http://wpthemetestdata.wordpress.com/">Home</a></li>
<li id="menu-item-1637" ><a href="http://localhost/wordpress/?page_id=703">Blog</a></li>
<li id="menu-item-1638" ><a href="http://localhost/wordpress/?page_id=701">Front Page</a></li>
<li id="menu-item-1639" ><a href="http://localhost/wordpress/?page_id=2">About The Tests</a>
<ul tabindex="0">
<li id="menu-item-1760" ><a href="http://localhost/wordpress/?page_id=1133">Page Image Alignment</a></li>
<li id="menu-item-1761" ><a href="http://localhost/wordpress/?page_id=1134">Page Markup And Formatting</a></li>
<li id="menu-item-1640" ><a href="http://localhost/wordpress/?page_id=501">Clearing Floats</a></li>
<li id="menu-item-1641" ><a href="http://localhost/wordpress/?page_id=155">Page with comments</a></li>
<li id="menu-item-1642" ><a href="http://localhost/wordpress/?page_id=156">Page with comments disabled</a></li>
</ul>
</li>
<li id="menu-item-1643" ><a href="http://localhost/wordpress/?page_id=174">Level 1</a>
<ul >
<li id="menu-item-1644" ><a href="http://localhost/wordpress/?page_id=173">Level 2</a>
<ul >
<li id="menu-item-1645" ><a href="http://localhost/wordpress/?page_id=172">Level 3</a></li>
<li id="menu-item-1762" ><a href="http://localhost/wordpress/?page_id=746">Level 3a</a></li>
<li id="menu-item-1763" ><a href="http://localhost/wordpress/?page_id=748">Level 3b</a></li>
</ul>
</li>
<li id="menu-item-1764" ><a href="http://localhost/wordpress/?page_id=742">Level 2a</a></li>
<li id="menu-item-1765" ><a href="http://localhost/wordpress/?page_id=744">Level 2b</a></li>
</ul>
</li>
<li id="menu-item-1646" ><a href="http://localhost/wordpress/?page_id=146">Lorem Ipsum</a></li>
<li id="menu-item-1766" ><a href="http://localhost/wordpress/?page_id=733">Page A</a></li>
<li id="menu-item-1767" ><a href="http://localhost/wordpress/?page_id=735">Page B</a></li>
</ul>
</div>
</div>
</header>
CodePudding user response:
You should add tabindex='0'
property to the .sub-menu
element if you haven't to make it focusable. Not all elements are focusable. :focus
on <a>
tag works because it is focusable as long as it has either href
or tabindex
attribute. Refer here for more on tabindex.
Edit: I have checked the code and it looks like you want the .sub-menu
to stay visible when the links inside it are focused as well. So add this style for that and it should work. You want the left position of the .sub-menu
to be 0 as long as the links inside it are focused.
header .navigation > .menu-item-has-children > .sub-menu:focus-within {
left: 0;
}
CodePudding user response:
I took the liberty to re-write the code a bit since there was a lot of noise. If you can, next time only post the code that is absolutely necessary to demonstrate the problem :).
Since the code is now different from yours, you might need to make some changes. If you are unable to apply them, please leave a comment, and I'll see if I can adapt it more closely to what you posted.
ul {
list-style: none;
padding: 0;
}
.nav {
display: flex;
background-color: gray;
}
.nav li {
flex: 1;
}
.about-the-tests {
position: relative;
}
.sub-menu {
position: absolute;
visibility: hidden;
}
/* Opens the menu when the "About the Tests" link is focused */
.about-the-tests a:focus .sub-menu,
/* Keeps the menu open when a link is focused inside it */
.about-the-tests:focus-within .sub-menu {
visibility: visible;
}
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<ul >
<li><a href="https://example.com">Home</a></li>
<li><a href="https://example.com">Blog</a></li>
<li><a href="https://example.com">Front Page</a></li>
<li >
<a href="https://example.com">About the Tests</a>
<ul >
<li><a href="https://example.com/page_image_alignment">Page Image Alignment</a></li>
<li><a href="https://example.com/page_markup_and_formatting">Page Markup And Formatting</a></li>
<li><a href="https://example.com/clearing_floats">Clearing Floats</a></li>
<li><a href="https://example.com/page_with_comments">Page with comments</a></li>
<li><a href="https://example.com/page_with_comments_disabled">Page with comments disabled</a></li>
</ul>
</li>
<li><a href="https://example.com">Level 1</a></li>
</ul>
</body>
</html>
The main thing I added was the focus-within
pseudo class.
I also changed how the display is hidden. Now it's hidden using the visibility
property. You can also try it with the display
property, but I don't know how well screen readers deal with that. Anyway, I think both of those approaches are cleaner than moving the elements off the screen.
Also: Try avoiding !important
. It's almost always a mistake in your CSS, as later CSS rules may always overwrite previous ones.