CSS circular year calendar — Orbit example
A circular year calendar shows all twelve months on a single dial — useful as the centerpiece of a personal-planner app, a year-in-review dashboard, or a homepage hero that doubles as a real, glanceable date display. The metaphor is honest: a year is a cycle, and a circle expresses that more naturally than a 12-grid of rectangles.
This example layers four concentric rings (days, months, seasons, and event markers) around a central year label. The day numbers (1–30) ride on the outer ring as <o-arc> curved-text elements, the months and seasons sit on inner rings, and from-X rotations align each ring so the labels land exactly between the tick marks.
Examples include the current Orbit stylesheet and runtime. Get both files for your project.
How it works
Section titled “How it works”useRange(1, 30)plus.mapgenerates the 30 day-tickvectorelements and the 30 day-number<o-arc>elements without writing them by hand. In a vanilla project, generate them with a server template or a one-offforloop.<o-arc>for the month and season labels is what lets the text follow the curve of its ring. Because each<o-arc>is auto-distributed around its parentorbit-N, you only need to drop the labels in order — Orbit handles the angles.flipon the bottom-half labels (Apr–Sep, Summer) keeps them readable. Withoutflip, “Jun” on the bottom of the dial would render upside-down to anyone reading the calendar.from-Xring offsets (from-355,from-15,from-6) nudge each ring by a few degrees so the day ticks line up with the month boundaries instead of straddling them.- Two
vectormarkers withangle-60andangle-222highlight the current month and current day. Update them from JavaScript to make the calendar live.
Customization
Section titled “Customization”Make it live by computing the angles from Date.now():
const now = new Date();const monthAngle = now.getMonth() * 30; // 12 months × 30°const dayAngle = (now.getDate() - 1) * 12; // ~30 days × 12°document.querySelector('.month').style.setProperty('--o-angle-composite', monthAngle + 'deg');document.querySelector('.day').style.setProperty('--o-angle-composite', dayAngle + 'deg');Color the seasons to make the dial readable at a glance:
.orbit-4 o-arc:nth-child(1) { --o-fill: #c8e6f5; } /* Winter */.orbit-4 o-arc:nth-child(2) { --o-fill: #d4f5c8; } /* Spring */.orbit-4 o-arc:nth-child(3) { --o-fill: #f5e8c8; } /* Summer */.orbit-4 o-arc:nth-child(4) { --o-fill: #f5d4c8; } /* Autumn */Switch the language of the month labels — replace “Jan, Feb, Mar…” with the equivalents in your locale. The layout is language-agnostic.
Related
Section titled “Related”- Calendar examples hub — including the Chronodex day planner
<o-arc>element reference- Smartwatch face example — uses the same
<o-arc>text-on-curve pattern
Use this in your project
Section titled “Use this in your project”Install Orbit and the markup above gives you the entire calendar dial.