webdevpuneet.com

Calendar Widget — Free HTML CSS JS Snippet

Calendar Widget · Dashboards · Plain HTML, CSS & JS · Live preview

CategoryDashboards

Copy & paste

Source Code

<div class="wrap">
  <div class="cal">
    <div class="cal-head">
      <button class="nav-btn" onclick="shift(-1)">‹</button>
      <div class="month-label" id="month-label"></div>
      <button class="nav-btn" onclick="shift(1)">›</button>
    </div>

    <div class="day-names">
      <span>Su</span><span>Mo</span><span>Tu</span><span>We</span>
      <span>Th</span><span>Fr</span><span>Sa</span>
    </div>

    <div class="days" id="days"></div>

    <div class="events-section">
      <div class="events-head">Upcoming</div>
      <ul class="events-list" id="events-list"></ul>
    </div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Monthly grid: firstDay padding + daysInMonth + trailing padding — always 7 columns
today class: highlighted with accent background colour
has-event class: ::after dot indicator at bottom of day cell
selected class: click-to-select with accent tint, auto-deselects previous
Upcoming events panel: filtered to next 30 days, sorted ascending, limited to 4
Event items: coloured dot + truncated title + formatted short date
shift(dir): setMonth handles month boundary wrap automatically
Prev/next nav buttons with hover accent border effect

About this UI Snippet

Calendar Widget — Monthly Grid, Today Highlight, Event Dots & Upcoming Events Panel

Screenshot of the Calendar Widget snippet rendered live

A calendar widget is a fundamental dashboard component for displaying date-based context alongside other metrics and tasks. This snippet provides a complete mini monthly calendar: previous/next month navigation, a 7-column day grid with today highlighted, event dot indicators on days that have events, click-to-select days, and a dynamic upcoming events panel that filters events within the next 30 days — all in plain HTML, CSS, and vanilla JavaScript.

How the calendar grid is generated

The render() function computes three things: the day of the week the month starts on (firstDay), the number of days in the month, and the number of days in the previous month (for padding). The grid always starts on Sunday. Padding days from the previous month fill the start of the first row; padding days from the next month fill the end of the last row. Each day div is created with classList flags: .other (padding days), .today (today's date), .has-event (dot indicator), and .selected (click selection).

The event dot indicator

Days with matching events get the .has-event class which adds a ::after pseudo-element — a 4px circle positioned at the bottom of the day cell. The dot is accent coloured for normal days and white on the .today cell (since the today background is the accent colour). This is a standard calendar pattern used by Apple Calendar, Google Calendar, and iOS date pickers.

The upcoming events panel

Below the calendar grid, an upcoming events list filters the events array to entries within the next 30 days from today. Events are sorted by date ascending and limited to 4 items. Each event shows a coloured dot matching the event's colour, the event title (truncated with text-overflow: ellipsis), and the formatted date. If no upcoming events exist, a "No upcoming events" italic message shows instead.

Month navigation

The shift(dir) function calls cur.setMonth(cur.getMonth() + dir) — JavaScript's Date handles month boundary arithmetic automatically. Shifting from January by -1 gives December of the previous year. The calendar re-renders fully on each navigation.

Customising events

Replace the events array with your own event data. Each event needs date (YYYY-MM-DD format), title, and color. Wire to a calendar API (Google Calendar, CalDAV) by replacing the events array with data fetched from the API on render.

Step by step

How to Use

  1. 1
    Navigate monthsClick the ‹ and › buttons to move to the previous or next month. The grid regenerates, today highlight remains on the current date, and event dots update for each month.
  2. 2
    Click a day to select itClick any day in the current month to highlight it with a selected state (indigo tint). The previously selected day deselects. Today cannot be selected — it always shows the filled accent background.
  3. 3
    Update the events arrayIn the JS panel, edit the events array. Each event needs: date in YYYY-MM-DD format, title string, and color hex. Events show as dots on the calendar and appear in the upcoming panel if within the next 30 days.
  4. 4
    Change the week start dayThe calendar starts on Sunday (getDay() = 0). To start on Monday, subtract 1 from firstDay and adjust the day-names header order: Mo Tu We Th Fr Sa Su.
  5. 5
    Extend upcoming events rangeIn render(), change the cutoff from 30 days to any number: cutoff.setDate(cutoff.getDate() + N). Increase the .slice(0, 4) limit to show more upcoming events in the panel.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component managing cur state with useState and events with useMemo, or "Tailwind" for a Tailwind CSS version.

Real-world uses

Common Use Cases

Dashboard date context and event overview widget
Show the current month alongside key events — sprint deadlines, team meetings, product launches — in a compact sidebar widget. The upcoming events panel gives date-aware context without opening a full calendar application.
Booking and appointment date picker for scheduling UIs
Wire the day click handler to a time slot picker panel, or use a single-field date picker for compact forms. When a day is clicked, fetch available slots from your API and display them below the calendar. The visual selected state confirms the chosen date before the user picks a time.
Content calendar and publishing schedule displays
Mark content publishing dates, social media post days, and email campaign sends as events — for a week-grid view, see the schedule timetable. Colour-code by content type (blog = indigo, social = pink, email = green). The dot indicators give a visual density map of publishing frequency.
Integration with Google Calendar or CalDAV APIs
Replace the static events array with a fetch call to the Google Calendar API or any CalDAV endpoint. Parse the events from the API response into the {date, title, color} format the widget expects. Re-fetch on each month navigation to load events for the new month.
Learn JavaScript Date arithmetic for calendar generation
The render function demonstrates how to use JavaScript Date to compute month grids: getDay() for the starting weekday, setDate(0) to get the last day of the previous month, and setMonth() for month navigation. These techniques apply to any date-driven UI.
Team availability and leave calendar overview widgets
Show team leave days, public holidays, and team events in a shared calendar widget. Each team member can have a distinct event colour. The upcoming list surfaces the next important dates across all event categories in one scannable list.
Related: Consistent Hashing Visualizer
See the Consistent Hashing Visualizer for a related dashboards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

render() creates a Date for the first day of cur month and reads .getDay() to know which column (0=Sunday, 6=Saturday) the month starts on. It fills leftward from that column with trailing days from the previous month. It then places all days in the current month. Finally it fills any remaining cells in the last row with leading days of the next month. This always produces a complete 7-column grid, typically 5 rows (35 cells) or occasionally 6 rows (42 cells) for months that start on Saturday or Sunday.

Call the Google Calendar Events API: fetch("https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin="+startOfMonth+"&timeMax="+endOfMonth+"&key="+API_KEY). Map the response items to {date: item.start.dateTime || item.start.date, title: item.summary, color: "#6366f1"}. Call render() after the fetch resolves. For authentication, use Google OAuth2 and pass the access token in the Authorization header instead of the API key.

Change the firstDay calculation: const firstDay = (new Date(year, month, 1).getDay() + 6) % 7. This converts Sunday (0) to 6 and Monday (1) to 0, shifting the week start. Also update the day-names header to Mo Tu We Th Fr Sa Su. The padding calculations for prev/next month days remain the same.

Click "JSX" to download. Manage cur with useState<Date>(new Date(year, month, 1)). Compute grid days with useMemo([cur]) — run the same padding and day calculations, returning an array of day objects. Render the array to day divs. Manage selectedDate with useState<string|null>(null). For events, fetch from your API in a useEffect that re-runs when cur changes.