Calendar
Month grids for picking a date or a date range.
Month grid
A <table> with one button per day. Mark days from adjacent months with .outside, the current date with .today, and days that carry something with .marked. Render six rows every month so the block size never jumps.
<div class="calendar">
<header>
<button type="button" class="prev" aria-label="Previous month">…</button>
<span class="title" id="cal-2027-01">January 2027</span>
<button type="button" class="next" aria-label="Next month">…</button>
</header>
<table role="grid" aria-labelledby="cal-2027-01">
<thead>
<tr><th scope="col" abbr="Monday">Mo</th> … </tr>
</thead>
<tbody>
<tr>
<td class="outside"><button type="button" tabindex="-1">28</button></td>
…
<td class="marked"><button type="button">1</button></td>
<td class="today"><button type="button" aria-current="date">26</button></td>
</tr>
<!-- always six rows -->
</tbody>
</table>
</div>
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|
Single date
Add .selected to the cell and aria-pressed="true" to its button.
<td class="selected">
<button type="button" aria-pressed="true">14</button>
</td>
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|
Date range
.range-start and .range-end paint the ends, .in-range paints the band between them. The band is a cell background, so it runs edge to edge across a week.
<td class="range-start"><button type="button" aria-pressed="true">8</button></td>
<td class="in-range"><button type="button">9</button></td>
<td class="in-range"><button type="button">10</button></td>
…
<td class="range-end"><button type="button" aria-pressed="true">14</button></td>
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|
Several months
Wrap calendars in .calendar-group. Omit .prev on the first month and .next on the last: the header keeps its title centred either way.
<div class="calendar-group">
<div class="calendar">
<header>
<button type="button" class="prev" aria-label="Previous month">…</button>
<span class="title">January 2027</span>
</header>
…
</div>
<div class="calendar">
<header>
<span class="title">February 2027</span>
<button type="button" class="next" aria-label="Next month">…</button>
</header>
…
</div>
</div>
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|
Compact
.calendar--compact shrinks cells to one line for tight panels.
<div class="calendar calendar--compact">…</div>
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|
Behaviour
The calendar is state, not behaviour. Month navigation and selection are set by the server render or a small script: change the cell classes and the aria-* attributes, nothing else. Cells are buttons, so keyboard users can tab through days and activate them without extra work.
Change the cell size with --calendar-cell and the range band colour with --calendar-range-bg.