Skip to content

Mini Calendar

Compact month calendar generated with vanilla JS and styled with pure CSS: selectable days, today marker, month navigation and full arrow-key support.

Live preview

Open in new tab

Code

A compact month calendar generated with vanilla JavaScript and styled with pure CSS. It shows one month at a time, marks today with a dot, lets users pick a day with mouse or keyboard and reports the choice in a footer. Use it in sidebars, booking widgets, dashboards or as the base of a custom date picker.

How it works

The root .mc-cal carries data-mc-calendar plus three options: data-week-start, data-locale and data-selected. The markup only contains the shell: the .mc-head row with .mc-prev, the .mc-month heading and .mc-next, an empty table.mc-grid, and the .mc-foot row with the .mc-picked text and the .mc-today button.

On DOMContentLoaded the script fills the header row with weekday names from Intl.DateTimeFormat, so they follow the chosen locale, and renders the month into .mc-body. It always draws six weeks so the calendar never changes height. Days of the current month become button.mc-day elements with a data-date value in YYYY-MM-DD format; days of the previous and next month are muted .mc-day--outside spans. The selected day gets aria-pressed="true" and a filled circle, and today gets aria-current="date", shown as an accent number with a small dot.

Clicking a day, or pressing the Today button, selects it, updates data-selected on the root and fires a bubbling mc:select event whose detail.date holds the ISO date. The arrow buttons move one month back or forward.

Customization

  • data-week-start="1" on .mc-cal: use 0 to start weeks on Sunday.
  • data-locale="en-US": any BCP 47 tag such as de-DE or fr-FR translates the month name, the weekday headers and the formatted dates.
  • data-selected: set an ISO date like 2026-03-14 to preselect a day; leave it empty to select today.
  • --mc-accent and --mc-accent-soft: the selected day, today marker, hover circle and navigation buttons.
  • --mc-size: the maximum diameter of each day circle.
  • --mc-radius and max-width: 21rem in .mc-cal: the card corner radius and width.
  • Listen for mc:select on the root to fill a hidden input or load events for the chosen date.

Accessibility

The calendar is a real data table labelled by the month heading through aria-labelledby, with weekday column headers whose abbr titles give the full names. Each day button has a full date aria-label such as "Thursday, October 15, 2026" and uses aria-pressed for the selection. A roving tabindex keeps only one day in the Tab order: arrow keys move by day and week, Home and End jump to the start and end of the week, PageUp and PageDown change the month (with Shift, the year). The month heading and the selection text are aria-live regions. Every control has a visible :focus-visible outline, and prefers-reduced-motion turns off the transitions.

Usage notes

The calendar needs JavaScript to render its days. Several calendars can share a page; each gets its own heading ID.

Requirements

No dependencies. Pure HTML, CSS and JavaScript.

Mini Calendar – Pure CSS calendars component screenshot
Mini Calendar · Pure CSS Calendars

More Calendars

Month Calendar with Events – Tailwind CSS calendars preview

Month Calendar with Events

Tailwind CSS month calendar with colored event pills, today highlight, prev/next navigation, keyboard support and a day agenda.