Minimized Checkbox Menu

Introduction

In February 2026, Google changed the way their programmable search engine on the site looks. This was accommodated in a change to the site's 2023 CSS file. Later that month, I realized that instead of hiding the checckbox in the site's main menu, if I minimized it, then the section dropdowns will became navigable using the keyboard which makes it accessbile.

This page tests both whether a change to a new 2026 CSS file ill work or if I need to change the HTML on the pages as well.

I like the way the current menu works, but it bothers me that it is not keyboard accessible using the tab key. What I want to do is keep the same look and feel of the current menu system but make it accessible using the keyboard.


How the Menu Currently Works

The current 2023 main menu uses a hidden checkbox using display:none. The code for it includes two span tags, one with the down-arrow (▼) and the other with the up-arrow (▲). When the checkox is checked, one is hidden and the other shown.

The HTML for it is:

<input type="checkbox" id="show-menu" role="button">
<label for="show-menu" id="section-menu" class="menu-item">
<span id="menu-down">Section Menu   ▼</span><span id="menu-up"> Section Menu   ▲</span><span id="hamburger">☰</span></label>

The CSS to do this is simply:

#show-menu:checked ~ #section-menu #menu-down {display: none;}
#show-menu:checked ~ #section-menu #menu-up {display: inline-block;}

The ~ selector is the subsequent-sibling combinator. What it does is separate two selectors and matches all instances of the second element that follow the first element (not necessarily immediately) that share the same parent element.

How I use it is when the hidden checkbox is checked, it matches the spans with the id's of menu-up and menu-down in the label with the id of section-menu. When the hidden checkbox is checked, it also shows the hidden section menu div using:

#show-menu:checked ~ #menu-div {display:block;}

As well as hiding the checkbox, I put the "Section Menu" text in the spans along with the up and down arrows instead of putting the text the checkbox label. This was probably a mistake.


Checkboxes and Labels

The order of how the labels and checkboxes appear can be changed easily by moving where the label text appears in relation to the checkobx in the HTML.

The following uses:

<input type="checkbox" id="ex1"/>
<label for="ex1" style="display:inline;">This is the label for the checkbox</label>

The following uses:

<label for="ex2" style="display:inline;">This is the label for the checkbox</label>
<input type="checkbox" id="ex2"/>

The checkbox can also be placed inside the label. Because the label is now the parent of checkbox, doing what I want to do which is changing the label when the checkbox is checked, makes the CSS a little more complicated than it can be. The following uses:

<label for="ex3" style="display: inline;">
This is the label for the checkbox <input type="checkbox" id="ex3" /></label>

The following uses:

<label for="ex4" style="display: inline;">
<input type="checkbox" id="ex4" />This is the label for the checkbox</label>


Accessibility Tests

Open the browser developer tools (usuaully by pressing F12) to check the state of the checkboxes. Use the tab key to navigate around the checkboxes.

In tests 5 and 6, the visibility of the checkbox is not changed, it is minimized using the CSS:

width:0;
height:0;
margin:0;
padding:0;

Test 1

Label wrapped around checkbox:

Test 2

Label and checkbox are separate:

Test 3

Label wrapped around checkbox, checkbox is display:none:

As the above checkbox is hidden it cannot be selected using the keyboard.

Test 4

Label and checkbox are separate, checkbox is display:none

As the above checkbox is hidden it cannot be selected using the keyboard.

Test 5

Label wrapped around checkbox, checkbox is resized to 0,0:

As the above checkbox is simply resized, it can be selected using the keyboard.

Test 6

Label and checkbox are separate:

As the above checkbox is simply resized, it can be selected using the keyboard.

Test 7

Label wrapped around checkbox, checkbox has visibility hidden

As the above checkbox is hidden, it cannot be selected using the keyboard.

Test 8

Label and checkbox are separate, checkbox has visibility hidden:

As the above checkbox is hidden, it cannot be selected using the keyboard.

Results

The results are the same in Chrome, Edge, Firefox and Opera.

All the checkboxes can be toggled by clicking on the label with the mouse, but if the checkboxes are hidden using either the display or visibility properties then they cannot by accessed by using the keyboard. The tab key to move between them and the space bar to toggle them. If the chckbox has a size of 0,0, it is still toggable using the keyboard.

This means that in the above tests 1, 2, 5, and 6 work, but 3, 4, 7, and 8 do not.


CSS Parent, Child, and Sibling Selectors

Over time, CSS has aquired many selectors to access almost any element by its relationship to another in an HTML document. Not all are supported by some browsers.

Some examples:

The :has() pseudo selector was introduced in 2023 and matches any parent element that has a specific sibling or element. This pseudo selector is supported in most browsers.

In 2026, the CSS || column combinator is still in the experiental stage and hardly any browsers support it. The selector matches only those elements matched by the second selector that belong to the column elements matched by the first.

The tilde (~) subsequent-sibling combinator selector was introduced in CSS 2 in May 1998. It is very widely supported and I think I will continue to use it in the main menu.


Changing the Checkbox Label

I like the way the arrows appear on the current menu when the checkbox is checked or unchecked. In the 2023 menu, I put the "Section Menu" text in the spans along with the up and down arrows instead of putting the text the checkbox label. This was probably a mistake and I should have put the text in the label and just have the up and down arrows in the spans.

Using tests 1, 2, 5, and 6 from the above tests:

In the test 1 and 5, the checkbox is wrapped inside the label. Because of this, the label is the parent of the checkbox. This complicates the CSS so using just tests 1 and 5:

Now minimizing the checkbox, it looks like this:

The HTML for doing this is:

<input type="checkbox" id="chkboxtest"/>
<label for="chkboxtest" id="lbltest">Section menu <span id="downtest">▼</span><span id="uptest">▲</span></label>

and the CSS is:

#chkboxtest {
width:0;
height:0;
margin:0;
padding:0;
}
#chkboxtest:focus + label { outline: 2px solid black; }
#lbltest { display:inline; }
#uptest { display:none; }
#chkboxtest:checked ~ #lbltest #downtest { display: none; }
#chkboxtest:checked ~ #lbltest #uptest { display: inline-block; }

The CSS is very simple but includes both + and ~ combinators.

The + combinator is the next-sibling combinator and what it does is separates two selectors and matches the second element only if it immediately follows the first element, and both are children of the same parent element. In the above example it matches the chkboxtest:focus element with the next label element.

The ~ combinator is the subsequent-sibling combinator. What it does is separate two selectors and matches all instances of the second element that follow the first element (not necessarily immediately) that share the same parent element.

How I use that in the example is to match the spans in the label when the checkbox is checked. Here I used spans, but any element that can be identified can be used, even images.


Using as the Main Menu

Both the HTML and CSS of the 2026 main menu is almost, but not quite the same, as the 2023 main menu. The changes were more for aesthetics more than anything else, but I felt it was important to look good.

This is what the normal accessibile link looks like:

Normal accessibile link

This is what the normal accessibile link looks like:

Checkbox link using #chkbox:focus + label { outline: 1px solid white; }

By adding a span inide the label tag, then that can be highlighted:

Checkbox link using #chkbox:focus + label > span { border: 1px solid white; }

By adding a span inide the label tag, then that can be highlighted. As well as being highlighted the span can also be formatted using CSS:

Checkbox link using span { padding:2px; border-radius:6px; } and #chkbox:focus + label > span { border: 1px solid white; }

The HTML for this part of the menu is now:

<input type="checkbox" id="show-menu" role="button" />
<label for="show-menu" id="section-menu" class="menu-item"><span id="menu-hilite">Section menu <span id="menu-down">▼</span><span id="menu-up">▲</span><span id="hamburger">☰</span></span></label>

The CSS for this part of the menu is now:

#menu-hilite {
padding:2px;
border-radius:6px; }

#show-menu {
width:0;
height:0;
margin:0;
padding:0; }

#show-menu:focus + label > #menu-hilite { border: 1.6px solid white; }
#show-menu:checked ~ #menu-div { display:block; }
#show-menu:checked ~ #section-menu #menu-down { display: none; }
#show-menu:checked ~ #section-menu #menu-up { display: inline-block; }

There are still two slight annoyances with the menu. The first is that after the dropdown menu is opened. When the tab key is pressed the cursor goes to the search bar instead of going down the menu. The second is that when the dropdown is opened, by whatever method, because the main menu item still has focus, it remains outlined.


Sources & Resources

CSS selectors (MDN Web Docs)
CSS3 :unchecked pseudo-class (Stack Overflow)
How should I make this hidden checkbox with label accessible (Stack Overflow) - also see the Codepen
The 'Checkbox Hack' (and things you can do with it) (CSS Tricks)