Skip to main content
Syllabus
On this page

Styling Lists & Tables

Badar KhalilUpdated September 30, 2026 7 min read

Styling Lists and Tables in CSS

Lists and tables organise information. Lists group related items such as menus, steps and features. Tables present data in rows and columns. Learning styling lists and tables in CSS helps you build navigation bars, breadcrumbs, step-by-step guides, pricing tables, dashboards and reports that are clean, readable and accessible. In this lesson you will cover list markers, custom counters, horizontal lists, table borders, zebra stripes, hover rows, sticky headers and responsive tables, with live editable code.

Focus keyword: styling lists and tables in CSS. Related keywords: list-style-type, ::marker, CSS counters, border-collapse, border-spacing, caption-side, zebra striping, nth-child, sticky table header, responsive table CSS, tabular-nums, table-layout fixed.

Part 1: Styling Lists

1. List Types in HTML

  • <ul>: unordered list, shown with bullets by default.
  • <ol>: ordered list, shown with numbers by default.
  • <dl> with <dt> and <dd>: description list for term and definition pairs.

2. The list-style Properties

PropertyWhat it doesExample values
list-style-typeSets the marker shape or numbering systemdisc, circle, square, decimal, lower-alpha, upper-roman, none
list-style-positionPuts the marker outside or inside the content boxoutside, inside
list-style-imageUses an image as the markerurl('icon.svg')
list-styleShorthand for the three abovesquare inside, none

To remove bullets completely, use list-style: none; padding: 0; margin: 0;. Note that some screen readers (notably VoiceOver with Safari) stop announcing an element as a list when list-style is none, so add role='list' to the element if the list semantics matter.

3. Styling Markers with ::marker

The ::marker pseudo-element targets the bullet or number of a list item. You can change its color, font-size, font-weight, and even its content. Only a limited set of properties is supported, so for heavy customisation use counters or ::before.

4. CSS Counters for Custom Numbering

CSS counters let you build numbered steps, nested outlines (1.1, 1.2) and styled number badges. The three building blocks are counter-reset (create the counter), counter-increment (increase it on each item) and counter() (display the value inside content).

5. Horizontal Lists and Navigation

Most navigation menus are lists. Turn a vertical list into a horizontal one with display: flex and gap. Breadcrumbs can add separators using the adjacent sibling selector: li + li::before { content: '/'; }. Always wrap navigation lists in a <nav> with an aria-label.

Part 2: Styling Tables

1. Semantic Table Structure

A well-built table uses <caption>, <thead>, <tbody>, <tfoot>, <th scope='col'> and <th scope='row'>. These elements give screen readers the context to announce each cell together with its headers. Use tables only for tabular data, never for page layout.

2. Table Properties Reference

PropertyPurpose
border-collapsecollapse merges neighbouring borders into one, separate keeps them apart
border-spacingGap between cells (only when separate)
caption-sidePlaces the caption at the top or bottom
table-layoutauto sizes by content, fixed uses equal, predictable column widths
empty-cellsShow or hide borders of empty cells
vertical-alignAligns content inside cells (top, middle, bottom)
font-variant-numeric: tabular-numsMakes digits equal width so numbers line up in columns

3. Zebra Striping and Row Hover

Alternating row colours help the eye follow a row across wide tables. Use tbody tr:nth-child(even) for stripes and tbody tr:hover for a highlight. Keep the contrast subtle, and make sure text contrast stays above 4.5:1 on every row colour.

4. Aligning Numbers

Right-align numeric columns and apply font-variant-numeric: tabular-nums so decimals line up. Left-align text columns. Consistent alignment makes comparisons much faster.

5. Sticky Headers

For long tables, keep the header visible while scrolling. Wrap the table in a container with overflow: auto and a fixed max-height, then set position: sticky; top: 0; on the <th> cells in the header. Give the sticky cells a solid background so rows do not show through.

6. Responsive Tables

Tables are naturally wide, so on small screens you have two common strategies:

  • Horizontal scroll: wrap the table in a div with overflow-x: auto. This is the simplest and keeps the structure intact.
  • Stacked cards: at a small breakpoint, turn each row into a block and show the column name using content: attr(data-label) on td::before.

Accessibility Checklist

  • Add a <caption> that describes the table.
  • Use <th> with scope for headers, not styled <td> cells.
  • Do not rely on colour alone to convey meaning inside cells.
  • Keep the scroll container keyboard focusable with tabindex='0' when it scrolls.
  • Keep lists as real lists so assistive technology announces the item count.
  • ::marker with custom content for branded bullets without extra markup.
  • CSS counters and counter-style for multi-level numbering and step wizards.
  • :has() to highlight a row or list item based on its content, for example tr:has(input:checked).
  • position: sticky headers and first columns for data-heavy dashboards.
  • Container queries for tables inside resizable cards.
  • tabular-nums for finance and analytics UIs.

Common Mistakes

  • Forgetting border-collapse: collapse and getting double borders.
  • Using tables for layout.
  • Removing list bullets and losing list semantics without adding a role.
  • Placing sticky headers without a background colour.
  • Leaving wide tables unscrollable on mobile.

Summary

Lists and tables are essential building blocks. With list-style, ::marker and counters you can style any list. With border-collapse, stripes, sticky headers and responsive patterns you can make data tables that are beautiful and usable on every device. Experiment with each live example below.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Exercise: Create a Numbered Steps ListHTML

Turn the ordered list into a styled steps list using CSS counters. Remove the default numbers, then show each step number inside a blue circle using li::before with content: counter(step). Add a light gray background and rounded corners to each item.

Try it Yourself HTML
Output

Press Run to execute.

Show expected output
Each list item shows a blue circular number badge on the left, a light gray background and rounded corners, with no default browser numbers.

This is a self-check — compare your result with the expected output above.

Exercise: Zebra Table with HoverHTML

Style the table so borders are collapsed, the header row has a dark background with white text, even body rows have a light gray background, and a row turns light blue on hover. Right-align the Price column and use tabular-nums.

Try it Yourself HTML
Output

Press Run to execute.

Show expected output
A table with single borders, a dark header, alternating light gray rows, a light blue hover row, and right-aligned aligned numbers in the Price column.

This is a self-check — compare your result with the expected output above.

Quiz: Styling Lists & Tables Quiz Pass 70%
Loading quiz…

Was this page helpful?