The second HTMHell special focuses on another highly controversial pattern in front-end development:
š„ the burger button. š„
The burger button and his tasty friends (kebab, meatball and bento) usually reveal a list of links when activated. According to our studies, these buttons are highly optimized for mouse and touch users, but lack support for keyboard and screen reader users in most cases.
After less than 1 hours of research, HTMHell presents a collection of 18 different bad practices found on real websites.
Pattern 1: the unsemantic burger
<div class="burger">
<span></span>
<span></span>
<span></span>
</div>
.burger {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 30px;
height: 20px;
cursor: pointer;
}
.burger span {
height: 1px;
display: block;
background: #000;
}
Issues and how to fix them
- The
<div>
element is an element of last resort, for when no other element is suitable. Use of the<div>
element instead of more appropriate elements leads to poor accessibility. If you need a button, use the<button>
element. - A click event on a
div
triggers only on click. A click event on abutton
triggers on click and if the user presses the Enter or Space key. - A
div
isnāt keyboard focusable. - Thereās no text label.
- The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers announce: Nothing.
Other variations of this pattern
The empty burger
<div class="burger"></div>
The all div burger
<div class="burger">
<div></div>
<div></div>
<div></div>
</div>
Pattern 2: The classic image burger
<img class="menu" src="menu.png">
Issues and how to fix them
- A click event on an
img
triggers only on click. A click event on abutton
triggers on click and if the user presses the Enter or Space key. - An
img
isnāt keyboard focusable. - Thereās no text alternative for the image. Screen readers may announce the filename instead.
- The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers may announce: menu.png, image.ā
Pattern 3: The modern image burger
<svg class="hamburger" viewBox="0 0 20 20" aria-labelledby="title">
<title>Open Navigation</title>
<g>
<rect y="3" width="20" height="2"></rect>
<rect y="9" width="20" height="2"></rect>
<rect y="15" width="20" height="2"></rect>
</g>
</svg>
Issues and how to fix them
- A click event on an
svg
triggers only on click. A click event on abutton
triggers on click and if the user presses the Enter or Space key. - An
svg
isnāt keyboard focusable in most browsers (IE 11 is an exception). - The value of
aria-labelledby
references elements by their id, not by tag name. - The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers interpret
svg
elements differently. To get a consistent result therole="img"
attribute should be present on thesvg
. - Screen readers may announce: āOpen Navigation, graphicā or āOpen Navigation, group.ā
Pattern 4: Almost a burger
<button class="navbar-toggle" type="button">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
Issues and how to fix them
- Thereās no text label.
- The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers announce: button.
Pattern 5: The placeholder link burger button
<a class="menuButton"></a>
Issues and how to fix them
- A link without
href
is still not a button. - If the
<a>
element has nohref
attribute, then the element represents a placeholder for where a link might otherwise have been placed.Footnote2 - If youāre adding a click event to a placeholder link, you probably donāt want to use a placeholder link, but an actual link with an
href
attribute or a<button>
, depending on what's happening on click. - Placeholder links aren't focusable.
- Thereās no text label.
- The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers announce: probably nothing.
Pattern 6: The wannabe button burger link
<a role="button" aria-label="menu" aria-expanded="false" class="burger">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
- Do not change native semantics, unless you really have to.
- If the
<a>
element has nohref
attribute, then the element represents a placeholder for where a link might otherwise have been placed.Footnote2 - If youāre adding a click event to a placeholder link, you probably donāt want to use a placeholder link, but an actual link with an
href
attribute or a<button>
, depending on what's happening on click. - Placeholder links aren't focusable.
- Screen readers may announce: āmenu, collapsed, buttonā
Pattern 7: The unsemantic burger with extra bacon
<span class="mobile-nav" aria-hidden="true">
Show nav
<span></span>
<span></span>
<span></span>
<span></span>
</span>
Issues and how to fix them
- Pretty much the same as Pattern 1: The unsemantic burger except that this button has a label which is good, but it also has
aria-hidden="true"
which means that it's completely inaccessible to screen reader users. - Screen readers announce: Nothing.
Pattern 8: The JavaScript link burger button
<a class="toggle-link" href="javascript:">
<i class="fa fa-reorder"></i>
</a>
.fa-reorder::before {
content: "ļ";
}
Issues and how to fix them
- Screen readers may announce CSS generated content.Footnote1
- Font Awesome advises to hide icons semantically by settings
aria-hidden="true"
on the<i>
element. - The
i
element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text.Footnote2 If you just want italic text, usefont-style: italic;
in CSS. - Thereās no text label.
- If youāre not sure when to use
<a>
or<button>
, watch The Links vs. Buttons Showdown by Marcy Sutton. - The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers announce: ālinkā.
Pattern 9: The āI have no idea what I'm doing, let's just add some attributesā burger button
<div class="mega-toggle-block" tabindex="0">
<span class="mega-toggle-label" role="button" aria-expanded="false"> </span>
</div>
Issues and how to fix them
- The
<div>
element is an element of last resort, for when no other element is suitable. Use of the<div>
element instead of more appropriate elements leads to poor accessibility. If you need a button, use the<button>
element. - A click event on a
div
triggers only on click. A click event on abutton
triggers on click and if the user presses the Enter or Space key. - The
div
is focusable, but it has norole
or label. - The
span
tries to mimic abutton
, but it's not focusable and it has no label. - You donāt need the
tabindex
attribute if you use abutton
. HTML buttons are focusable by default. - Thereās no text label.
- Screen readers may announce: āgroupā.
Pattern 10: The heavenly anchor link burger button
<a href="#menutoggle" id="menutoggle">ā°</a>
Issues and how to fix them
- A screen reader may announce this as trigram for heaven, because ā° is the unicode character for the trigram for heaven.
- The purpose of the icon is decorative, it should be hidden from screen readers. Consider adding decorative images using background properties in CSS.
- An anchor link is not a
<button>
. - An anchor link should not refer to itself.
- If youāre not sure when to use
<a>
or<button>
, watch The Links vs. Buttons Showdown by Marcy Sutton. - The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers announce: ātrigram for heaven, linkā.
Pattern 11: The bento checkbox button
<div class="bento">
<input type="checkbox" id="bento">
<label for="bento"></label>
</div>
.bento label {
background-image: url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnPjxwYXRoIGQ9J00zIDNoNHY0SDN6bTE0IDBoNHY0aC00em0tNyAwaDR2NGgtNHptLTcgN2g0djRIM3ptMTQgMGg0djRoLTR6bS03IDBoNHY0aC00em0tNyA3aDR2NEgzem0xNCAwaDR2NGgtNHptLTcgMGg0djRoLTR6JyBmaWxsPScjQTdBQUIyJy8+PC9zdmc+);
width: 30px;
height: 30px;
display: block;
}
.bento input {
position: absolute;
opacity: 0;
pointer-events: none;
left: -9999px;
top: -9999px;
}
Issues and how to fix them
- A checkbox is not a
<button>
. - The default key events on a checkbox and a button are not the same.
- If youāre not sure when to use
<a>
or<button>
, watch The Links vs. Buttons Showdown by Marcy Sutton. - The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - This ābuttonā has no label.
- Screen readers may announce: āunticked tickboxā.
Pattern 12: The bento list anchor link button
<ul class="offcanvas-icon">
<li>
<a href="#" class="menu-button">
<span class="dot1"></span>
<span class="dot2"></span>
<span class="dot3"></span>
<span class="dot4"></span>
<span class="dot5"></span>
<span class="dot6"></span>
<span class="dot7"></span>
<span class="dot8"></span>
<span class="dot9"></span>
</a>
</li>
</ul>
Issues and how to fix them
- Use
<ul>
to group and list related items, not as a button wrapper. - An anchor link is not a
<button>
. - CSS is quite powerful, you don't need 9
span
s to display 9 dots. - If youāre not sure when to use
<a>
or<button>
, watch The Links vs. Buttons Showdown by Marcy Sutton. - The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - This ābuttonā has no label.
- Screen readers may announce: ālist 1 itemā.
Pattern 13: The meatball link
(Note: There was a click event on the link that prevented default.)
<a href="https://example.com/">ā¢ ā¢ ā¢</a>
Issues and how to fix them
- A link is not a
<button>
. - The default key events on a link and a button are not the same.
- If youāre not sure when to use
<a>
or<button>
, watch The Links vs. Buttons Showdown by Marcy Sutton. - The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - This ābuttonā has no label.
- Screen readers may announce: ālink, bullet bullet bulletā.
Pattern 14: The kebab div button
<div class="menu" title="Menu">
<i></i>
<i></i>
<i></i>
</div>
Issues and how to fix them
- Pretty much the same as Pattern 1: The unsemantic burger.
- The
i
element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text.Footnote2 If you just want italic text, usefont-style: italic;
in CSS. - Screen readers may announce: nothing.
Pattern 15: The hamburger
<button class="nav__toggle-button" aria-label="Hamburger Menu">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" fill="currentColor"></path>
</svg>
</button>
Issues and how to fix them
- Not as bad as all the others, but the term āHamburgerā might confuse users.
- The ābuttonā should indicate whether the element it controls is currently expanded or collapsed (
aria-expanded="false"
if collapsed). - Screen readers may announce: ābutton, Hamburger Menuā.
Pattern 16: The chatty burger button
<button aria-label="All Company expand to see list of Company products and services" aria-expanded="false"></button>
Issues and how to fix them
- Not as bad as all the others, but the label is too long. Keep it short and simple.
- Screen readers may announce: ābutton, All Company expand to see list of Company products and services, expandedā.
Alternatives
Solution 1: A button with visible text and no icon.
<button type="button" aria-expanded="false">
Menu
</button>
- Text only: easy to implement and comprehensible.
- Screen readers may announce: Menu, buttonā.
Solution 2: A button with visible text and only visually accessible icon.
<button type="button" aria-expanded="false">
<svg aria-hidden="true"> ā¦ </svg>
Menu
</button>
- If you want to use an icon, hide it from screen readers by wrapping it in a
span
witharia-hidden="true"
. - Screen readers may announce: Menu, buttonā.
Solution 3: A button with hidden text and only visually accessible icon.
<button type="button" aria-expanded="false">
<span class="sr-only">Menu</span>
<svg aria-hidden="true"> ā¦ </svg>
</button>
.sr-only {
position: absolute;
white-space: nowrap;
width: 1px;
height: 1px;
overflow: hidden;
border: 0;
padding: 0;
clip-path: inset(50%);
margin: -1px;
}
- Unfortunately, thereās no native way of hiding content only visually.
The.sr-only
class makes sure that content is visually hidden but still accessible to screen reader users. - Screen readers may announce: Menu, buttonā.
Solution 4: A button with accessible text and only visually accessible icon.
<button type="button" aria-label="Menu" aria-expanded="false">
<svg aria-hidden="true"> ā¦ </svg>
</button>
- If you donāt want to show text on screen, provide a text alternative for your icon or SVG by adding
aria-label
to the button. - Screen readers may announce: Menu, buttonā.
Resources
Wanna learn accessibility testing?
Are you interested in learning how to discover these accessibility issues and a lot more? Then join me for a Smashing Magazine workshop starting on November 4th.
Deep Dive On Accessibility Testing
Workshop, 5Ć2.5h + Q&A
Thu & Fri, November 4ā18 202109:00 ā 11:30 AM PT (Pacific, US) ā¢ 18:00 ā 20:30 CET (Europe)
Use this link for a special -15% discount.