Simple Navigation

Example

Jump to section titled: Example

HTML

Jump to section titled: HTML

Option 1. Good for simple top level navigation.

Copy 👋<!-- see note below on aria-label. -->
<nav aria-label="Main">
<ul>
<!-- aria-current for users without visual clues. -->
<li><a href="/" aria-current="page"> Home </a></li>
<li><a href="/about" > About </a></li>
<li><a href="/services"> Services </a></li>
<li><a href="/contact"> Contact </a></li>

<!-- Link to footer nav. Icon hidden to screen readers -->
<li><a href="#more-navigation"
aria-label="More navigation links in the footer.">More
<span aria-hidden="true"></span></a></li>
</ul>  
</nav>

Note:

  • <nav> is a Landmark that gives screen readers an idea of structure.
  • aria-label="Main" tells screen reader which navigation this is.
  • aria-current="page" tells screen readers what page they are on.*
  • <ul role="list"> is not needed. Safari now announces the number of list items if within <nav>.
* As this page is not the current page in the top-level menu I have changed "page" to "true" and added a area-label to explain.
Copy 👋<a href="/components/" aria-current="true" 
aria-label="Currently viewing a single post under Components.">
Components</a>

Option 2. Adds a visually hidden heading as screen reader users look for headings more than landmarks.

Copy 👋<!-- see note below  -->
<nav aria-labelledby="main-nav">
<h2 id="main-nav" class="visualy-hidden">Main Navigation</h2>
<ul>
<li><a href="/" aria-current="page"> Home </a></li>
<li><a href="/about" > About </a></li>
<li><a href="/services"> Services </a></li>
<li><a href="/blog"> Blog </a></li>
<li><a href="/contact"> Contact </a></li>
</ul>  
</nav>

Note: Aria-labelledby is generally better. But, in a top level navigation it's likely this hidden <h2> will break the The "H1 must come first" rule.

CSS

Jump to section titled: CSS

Not complete.

Copy 👋/* Flex to apportion link according to size  */
header nav ul, {
display: flex;
flex-wrap: wrap;
gap: var(--space-m);
}

.nav a[href][aria-current="page"],
.nav a[href][aria-current="true"] {
text-decoration: underline;
text-decoration-thickness: .4rem;
text-decoration-color: var(--brand);
text-underline-offset: .8rem;
}

 /* Styling the second nav target */

#more-navigation:target ul {   
 outline: .2rem solid var(--text);  
 outline-offset: var(--space-xl);  
 padding-inline-end: var(--space-2xl);                     
 }

 /* stop animation for those prefer reduced motion */

@media (prefers-reduced-motion: no-preference){
 #more-navigation:target ul{
animation: slide-in-elliptic-left-fwd
 0.4s cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s both;
}
 }  

 /* Target animation created with animista.net */
@keyframes slide-in-elliptic-left-fwd {
  0% {
    transform: translateX(-800px) rotateY(30deg) scale(0);
    transform-origin: -100% 50%;
    opacity: 0;
  }
  100% {
    transform: translateX(0) rotateY(0) scale(1);
    transform-origin: 1800px 50%;
    opacity: 1;
  }
}

Note:

  • Flex on the <ul> justifies content horizontally according to item size.
  • Highligting the current page helps with UX.
  • Globally padding the <a> tag increases the target size.
  • If clearly navigation we can break the rule on underlining <a> tags.