SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/calendars

7 CSS Calendars

5 Pure CSS2 with JSPublished 2026-10-05Free · no sign-up

Seven calendar layouts: a month view built as a real table, a date picker with month navigation, a week schedule placed with CSS Grid, a check-in and check-out range picker, tear-off date badges for event lists, a styled native date input and an agenda list grouped by day.

01. Month View Calendar

CalendarGrid

A month grid built as a real table with day-name headers, so screen readers announce each date with its weekday. Today has aria-current set to date, days from other months are dimmed, and the grid uses table-layout: fixed for even columns.

View code
<table class="cal1"><caption>October 2026</caption><thead><tr><th scope="col" abbr="Monday">Mo</th><th scope="col" abbr="Tuesday">Tu</th><th scope="col" abbr="Wednesday">We</th><th scope="col" abbr="Thursday">Th</th><th scope="col" abbr="Friday">Fr</th><th scope="col" abbr="Saturday">Sa</th><th scope="col" abbr="Sunday">Su</th></tr></thead><tbody><tr><td class="o">28</td><td class="o">29</td><td class="o">30</td><td>1</td><td>2</td><td>3</td><td>4</td></tr><tr><td aria-current="date">5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td><td>11</td></tr><tr><td>12</td><td>13</td><td>14</td><td>15</td><td>16</td><td>17</td><td>18</td></tr><tr><td>19</td><td>20</td><td>21</td><td>22</td><td>23</td><td>24</td><td>25</td></tr><tr><td>26</td><td>27</td><td>28</td><td>29</td><td>30</td><td>31</td><td class="o">1</td></tr></tbody></table>
.cal1 { width: 290px; max-width: 100%; border-collapse: separate; border-spacing: 2px; table-layout: fixed; font-family: Inter, system-ui, sans-serif; text-align: center; }
.cal1 caption { padding-bottom: 10px; color: #101828; font-weight: 800; font-size: 16px; text-align: left; }
.cal1 th { padding-bottom: 6px; color: #475467; font-size: 12px; font-weight: 600; }
.cal1 td { height: 36px; border-radius: 8px; color: #101828; font-size: 14px; }
.cal1 td.o { color: #667085; }
.cal1 td[aria-current] { background: #2563eb; color: #fff; font-weight: 800; }

02. Date Picker with Selectable Days

CalendarPicker

Days are buttons in a grid; clicking one selects it, marks it with aria-pressed and writes the full date into an output. Previous and next month buttons are named in full, each day button's name includes the weekday, and the month heading is a live region.

View code
<div class="cal2"><div class="hd"><button type="button" class="p" aria-label="Previous month">&lsaquo;</button><h3 aria-live="polite">October 2026</h3><button type="button" class="n" aria-label="Next month">&rsaquo;</button></div><div class="dw" aria-hidden="true"><span>M</span><span>T</span><span>W</span><span>T</span><span>F</span><span>S</span><span>S</span></div><div class="g"></div><p>Selected: <output>none</output></p></div>
.cal2 { width: 280px; max-width: 100%; box-sizing: border-box; padding: 14px; border: 1px solid #28324f; border-radius: 16px; background: #121828; color: #e2e8f0; font-family: Inter, system-ui, sans-serif; }
.cal2 .hd { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal2 h3 { margin: 0; font-size: 15px; color: #fff; }
.cal2 .hd button { width: 32px; height: 32px; border: 0; border-radius: 8px; background: #1e2640; color: #fff; font-size: 18px; cursor: pointer; }
.cal2 .dw, .cal2 .g { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; }
.cal2 .dw span { color: #94a3b8; font-size: 12px; padding: 4px 0; }
.cal2 .g button { aspect-ratio: 1; min-width: 0; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #e2e8f0; font: 500 13px Inter, system-ui, sans-serif; cursor: pointer; }
.cal2 .g button:hover { background: #1e2640; }
.cal2 .g [aria-pressed="true"] { background: #6366f1; color: #fff; font-weight: 800; }
.cal2 p { margin: 10px 0 0; color: #94a3b8; font-size: 13px; } .cal2 output { color: #fff; font-weight: 600; }
.cal2 button:focus-visible { outline: 2px solid #a5b4fc; outline-offset: 1px; }
var w = document.querySelector('.cal2'), g = w.querySelector('.g'), h = w.querySelector('h3'), out = w.querySelector('output'), d = new Date(2026, 9, 1);
function draw() {
  g.innerHTML = ''; h.textContent = d.toLocaleDateString('en-GB', { month: 'long', year: 'numeric' });
  var lead = (new Date(d.getFullYear(), d.getMonth(), 1).getDay() + 6) % 7, days = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
  for (var i = 0; i < lead; i++) g.appendChild(document.createElement('span'));
  for (var k = 1; k <= days; k++) { var b = document.createElement('button'); b.type = 'button'; b.textContent = k; b.setAttribute('aria-pressed', 'false');
    b.setAttribute('aria-label', new Date(d.getFullYear(), d.getMonth(), k).toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long' })); g.appendChild(b); }
}
g.onclick = function (e) { var b = e.target.closest('button'); if (!b) return; g.querySelectorAll('[aria-pressed=true]').forEach(function (x) { x.setAttribute('aria-pressed', 'false'); }); b.setAttribute('aria-pressed', 'true'); out.textContent = b.getAttribute('aria-label'); };
w.querySelector('.p').onclick = function () { d.setMonth(d.getMonth() - 1); draw(); };
w.querySelector('.n').onclick = function () { d.setMonth(d.getMonth() + 1); draw(); };
draw();

03. Week Schedule on CSS Grid

CalendarSchedule

A five-day week with time rows and event blocks placed by grid line numbers: an event from 10:00 to 12:00 spans grid-row 3 / 5. Each event has its time written out, so the schedule still makes sense when read in order.

View code
<div class="cal3"><span class="t" style="grid-row:2">9:00</span><span class="t" style="grid-row:3">10:00</span><span class="t" style="grid-row:4">11:00</span><span class="t" style="grid-row:5">12:00</span><b style="grid-column:2">Mon</b><b style="grid-column:3">Tue</b><b style="grid-column:4">Wed</b><b style="grid-column:5">Thu</b><b style="grid-column:6">Fri</b><p class="e a" style="grid-column:2;grid-row:2/4">Planning <small>Mon 9:00-11:00</small></p><p class="e b" style="grid-column:4;grid-row:3/5">Design review <small>Wed 10:00-12:00</small></p><p class="e c" style="grid-column:6;grid-row:2/3">Demo <small>Fri 9:00</small></p></div>
.cal3 { display: grid; grid-template-columns: 38px repeat(5, minmax(0, 1fr)); grid-template-rows: 26px repeat(4, 46px); gap: 3px; width: 340px; max-width: 100%; box-sizing: border-box; font-family: Inter, system-ui, sans-serif; }
.cal3 b { grid-row: 1; align-self: center; text-align: center; color: #344054; font-size: 12px; }
.cal3 .t { grid-column: 1; color: #475467; font-size: 10px; border-top: 1px solid #e4e7ec; }
.cal3 .e { margin: 0; padding: 4px; border-radius: 6px; font-size: 11px; font-weight: 700; line-height: 1.25; overflow: hidden; }
.cal3 small { display: block; font-weight: 500; }
.cal3 .a { background: #dbeafe; color: #1e3a8a; border-left: 3px solid #2563eb; }
.cal3 .b { background: #fce7f3; color: #831843; border-left: 3px solid #db2777; }
.cal3 .c { background: #dcfce7; color: #14532d; border-left: 3px solid #16a34a; }

04. Date Range Highlight

CalendarRange

Picking a check-in and a check-out date highlights every day between them as one connected band. Classes for start, middle and end round the right corners, the two chosen days are pressed buttons, and the range is written out as text under the grid.

View code
<div class="cal4"><p class="m">November 2026</p><div class="g"></div><p class="out" aria-live="polite">Choose your check-in date</p></div>
.cal4 { width: 280px; max-width: 100%; font-family: Inter, system-ui, sans-serif; color: #101828; }
.cal4 .m { margin: 0 0 8px; font-weight: 800; }
.cal4 .g { display: grid; grid-template-columns: repeat(7, 1fr); row-gap: 4px; }
.cal4 button { min-width: 0; height: 36px; padding: 0; border: 0; background: transparent; color: #101828; font: 500 13px Inter, system-ui, sans-serif; cursor: pointer; }
.cal4 .mid { background: #e0f2fe; }
.cal4 .start, .cal4 .end { background: #0369a1; color: #fff; font-weight: 800; }
.cal4 .start { border-radius: 10px 0 0 10px; } .cal4 .end { border-radius: 0 10px 10px 0; } .cal4 .start.end { border-radius: 10px; }
.cal4 button:focus-visible { outline: 2px solid #0369a1; outline-offset: 1px; position: relative; z-index: 1; }
.cal4 .out { margin: 10px 0 0; color: #475467; font-size: 13px; }
var g = document.querySelector('.cal4 .g'), out = document.querySelector('.cal4 .out'), a = null, b = null;
for (var i = 0; i < 6; i++) g.appendChild(document.createElement('span'));
for (var k = 1; k <= 30; k++) { var x = document.createElement('button'); x.type = 'button'; x.textContent = k; x.dataset.d = k; x.setAttribute('aria-label', k + ' November'); g.appendChild(x); }
g.onclick = function (e) {
  var t = e.target.closest('button'); if (!t) return; var d = +t.dataset.d;
  if (a === null || b !== null || d <= a) { a = d; b = null; } else { b = d; }
  g.querySelectorAll('button').forEach(function (x) { var v = +x.dataset.d, c = []; x.removeAttribute('aria-pressed');
    if (v === a) c.push('start'); if (v === (b === null ? a : b)) c.push('end'); if (b !== null && v > a && v < b) c.push('mid');
    if (v === a || v === b) x.setAttribute('aria-pressed', 'true'); x.className = c.join(' '); });
  out.textContent = b === null ? 'Check-in ' + a + ' November. Now choose check-out.' : a + ' to ' + b + ' November, ' + (b - a) + (b - a === 1 ? ' night' : ' nights');
};

05. Mini Date Badges for Events

CalendarBadge

The small tear-off calendar icon used on event listings: month on a coloured strip, day number large below it. Each badge is a time element with a full datetime, so the date is machine readable for browsers and search engines.

View code
<ul class="cal5"><li><time datetime="2026-11-03"><span class="mo">Nov</span><span class="d">3</span></time><div><b>Frontend meetup</b><span>Shoreditch · 18:30</span></div></li><li><time datetime="2026-11-19"><span class="mo">Nov</span><span class="d">19</span></time><div><b>CSS workshop</b><span>Online · 16:00 GMT</span></div></li></ul>
.cal5 { display: grid; gap: 12px; width: 280px; max-width: 100%; margin: 0; padding: 0; list-style: none; font-family: Inter, system-ui, sans-serif; }
.cal5 li { display: flex; align-items: center; gap: 12px; }
.cal5 time { display: grid; width: 52px; flex: none; border-radius: 10px; overflow: hidden; text-align: center; background: #fff; }
.cal5 .mo { padding: 2px 0; background: #be123c; color: #fff; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }
.cal5 .d { padding: 4px 0 6px; color: #111827; font-size: 22px; font-weight: 800; }
.cal5 div { display: grid; } .cal5 b { color: #fff; } .cal5 div span { color: #94a3b8; font-size: 13px; }

06. Styled Native Date Input

CalendarInput

Often the best date picker is the browser's own: type="date" gives a localised, accessible picker on every device. This demo styles the field to match the page, limits it with min and max, and adds a hint about delivery days.

View code
<div class="cal6"><label for="cal6d">Delivery date</label><input id="cal6d" type="date" min="2026-10-06" max="2026-12-23" value="2026-10-12" aria-describedby="cal6h"><p id="cal6h">We deliver Monday to Saturday.</p></div>
.cal6 { display: grid; gap: 6px; width: 260px; max-width: 100%; font-family: Inter, system-ui, sans-serif; }
.cal6 label { color: #101828; font-weight: 700; font-size: 14px; }
.cal6 input { min-width: 0; padding: 11px 12px; border: 1px solid #98a2b3; border-radius: 10px; background: #fff; color: #101828; font: 15px Inter, system-ui, sans-serif; color-scheme: light; }
.cal6 input:focus { outline: none; border-color: #7f56d9; box-shadow: 0 0 0 3px rgba(127,86,217,.25); }
.cal6 input::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .7; }
.cal6 p { margin: 0; color: #475467; font-size: 13px; }

07. Agenda List View

CalendarList

An agenda groups events under day headings, the most readable calendar view on phones. Day headings are h3 elements and each day's events are a list, so people can jump between days with a screen reader's heading shortcuts.

View code
<div class="cal7"><h3>Today · Mon 5 Oct</h3><ul><li><time datetime="09:30">09:30</time><span class="dot" style="--c:#60a5fa"></span>Sprint planning</li><li><time datetime="14:00">14:00</time><span class="dot" style="--c:#f472b6"></span>Customer call: Linea</li></ul><h3>Tue 6 Oct</h3><ul><li><time datetime="11:00">11:00</time><span class="dot" style="--c:#34d399"></span>Release 4.2</li></ul></div>
.cal7 { width: 280px; max-width: 100%; font-family: Inter, system-ui, sans-serif; }
.cal7 h3 { margin: 0 0 6px; color: #94a3b8; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.cal7 ul { margin: 0 0 16px; padding: 0; list-style: none; display: grid; gap: 6px; }
.cal7 li { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px; background: #151b2e; color: #f1f5f9; font-size: 14px; font-weight: 600; }
.cal7 time { color: #94a3b8; font: 500 13px "JetBrains Mono", ui-monospace, monospace; }
.cal7 .dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--c); }

About these CSS Calendars

A month is a table

A month view has rows of weeks and columns of weekdays, so a <table> with column headers lets screen readers announce the weekday of every date. Mark today with aria-current="date".

Consider the native picker

<input type="date"> gives every visitor a localised, accessible picker that suits their device. Build a custom one only when you need ranges, prices per day or a calendar that stays open.

Events on CSS Grid

A schedule is a grid of days and time slots. Give each event its column and row lines (grid-row: 3 / 5 for two hours) and the layout handles overlaps and spacing for you.

Dates in machine-readable form

Wrap dates in <time datetime="2026-11-03">. Browsers, assistive technology and search engines can read the real date, whatever format you display.

Frequently asked questions

Which day should the week start on?

It depends on the country: Monday in most of Europe, Sunday in the US. The picker's code shows where to change it.

Do the pickers handle time zones?

They work in the visitor's local time. Convert to UTC on the server when storing bookings.

Can I style the native date picker popup?

Only the field itself. The popup is drawn by the browser and cannot be styled.