webdevpuneet.com

Mobile Calendar Screen — Free HTML CSS JS Snippet

Mobile Calendar Screen · Mobile · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<div class="mcl-phone">
  <div class="mcl-screen">
    <div class="mcl-status"><span>9:41</span><span class="mcl-batt"><i></i></span></div>
    <header class="mcl-head">
      <div><small>March 2026</small><h1>This week</h1></div>
      <div class="mcl-ava">AM</div>
    </header>

    <div class="mcl-week" id="mclWeek">
      <button class="mcl-day" data-day="Mon 9"><small>Mon</small><b>9</b><i class="mcl-mk"></i></button>
      <button class="mcl-day" data-day="Tue 10"><small>Tue</small><b>10</b><i class="mcl-mk"></i></button>
      <button class="mcl-day active" data-day="Wed 11"><small>Wed</small><b>11</b><i class="mcl-mk"></i></button>
      <button class="mcl-day" data-day="Thu 12"><small>Thu</small><b>12</b></button>
      <button class="mcl-day" data-day="Fri 13"><small>Fri</small><b>13</b><i class="mcl-mk"></i></button>
      <button class="mcl-day" data-day="Sat 14"><small>Sat</small><b>14</b></button>
      <button class="mcl-day" data-day="Sun 15"><small>Sun</small><b>15</b></button>
    </div>

    <div class="mcl-agenda" id="mclAgenda">
      <div class="mcl-slot" data-for="Wed 11">
        <div class="mcl-time">09:00</div>
        <div class="mcl-ev e1"><b>Team standup</b><small>Design squad · 30 min</small></div>
      </div>
      <div class="mcl-slot" data-for="Wed 11">
        <div class="mcl-time">11:30</div>
        <div class="mcl-ev e2"><b>Client review</b><small>Bella Napoli app · Zoom</small></div>
      </div>
      <div class="mcl-slot" data-for="Wed 11">
        <div class="mcl-time">15:00</div>
        <div class="mcl-ev e3"><b>Focus block</b><small>Prototype polish</small></div>
      </div>
      <div class="mcl-slot" data-for="Tue 10">
        <div class="mcl-time">10:00</div>
        <div class="mcl-ev e2"><b>1:1 with Jordan</b><small>Weekly sync · 30 min</small></div>
      </div>
      <div class="mcl-slot" data-for="Mon 9">
        <div class="mcl-time">13:00</div>
        <div class="mcl-ev e1"><b>Sprint planning</b><small>Whole team · 1 hr</small></div>
      </div>
      <div class="mcl-slot" data-for="Fri 13">
        <div class="mcl-time">16:30</div>
        <div class="mcl-ev e3"><b>Design critique</b><small>Portfolio review</small></div>
      </div>
      <p class="mcl-empty" id="mclEmpty" hidden>Nothing scheduled. Enjoy the free time! 🌤</p>
    </div>

    <button class="mcl-fab" id="mclFab" aria-label="Add event">+</button>
  </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

Week day strip
Seven equal pill buttons with weekday and date.
Event dot markers
Busy days flagged before selection.
Per-day filtering
data-for tags drive which events show.
Replayed entrance
Reflow trick re-triggers the slide-in.
Contextual header
Title shows Today or the day label.
Friendly empty state
Warm message when a day is free.
Color-coded events
Category shown via a colored left border.
No dependency
Pure HTML, CSS, and vanilla JavaScript.

About this UI Snippet

Mobile Calendar Screen — Week Agenda UI

Screenshot of the Mobile Calendar Screen snippet rendered live

A calendar screen balances two views at once — a compact week strip to pick a day, and an agenda list of that day's events. This snippet builds a complete, interactive one inside a CSS phone frame: tapping a day highlights it, filters the agenda to that day's events, updates the header, and shows a friendly empty state when a day is free — plus a floating add button — in HTML, CSS, and vanilla JavaScript with no dependency.

The week strip with event dots

The seven days sit in an equal-width flex row as pill buttons, each showing the weekday abbreviation and date. Days that have events carry a small dot marker positioned at the bottom, so you can see at a glance which days are busy before selecting them. The selected day flips to a dark pill and its dot turns white to stay visible against the dark background.

Filtering the agenda by day

Every event slot carries a data-for attribute naming its day. Selecting a day loops the slots, showing only matching ones and hiding the rest, and counts how many were shown. This single-source filter means the same event data can drive any day without duplicating markup — you just tag each event with its day and let the selection decide what renders.

Re-triggering the entrance animation

When you switch days, the newly shown slots replay their slide-in animation. Because the elements are only being un-hidden rather than recreated, the code clears the animation, forces a reflow with void slot.offsetWidth, and restores it — the standard trick to restart a CSS animation so each day's agenda animates in fresh rather than appearing statically.

A contextual header and empty state

The header title updates to the selected day, showing "Today" for the current day and the day label otherwise, so the context is always clear. When a selected day has no events, a warm empty-state message appears instead of a blank list — the difference between a screen that feels broken and one that feels considerate.

Color-coded events and a rotating FAB

Events use a colored left border to categorize them, and the floating add button spins slightly on press via a scale-and-rotate transform, the playful touch real calendar apps use for their compose action.

Accessibility and performance

The day strip and the add button are real buttons, so the calendar is keyboard-navigable and screen readers announce each day. When you adapt this, expose the selected day with aria-pressed or aria-current="date" so the active day is announced, and label each day button with its full date rather than just the number so it reads as "Wednesday, March 11" instead of a bare "11". The event dots are decorative, so pair them with text — a count or a label — for non-visual users. Performance is minimal: switching days toggles display on a fixed set of event slots rather than rebuilding the agenda, and the entrance replay is a reflow-triggered CSS animation with no per-frame JavaScript. Because every event is tagged with its day and filtered in place, there is no data cloning or re-render on selection. For a full month or multi-week view with many events, you would render only the visible range, but for a single week the direct show-and-hide keeps the interaction instant and the code easy to follow.

Reusing it

Feed the week and events from your calendar data, render the dot markers from which days have events, and wire the add button to your event composer. Lift it out of the phone frame for a responsive web calendar, or keep it framed beside a horizontal timeline to present a scheduling app.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA week calendar renders with a day strip and today's agenda already selected.
  2. 2
    Read the event dotsDays with events show a small dot so you can spot busy days at a glance.
  3. 3
    Tap a different dayThe day highlights, the agenda filters to its events, and they slide in fresh.
  4. 4
    Watch the headerThe title updates to the selected day, showing "Today" for the current day.
  5. 5
    Find a free daySelect a day with no events and a friendly empty-state message appears.
  6. 6
    Tap the add buttonThe floating button spins on press for its compose action.

Real-world uses

Common Use Cases

Calendar app week views
Pick a day from a seven-pill strip, with event dots flagging busy days, as the phone version of a calendar widget.
Appointment scheduling
Pair with a time slot picker so a selected day leads directly to choosing a start time.
Agenda and timeline lists
Reuse the agenda like a horizontal timeline, where data-for tags control which events show for each day.
Booking availability flows
Feed the chosen day into an availability scheduler, with a friendly empty state when nothing is booked.
Replayed entrance animations
Study the reflow trick that re-triggers the slide-in each time a different day is selected, so the list never appears to change silently.
Related: Mobile Alarm Clock Screen
See the Mobile Alarm Clock Screen for a related mobile pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Each event slot has a data-for attribute naming its day. Selecting a day loops all slots and sets display to flex for matches and none for the rest, then counts the matches. Because every event is tagged with its day, one set of markup can serve any day — the selection decides what is visible rather than swapping templates.

The slots are un-hidden rather than recreated, and CSS animations only play on first render. To replay the slide-in, the code sets animation to none, reads slot.offsetWidth to force a reflow, then clears the override. That reflow makes the browser treat the animation as new, so each day's agenda animates in fresh.

The demo treats Wednesday the 11th as the current day, so selecting it sets the title to Today and any other day shows its label. In a real app you would compare the selected date to the actual current date and format the title accordingly.

The filter counts how many slots matched the selected day. If none did, a hidden empty-state message is revealed instead of leaving a blank list. Showing a warm note on free days is a small touch that keeps the screen from looking broken when there is nothing scheduled.

Hold the selected day in state and derive the visible events with a filter in useMemo (React), computed (Vue), or a pipe (Angular) rather than toggling display. Render the day strip and dot markers from your event data. Re-trigger the entrance with a key change keyed to the selected day. The CSS and Tailwind utilities port directly.