27 CSS Calendar Designs 16 / 27
Minimalist Circular / Radial Calendar Layout
Days arranged around an elegant ring instead of a grid, positioned with trig-computed transforms.
The code
<div class="cal16">
<div class="cal16__stage" id="cal16Stage">
<div class="cal16__ring cal16__ring--1"></div>
<div class="cal16__ring cal16__ring--2"></div>
<div class="cal16__ring cal16__ring--3"></div>
<div class="cal16__ticks" id="cal16Ticks"></div>
<div class="cal16__wlabels" id="cal16Wlabels"></div>
<!-- Center hub -->
<div class="cal16__center">
<div class="cal16__center-month">June</div>
<div class="cal16__center-year">2026</div>
<div class="cal16__center-divider"></div>
<div class="cal16__center-today">the 8th</div>
<div class="cal16__center-events">3 events today</div>
</div>
<!-- Days injected by JS around the ring -->
<div id="cal16Days"></div>
<div class="cal16__nav">
<div class="cal16__nav-btn">‹</div>
<div class="cal16__nav-btn">›</div>
</div>
</div>
</div> <div class="cal16">
<div class="cal16__stage" id="cal16Stage">
<div class="cal16__ring cal16__ring--1"></div>
<div class="cal16__ring cal16__ring--2"></div>
<div class="cal16__ring cal16__ring--3"></div>
<div class="cal16__ticks" id="cal16Ticks"></div>
<div class="cal16__wlabels" id="cal16Wlabels"></div>
<!-- Center hub -->
<div class="cal16__center">
<div class="cal16__center-month">June</div>
<div class="cal16__center-year">2026</div>
<div class="cal16__center-divider"></div>
<div class="cal16__center-today">the 8th</div>
<div class="cal16__center-events">3 events today</div>
</div>
<!-- Days injected by JS around the ring -->
<div id="cal16Days"></div>
<div class="cal16__nav">
<div class="cal16__nav-btn">‹</div>
<div class="cal16__nav-btn">›</div>
</div>
</div>
</div>.cal16, .cal16 *, .cal16 *::before, .cal16 *::after {
box-sizing: border-box; margin: 0; padding: 0;
}
.cal16 ::selection { background: #c89b6a; color: #fff; }
.cal16 {
--bg: #faf8f4;
--ink: #2b2820;
--ink2: #837c6e;
--ink3: #c4bcab;
--hair: #e7e1d5;
--gold: #c89b6a;
--gold-d: #a47c4c;
--rose: #c97a6a;
--ring: #ddd5c6;
font-family: 'Jost', sans-serif;
background: var(--bg);
background-image: radial-gradient(circle at center, #fffdfa 0%, #f2ede3 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 20px;
color: var(--ink);
}
@keyframes cal16-in {
from { opacity: 0; transform: scale(0.9) rotate(-8deg); }
to { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes cal16-spin-ring {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes cal16-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(200,155,106,0.5); }
50% { box-shadow: 0 0 0 8px rgba(200,155,106,0); }
}
.cal16__stage {
position: relative;
width: 560px;
height: 560px;
max-width: 92vw;
max-height: 92vw;
animation: cal16-in 0.7s cubic-bezier(0.22,1,0.36,1) both;
}
/* Decorative concentric rings */
.cal16__ring {
position: absolute;
border-radius: 50%;
border: 1px solid var(--hair);
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
/* Outer ring sits just inside where the day numbers orbit */
.cal16__ring--1 { width: 75%; height: 75%; }
/* Middle dashed ring */
.cal16__ring--2 { width: 52%; height: 52%; border-style: dashed; border-color: var(--ring); }
/* Inner ring hugs the center hub */
.cal16__ring--3 { width: 30%; height: 30%; }
/* Slowly rotating tick marks ring — anchored at exact center, ticks pushed out by transform */
.cal16__ticks {
position: absolute;
width: 0; height: 0;
top: 50%; left: 50%;
animation: cal16-spin-ring 160s linear infinite;
}
.cal16__tick {
position: absolute;
top: 0; left: 0;
width: 1px; height: 6px;
background: var(--ink3);
transform-origin: 0 0;
}
/* ── Day cells positioned around the circle ──
Each cell uses: rotate(θ) translateY(-radius) rotate(-θ)
to sit on the ring while keeping text upright.
θ set inline per cell. ── */
.cal16__day {
position: absolute;
top: 50%; left: 50%;
width: 42px; height: 42px;
margin: -21px 0 0 -21px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-family: 'Jost', sans-serif;
font-size: 14px;
font-weight: 400;
color: var(--ink);
cursor: pointer;
transition: all 0.2s;
}
.cal16__day:hover { background: #fff; box-shadow: 0 4px 14px rgba(43,40,32,0.1); }
.cal16__day.weekend { color: var(--rose); }
.cal16__day.today {
background: var(--gold);
color: #fff;
font-weight: 600;
animation: cal16-pulse 2.5s ease-in-out infinite;
}
.cal16__day.selected:not(.today) {
background: #fff;
color: var(--gold-d);
font-weight: 600;
box-shadow: 0 0 0 1.5px var(--gold);
}
/* event dot */
.cal16__day .ev {
position: absolute;
bottom: 4px;
width: 4px; height: 4px;
border-radius: 50%;
background: var(--rose);
}
.cal16__day.today .ev { background: #fff; }
/* ── Center hub ── */
.cal16__center {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 38%;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.cal16__center-month {
font-family: 'Cormorant', serif;
font-size: 54px;
font-weight: 400;
line-height: 0.9;
color: var(--ink);
letter-spacing: 0.01em;
}
.cal16__center-year {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.4em;
color: var(--ink3);
margin-top: 8px;
padding-left: 0.4em;
}
.cal16__center-divider {
width: 40px; height: 1px;
background: var(--gold);
margin: 14px 0;
opacity: 0.5;
}
.cal16__center-today {
font-family: 'Cormorant', serif;
font-style: italic;
font-size: 18px;
color: var(--ink2);
}
.cal16__center-events {
font-size: 11px;
letter-spacing: 0.1em;
color: var(--ink3);
margin-top: 6px;
text-transform: uppercase;
}
/* Weekday labels on the outer edge */
.cal16__wlabels {
position: absolute;
width: 100%; height: 100%;
top: 0; left: 0;
}
.cal16__wlabel {
position: absolute;
top: 50%; left: 50%;
font-size: 9px;
font-weight: 600;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--ink3);
transform-origin: 0 0;
}
/* Nav buttons */
.cal16__nav {
position: absolute;
bottom: -6px; left: 50%;
transform: translateX(-50%);
display: flex;
gap: 12px;
}
.cal16__nav-btn {
width: 36px; height: 36px;
border-radius: 50%;
background: #fff;
border: 1px solid var(--hair);
display: flex; align-items: center; justify-content: center;
cursor: pointer;
color: var(--gold-d);
font-size: 15px;
transition: all 0.2s;
user-select: none;
box-shadow: 0 2px 8px rgba(43,40,32,0.06);
}
.cal16__nav-btn:hover { background: var(--gold); color: #fff; border-color: var(--gold); }
@media (max-width: 600px) {
.cal16__center-month { font-size: 38px; }
.cal16__day { width: 34px; height: 34px; margin: -17px 0 0 -17px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
.cal16 *, .cal16__ticks { animation: none !important; }
} .cal16, .cal16 *, .cal16 *::before, .cal16 *::after {
box-sizing: border-box; margin: 0; padding: 0;
}
.cal16 ::selection { background: #c89b6a; color: #fff; }
.cal16 {
--bg: #faf8f4;
--ink: #2b2820;
--ink2: #837c6e;
--ink3: #c4bcab;
--hair: #e7e1d5;
--gold: #c89b6a;
--gold-d: #a47c4c;
--rose: #c97a6a;
--ring: #ddd5c6;
font-family: 'Jost', sans-serif;
background: var(--bg);
background-image: radial-gradient(circle at center, #fffdfa 0%, #f2ede3 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 20px;
color: var(--ink);
}
@keyframes cal16-in {
from { opacity: 0; transform: scale(0.9) rotate(-8deg); }
to { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes cal16-spin-ring {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes cal16-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(200,155,106,0.5); }
50% { box-shadow: 0 0 0 8px rgba(200,155,106,0); }
}
.cal16__stage {
position: relative;
width: 560px;
height: 560px;
max-width: 92vw;
max-height: 92vw;
animation: cal16-in 0.7s cubic-bezier(0.22,1,0.36,1) both;
}
/* Decorative concentric rings */
.cal16__ring {
position: absolute;
border-radius: 50%;
border: 1px solid var(--hair);
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
/* Outer ring sits just inside where the day numbers orbit */
.cal16__ring--1 { width: 75%; height: 75%; }
/* Middle dashed ring */
.cal16__ring--2 { width: 52%; height: 52%; border-style: dashed; border-color: var(--ring); }
/* Inner ring hugs the center hub */
.cal16__ring--3 { width: 30%; height: 30%; }
/* Slowly rotating tick marks ring — anchored at exact center, ticks pushed out by transform */
.cal16__ticks {
position: absolute;
width: 0; height: 0;
top: 50%; left: 50%;
animation: cal16-spin-ring 160s linear infinite;
}
.cal16__tick {
position: absolute;
top: 0; left: 0;
width: 1px; height: 6px;
background: var(--ink3);
transform-origin: 0 0;
}
/* ── Day cells positioned around the circle ──
Each cell uses: rotate(θ) translateY(-radius) rotate(-θ)
to sit on the ring while keeping text upright.
θ set inline per cell. ── */
.cal16__day {
position: absolute;
top: 50%; left: 50%;
width: 42px; height: 42px;
margin: -21px 0 0 -21px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-family: 'Jost', sans-serif;
font-size: 14px;
font-weight: 400;
color: var(--ink);
cursor: pointer;
transition: all 0.2s;
}
.cal16__day:hover { background: #fff; box-shadow: 0 4px 14px rgba(43,40,32,0.1); }
.cal16__day.weekend { color: var(--rose); }
.cal16__day.today {
background: var(--gold);
color: #fff;
font-weight: 600;
animation: cal16-pulse 2.5s ease-in-out infinite;
}
.cal16__day.selected:not(.today) {
background: #fff;
color: var(--gold-d);
font-weight: 600;
box-shadow: 0 0 0 1.5px var(--gold);
}
/* event dot */
.cal16__day .ev {
position: absolute;
bottom: 4px;
width: 4px; height: 4px;
border-radius: 50%;
background: var(--rose);
}
.cal16__day.today .ev { background: #fff; }
/* ── Center hub ── */
.cal16__center {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 38%;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.cal16__center-month {
font-family: 'Cormorant', serif;
font-size: 54px;
font-weight: 400;
line-height: 0.9;
color: var(--ink);
letter-spacing: 0.01em;
}
.cal16__center-year {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.4em;
color: var(--ink3);
margin-top: 8px;
padding-left: 0.4em;
}
.cal16__center-divider {
width: 40px; height: 1px;
background: var(--gold);
margin: 14px 0;
opacity: 0.5;
}
.cal16__center-today {
font-family: 'Cormorant', serif;
font-style: italic;
font-size: 18px;
color: var(--ink2);
}
.cal16__center-events {
font-size: 11px;
letter-spacing: 0.1em;
color: var(--ink3);
margin-top: 6px;
text-transform: uppercase;
}
/* Weekday labels on the outer edge */
.cal16__wlabels {
position: absolute;
width: 100%; height: 100%;
top: 0; left: 0;
}
.cal16__wlabel {
position: absolute;
top: 50%; left: 50%;
font-size: 9px;
font-weight: 600;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--ink3);
transform-origin: 0 0;
}
/* Nav buttons */
.cal16__nav {
position: absolute;
bottom: -6px; left: 50%;
transform: translateX(-50%);
display: flex;
gap: 12px;
}
.cal16__nav-btn {
width: 36px; height: 36px;
border-radius: 50%;
background: #fff;
border: 1px solid var(--hair);
display: flex; align-items: center; justify-content: center;
cursor: pointer;
color: var(--gold-d);
font-size: 15px;
transition: all 0.2s;
user-select: none;
box-shadow: 0 2px 8px rgba(43,40,32,0.06);
}
.cal16__nav-btn:hover { background: var(--gold); color: #fff; border-color: var(--gold); }
@media (max-width: 600px) {
.cal16__center-month { font-size: 38px; }
.cal16__day { width: 34px; height: 34px; margin: -17px 0 0 -17px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
.cal16 *, .cal16__ticks { animation: none !important; }
}(() => {
const stage = document.getElementById('cal16Stage');
const daysWrap = document.getElementById('cal16Days');
const ticksWrap = document.getElementById('cal16Ticks');
const wlabelsWrap = document.getElementById('cal16Wlabels');
const DAYS = 30;
const today = 8;
const events = {2:1, 4:1, 7:1, 8:1, 9:1, 11:1, 13:1, 17:1, 20:1, 25:1};
// June 1, 2026 is a Monday → Sunday index. weekday of day d:
// Jun 1 = Mon(1). day-of-week = (d) % 7 where 0=Sun... compute:
const firstDow = 1; // Monday
const isWeekend = d => { const dow = (firstDow + (d-1)) % 7; return dow === 0 || dow === 6; };
const R = 210; // radius for day-number ring (stage radius = 280)
for (let d = 1; d <= DAYS; d++) {
const angle = (d / DAYS) * 360 - 90; // start at top
const rad = angle * Math.PI / 180;
const x = Math.cos(rad) * R;
const y = Math.sin(rad) * R;
const el = document.createElement('div');
el.className = 'cal16__day';
if (d === today) el.classList.add('today');
if (isWeekend(d)) el.classList.add('weekend');
el.style.transform = `translate(${x}px, ${y}px)`;
el.innerHTML = d + (events[d] ? '<span class="ev"></span>' : '');
el.addEventListener('click', function() {
daysWrap.querySelectorAll('.cal16__day').forEach(c => c.classList.remove('selected'));
this.classList.add('selected');
});
daysWrap.appendChild(el);
}
// tick marks — placed by rotate + translateY from the dead-center anchor
const tickR = 232;
for (let i = 0; i < 60; i++) {
const t = document.createElement('div');
t.className = 'cal16__tick';
const ang = (i / 60) * 360;
t.style.transform = `rotate(${ang}deg) translate(0, ${-tickR}px)`;
if (i % 5 === 0) { t.style.height = '10px'; t.style.opacity = '0.6'; }
ticksWrap.appendChild(t);
}
// weekday labels on the outer edge
const labels = ['S','M','T','W','T','F','S'];
const RL = 256;
for (let i = 0; i < 7; i++) {
const ang = (i / 7) * 360 - 90;
const rad = ang * Math.PI / 180;
const x = Math.cos(rad) * RL;
const y = Math.sin(rad) * RL;
const l = document.createElement('div');
l.className = 'cal16__wlabel';
l.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
l.textContent = labels[i];
wlabelsWrap.appendChild(l);
}
})(); (() => {
const stage = document.getElementById('cal16Stage');
const daysWrap = document.getElementById('cal16Days');
const ticksWrap = document.getElementById('cal16Ticks');
const wlabelsWrap = document.getElementById('cal16Wlabels');
const DAYS = 30;
const today = 8;
const events = {2:1, 4:1, 7:1, 8:1, 9:1, 11:1, 13:1, 17:1, 20:1, 25:1};
// June 1, 2026 is a Monday → Sunday index. weekday of day d:
// Jun 1 = Mon(1). day-of-week = (d) % 7 where 0=Sun... compute:
const firstDow = 1; // Monday
const isWeekend = d => { const dow = (firstDow + (d-1)) % 7; return dow === 0 || dow === 6; };
const R = 210; // radius for day-number ring (stage radius = 280)
for (let d = 1; d <= DAYS; d++) {
const angle = (d / DAYS) * 360 - 90; // start at top
const rad = angle * Math.PI / 180;
const x = Math.cos(rad) * R;
const y = Math.sin(rad) * R;
const el = document.createElement('div');
el.className = 'cal16__day';
if (d === today) el.classList.add('today');
if (isWeekend(d)) el.classList.add('weekend');
el.style.transform = `translate(${x}px, ${y}px)`;
el.innerHTML = d + (events[d] ? '<span class="ev"></span>' : '');
el.addEventListener('click', function() {
daysWrap.querySelectorAll('.cal16__day').forEach(c => c.classList.remove('selected'));
this.classList.add('selected');
});
daysWrap.appendChild(el);
}
// tick marks — placed by rotate + translateY from the dead-center anchor
const tickR = 232;
for (let i = 0; i < 60; i++) {
const t = document.createElement('div');
t.className = 'cal16__tick';
const ang = (i / 60) * 360;
t.style.transform = `rotate(${ang}deg) translate(0, ${-tickR}px)`;
if (i % 5 === 0) { t.style.height = '10px'; t.style.opacity = '0.6'; }
ticksWrap.appendChild(t);
}
// weekday labels on the outer edge
const labels = ['S','M','T','W','T','F','S'];
const RL = 256;
for (let i = 0; i < 7; i++) {
const ang = (i / 7) * 360 - 90;
const rad = ang * Math.PI / 180;
const x = Math.cos(rad) * RL;
const y = Math.sin(rad) * RL;
const l = document.createElement('div');
l.className = 'cal16__wlabel';
l.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
l.textContent = labels[i];
wlabelsWrap.appendChild(l);
}
})();More from 27 CSS Calendar Designs
Brutalist CSS Calendar DesignDark Mode CSS Calendar UICSS Grid Calendar LayoutResponsive Mobile-Friendly Calendar UIGlassmorphism Calendar CardDark Mode Calendar DesignEvent Planner & Schedule LayoutNeumorphic Calendar WidgetHorizontal Scroll / Timeline CalendarMinimalist Sidebar Calendar CardCSS Booking Date Picker UICSS Grid Advent Calendar
View the full collection →