CSS Tutorial

CSS Navigation

A nav bar is a flex list of links. Hover, current page, and a small-screen wrap or menu.

A list of links, laid out

Site navigation is HTML first: a nav, usually a ul of a elements. CSS then removes the bullets, puts the items in a row, and marks the current page. Harbor studio’s bar is Home, Desks, Hours, Visit — four links, flex, a teal current state, and a wrap when the preview is narrow.

You do not need a hamburger to learn this chapter. A wrapping flex nav is honest on a small screen and still keyboard-friendly. A disclosure menu is a later pattern, with more JavaScript than this tutorial wants to sneak in.

Flex the list

Reset list padding and bullets. Set the ul to display: flex with gapand flex-wrap: wrap. Style the anchors as blocks with padding so the hit area is larger than the word.

Example

<style>
  body {
    font-family: system-ui, sans-serif;
    color: #0c4a6e;
    background: #f0f9ff;
    margin: 1.25rem;
  }
  nav {
    background: #fff;
    border: 1px solid #7dd3fc;
    border-radius: 0.55rem;
    padding: 0.4rem 0.6rem;
  }
  nav ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.35rem;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  nav a {
    display: block;
    padding: 0.45rem 0.75rem;
    border-radius: 0.35rem;
    color: #0369a1;
    text-decoration: none;
    font-weight: 650;
  }
  nav a:hover {
    background: #e0f2fe;
    color: #0c4a6e;
  }
</style>
<h1>Harbor studio</h1>
<nav aria-label="Studio">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">Desks</a></li>
    <li><a href="#">Hours</a></li>
    <li><a href="#">Visit</a></li>
  </ul>
</nav>

list-style: none removes bullets. Some screen readers then skip announcing the list unless the ul keeps its list role — in practice, keep the ul/li markup and do not replace it with bare links in a div. Open this bar at /css/try.

Hover, focus, and the current page

Hover is a hint. The current page is information. Use a class on the current link (your HTML or a small template sets it) rather than hoping the URL matches. Focus needs a ring, especially after you restyle anchors to look like pills.

StateWhat to show
DefaultReadable color on the bar background
:hoverA light sky fill, still a link, not a new layout
:focus-visibleA 3px outline with offset
.current (or aria-current="page")Teal fill, white text, so “you are here” is obvious

Example

<style>
  body {
    font-family: system-ui, sans-serif;
    color: #0c4a6e;
    background: #f0f9ff;
    margin: 1.25rem;
  }
  nav ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  nav a {
    display: block;
    padding: 0.45rem 0.8rem;
    border-radius: 999px;
    color: #0369a1;
    text-decoration: none;
    font-weight: 650;
  }
  nav a:hover { background: #e0f2fe; }
  nav a:focus-visible {
    outline: 3px solid #0d9488;
    outline-offset: 2px;
  }
  nav a[aria-current="page"] {
    background: #0d9488;
    color: #fff;
  }
</style>
<nav aria-label="Studio">
  <ul>
    <li><a href="#" aria-current="page">Desks</a></li>
    <li><a href="#">Hours</a></li>
    <li><a href="#">Visit</a></li>
  </ul>
</nav>

aria-current="page" is both a style hook and an accessibility name for the current item. Prefer it over a class that only CSS knows about, or pair the two.

A bar that wraps on small screens

Put the brand and the list in one flex row with justify-content: space-between andflex-wrap: wrap. When the viewport is tight, the links drop under the name instead of overflowing. That is often enough. A min-width query can switch the list to a column with full-width hit targets if the labels are long.

Example

<style>
  body {
    font-family: system-ui, sans-serif;
    color: #0c4a6e;
    background: #f0f9ff;
    margin: 1.25rem;
  }
  .bar {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem 1rem;
    padding: 0.55rem 0.75rem;
    background: #fff;
    border: 1px solid #bae6fd;
    border-radius: 0.6rem;
  }
  .brand {
    margin: 0;
    font-size: 1.05rem;
    color: #0d9488;
  }
  .bar ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .bar a {
    display: block;
    padding: 0.4rem 0.7rem;
    border-radius: 0.35rem;
    color: #0284c7;
    text-decoration: none;
    font-weight: 650;
  }
  .bar a:hover { background: #e0f2fe; }
  .bar a[aria-current="page"] {
    background: #0d9488;
    color: #fff;
  }
  @media (min-width: 40rem) {
    .bar a { padding: 0.45rem 0.85rem; }
  }
</style>
<header class="bar">
  <p class="brand">Harbor studio</p>
  <nav aria-label="Studio">
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#" aria-current="page">Desks</a></li>
      <li><a href="#">Hours</a></li>
      <li><a href="#">Visit</a></li>
    </ul>
  </nav>
</header>

Skip hover-only flyout menus as the only way to reach a section. If you add a collapsed menu later, the same links must remain in the DOM and focusable when open. For this chapter, wrap and current page are the whole job.

Worked examples

The short listings above show one property. These sheets paint documents you would actually ship: a lab dashboard, a clinic form, a marks table, a nav bar.

CSS does not invent meaning. HTML already said what the pieces are. Cascade, specificity, and the box model decide how they look. The numbers are classroom values — current, pH, pulse, 3-4-5 — so the style has something real to sit on.

Preview them in the CSS editor at /css/try. Change one property and watch the page paint. The tags stay the same.

Engineering

A lab nav as a flex list

nav > a in a flex row is a bar. gap replaces margin hacks. flex-wrap lets links fall on a phone instead of overflowing.

The current page needs a class or [aria-current="page"] so colour is not the only cue. Hover is extra.

Example

<style>
  nav { display: flex; flex-wrap: wrap; gap: 0.6rem; background: #f0fdfa; padding: 0.5rem; }
  a { color: #0f766e; text-decoration: none; }
  a[aria-current="page"] { font-weight: 700; text-decoration: underline; }
</style>
<nav>
  <a href="/css" aria-current="page">Lab home</a>
  <a href="/css/flexbox">Flex</a>
  <a href="/css/grid">Grid</a>
</nav>

Biology

Clinic links that wrap

A wrapping nav is better than a hamburger you have not built yet. Padding on each a makes the hit target at least 44 px class in later work.

Example

<style>
  nav { display: flex; flex-wrap: wrap; gap: 0.4rem; }
  a { background: #fef3c7; color: #9f1239; padding: 0.35rem 0.6rem; text-decoration: none; }
</style>
<nav>
  <a href="/css">Home</a>
  <a href="/css/forms">Book</a>
  <a href="/css/text">Advice</a>
</nav>

FAQ: CSS Navigation

Common questions about this page.

What is the StudyGrid CSS tutorial?

The StudyGrid CSS tutorial is a full beginner track: selectors, the box model, text, layout, flex, grid, and responsive design. Each chapter has copy-and-preview examples.

Should I run css navbar examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn css navbar in this CSS CSS lesson (CSS Navigation).

Is the CSS editor the same as Try HTML?

No. Try CSS is a stylesheet preview at /css/try. Try HTML stays at /html/try. CSS lessons never open the HTML-only editor or the Python editor.

Do I need to install anything to learn CSS?

No. Open a chapter, click Try it in CSS, and the page preview updates in the browser.

Where should I start the CSS tutorial?

Start at CSS Intro, then Syntax, Selectors, and How To. After colors and the box model, continue to flex, grid, and media queries. Use Next at the bottom of each chapter.

Is the CSS tutorial free?

Yes. The CSS studio on StudyGrid (studygrid.in) is free: dashboard, chapters, and the live preview editor.