CSS Target Pseudo Class

Creating a Menu

Introduction

There are accessibility problems with the hidden checkbox hack used for many CSS only menus, including the one at the top of this page. Over the years, I have redesigned the site several times and apart from somaller details it was nearly always to try and improve the site's menu system. In March 2025, I rewrote a page showing how to use the <details> tag to create a horizontal drop-down menu.

While I was rewriting the details menu page I started thinking of other ways to toggle the menu divs without using the hidden checkbox or using JavaScript.


Testing

This page was tested in Chrome (134.0.6998.36), Edge (134.0.3124.66), Firefox (136.0.1) and Opera (117.0.5408.53).


The CSS Target Psuedo Class

The CSS target psuedo-class is used to style a currently active element as in these examples from MDN Web Docs and W3Schools.

I was thinking about those pages and thought that the CSS display property could be manipulated to show or hide the menu submenus and started looking around for ways to do that. It seems I was not the first to think of this and found examples on Deepu Balan, Stack Overflow, W3.org and W3Schools

Oh well. But, some of the above examples do not behave as I think they should. Some only display the menu while they are being hovered over and some will not close the submenu when the menu button is clicked on again, requiring a "Clear" option.

One possible problem with this type of menu is that they add the anchors to the browser address bar, such as "brisray.com/web/target-menu.htm#submenu1". As far as I know there is no easy way of addressing this without rewriting the address.

The number of columns in the submenus can be changed using media queries, for example:

@media screen and (max-width : 600px) {
	.submenu ul { column-count: 3; }
}

Let's see if I can come up with something that works as I expect.

In the following examples the submenus come from an unordered list that I use for all the menus. I insert them on the server side using Apache's #include virtual directive, but they can come from anywhere available.


A Menu

This menu is based on the code on W3Schools. I have added a "Close Menu" option.

The HTML for the above menu is:

<div id="menubara">
	<div class="menuitema"><a href="#submenua1">All Sections</a><a href="#submenua2">Web Section</a><a href="#/">Close Menu</a></div>
	<div class="submenua" id="submenua1"><!--#include virtual="/inc/main_menu.htm" --></div>
	<div class="submenua" id="submenua2"><!--#include virtual="/web/inc/web_menu.htm" --></div>
</div>

THe CSS for it is:

<style>
	#menubara {
		width: 100%;
		background-color: midnightblue;
		font-family: Arial, Helvetica, sans-serif;
		font-size: 1.2em;
	}

	.menuitema {
		display:inline-block;
		width: fit-content;
	}

	.menuitema a { 
		text-decoration: none; 
		color: white;
		padding: 4em 2em
	}
			
	.menuitema a:hover { color: cyan; }

	.submenua {	
		display: block;
		cursor: pointer;
		background-color: midnightblue;
		display: none;
	}

	.submenua a:hover, .submenua a:focus  { color: cyan; }
	
	.submenua ul { column-count: 5; }
 
	.submenua li {
		list-style-type: none;
		display: block;
	}
	
	.submenua a {
		text-decoration: none; 
		color: white;
	}

	#menubara div:target { display: block; }
	</style>

In the above menu the "Close Menu" option works by providing a blank anchor tag. The problem with using just "#" is that page will scroll back to the top of the page. If the menu is near the top of the page this should not be a problem, but to stop it from happening then any non-existent anchor on the page can be used. Most use "#a" or "#/"


Another Menu

This menu is adapted from the code on Stack Overflow. This menu opens and closes the submenus when clicked on.

The HTML for the above menu is:

<div id="showdiv1"></div>
<div id="showdiv2"></div>
<div>
<div id="menubarb">
	<a href="#showdiv1" class="clicker" tabindex="1">All Sections</a>
	<a href="#hidediv1" class="clicker hidden" tabindex="1">All Sections</a>
		  
	<a href="#showdiv2" class="clicker" tabindex="2">Web Section</a>
	<a href="#hidediv2" class="clicker hidden" tabindex="2">Web Section</a>
</div>
		  
<div class="hiddendiv sm1"><!--#include virtual="/inc/main_menu.htm" --></div>
<div class="hiddendiv sm2"><!--#include virtual="/web/inc/web_menu.htm" --></div>
</div>

THe CSS for it is:

<style>
#menubarb {
	width: 100%;
	background-color: midnightblue;
	color: white;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 1.2em;
}

#menubarb a:hover, #menubarb a:focus { color: cyan; }

.clicker {
	display: inline-block;
	color: white;
	padding: 0.4em 1em;
	text-decoration: none;
}
	
.clicker.hidden { display: none; }

.hiddendiv {
	height: 0px;
	overflow: hidden; 
	font-family: Arial, Helvetica, sans-serif;
	font-size: 1.2em;
}
	  
#showdiv1:target ~ div a[href="#showdiv1"], #showdiv2:target ~ div a[href="#showdiv2"] { display: none; }
#showdiv1:target ~ div a[href="#hidediv1"], #showdiv2:target ~ div a[href="#hidediv2"] { display: inline-block; }

#showdiv1:target ~ div .hiddendiv.sm1 { height: 180px; }
#showdiv2:target ~ div .hiddendiv.sm2 { height: 440px; }

.hiddendiv {
	display: block;
	cursor: pointer;
	background-color: midnightblue;
}

.hiddendiv a:hover, .hiddendiv a:focus { color: cyan; }
	
.hiddendiv ul { column-count: 5; }
 
.hiddendiv li {
	list-style-type: none;
	display: block;
}
	
.hiddendiv a { 
	text-decoration: none; 
	color: white;
}
</style>

One problem with the above CSS is that the height of each section of the submenus has to be defined, the lines

#showdiv1:target ~ div .hiddendiv.sm1 { height: 180px; }
#showdiv2:target ~ div .hiddendiv.sm2 { height: 440px; }

do this. This site is split into sections, each with its own menu. If the CSS is moved to a single file, then all 20 submenus have to be defined because if more links are added to that section's menu then the height is going to change. This can be done by changing the classes sm1 and sm2 to something like allsections, bristolmenu, utilsmenu, webmenu and so on.


CSS Target Pseudo Class

:target - MDN Web Docs
Demo of :target - W3Schools
Demo of :target (menu) - W3Schools
How to toggle Effect in Div using only css? - Stack Overflow
Pure CSS DropDown Menu using :target pseudo class - Deepu Balan
The ':target' pseudo-class - W3.org

Accessibility Checkers

AccessiBe accessScan - Online accessibility checker
Accessible Web - Online accessibility checker
AChecker - Online accessibility checker
ADAScan βeta - Online accessibility checker
axe DevTools - Chrome Browser Extension accessibility checker
Experte Accessibility Check - Online accessibility checker
Intent Based Accessibility Checker - Online accessibility checker
WAVE - Chrome Browser Extension accessibility checker
Web Accessibility Evaluation Tools List - W3C Web Accessibility Initiative

<selectlist> & <selectmenu> Tag

Add customizable select element, currently <selectlist> - GitHub
Customizable <select> Element - Chrome Platform Status
Open UI's <selectlist> demos - Microsoft Edge Demos
Say Hello to selectmenu, a Fully Style-able select Element - CSS Tricks
Selectlist Element - Open UI
Styling 'select' elements for real - Microsoft Windows Blog