webdevpuneet.com

Mobile Medication Reminder Screen — Free Snippet

Mobile Medication Reminder Screen · Mobile · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<div class="mrs-phone">
  <div class="mrs-screen">
    <div class="mrs-status"><span>9:41</span><span class="mrs-batt"><i></i></span></div>
    <header class="mrs-head">
      <div>
        <p class="mrs-date">Thursday, Sep 4</p>
        <h1>Today</h1>
      </div>
      <div class="mrs-streak">
        <span class="mrs-streak-flame">&#128293;</span>
        <b id="mrsStreak">12</b>
      </div>
    </header>

    <div class="mrs-progress-card">
      <div class="mrs-ring" id="mrsRing">
        <svg width="58" height="58" viewBox="0 0 58 58">
          <circle cx="29" cy="29" r="25" fill="none" stroke="#e2e8f0" stroke-width="6"/>
          <circle id="mrsRingFg" cx="29" cy="29" r="25" fill="none" stroke="#059669" stroke-width="6" stroke-linecap="round" stroke-dasharray="157" stroke-dashoffset="157" transform="rotate(-90 29 29)"/>
        </svg>
        <span class="mrs-ring-label" id="mrsRingLabel">0/4</span>
      </div>
      <div>
        <p class="mrs-progress-title" id="mrsProgressTitle">0 of 4 doses taken</p>
        <p class="mrs-progress-sub" id="mrsProgressSub">Next: Metformin at 8:00 AM</p>
      </div>
    </div>

    <div class="mrs-scroll">
      <ul class="mrs-list" id="mrsList">
        <li class="mrs-item" data-time="8:00 AM" data-status="upcoming">
          <span class="mrs-time">8:00<small>AM</small></span>
          <span class="mrs-pill mrs-pill-blue"></span>
          <div class="mrs-info"><b>Metformin</b><small>500mg &middot; 1 tablet &middot; with food</small></div>
          <button class="mrs-check" aria-label="Mark as taken"></button>
        </li>
        <li class="mrs-item" data-time="8:00 AM" data-status="upcoming">
          <span class="mrs-time">8:00<small>AM</small></span>
          <span class="mrs-pill mrs-pill-amber"></span>
          <div class="mrs-info"><b>Vitamin D3</b><small>1000IU &middot; 1 capsule</small></div>
          <button class="mrs-check" aria-label="Mark as taken"></button>
        </li>
        <li class="mrs-item" data-time="1:00 PM" data-status="upcoming">
          <span class="mrs-time">1:00<small>PM</small></span>
          <span class="mrs-pill mrs-pill-purple"></span>
          <div class="mrs-info"><b>Lisinopril</b><small>10mg &middot; 1 tablet</small></div>
          <button class="mrs-check" aria-label="Mark as taken"></button>
        </li>
        <li class="mrs-item" data-time="9:00 PM" data-status="upcoming">
          <span class="mrs-time">9:00<small>PM</small></span>
          <span class="mrs-pill mrs-pill-blue"></span>
          <div class="mrs-info"><b>Metformin</b><small>500mg &middot; 1 tablet &middot; with food</small></div>
          <button class="mrs-check" aria-label="Mark as taken"></button>
        </li>
      </ul>
    </div>

    <div class="mrs-toast" id="mrsToast" hidden>All doses logged for today &#10003;</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

Single data-status attribute per item drives every visual state via CSS attribute selectors
SVG progress ring animates its stroke-dashoffset rather than snapping between values
Next-dose subtitle computed live from the first remaining upcoming item, not hardcoded per item
Streak counter increments only on genuine full-day completion, fully reversible before that
Auto-dismissing completion toast with a rise-in entrance animation
Fully reversible taken/upcoming toggle on every dose, not a one-way action
Color-coded medication pills for quick visual scanning of a longer list
Scrollable list independent of the fixed header and progress card above it
Zero dependencies, vanilla JavaScript only

About this UI Snippet

Mobile Medication Reminder Screen — Progress Ring with Tap-to-Log Doses

Screenshot of the Mobile Medication Reminder Screen snippet rendered live

Medication adherence apps live or die on one interaction: how quickly and clearly a user can confirm they took a dose. This snippet builds that core loop inside a CSS phone frame — a scrollable list of today's doses grouped by time, a single tap on each item to toggle it taken, an SVG progress ring that animates as doses are logged, a "next dose" line that always points at the correct upcoming medication, and a streak counter that increments the moment the day is fully complete.

One data attribute drives the whole item state

Each .mrs-item carries a single data-status attribute set to either "upcoming" or "taken". Every visual change on a logged dose — the filled green checkmark circle, the reduced opacity, the strikethrough on the medication name — is expressed as a CSS rule scoped to .mrs-item[data-status="taken"], so toggling one attribute in JavaScript drives every visual consequence at once rather than needing several class toggles kept in sync by hand.

The progress ring animates its stroke, it does not just relabel

#mrsRingFg is an SVG circle with stroke-dasharray set to its full circumference and stroke-dashoffset computed on every update as circumference - (circumference * takenCount) / total — the same stroke-offset technique used by most circular progress indicators. Because stroke-dashoffset has a CSS transition, each dose logged causes the ring to visibly sweep forward rather than snapping to its new fraction instantly, giving the same satisfying motion as a fitness-ring close animation.

"Next dose" is computed, not written per item

nextUpcoming() walks the item list in DOM order and returns the name and time of the first item still marked "upcoming" — so the subtitle under the progress ring always reflects whichever dose is genuinely next, automatically updating (or disappearing entirely once nothing remains) as doses get logged in any order, not necessarily top to bottom.

A streak that only increments on real completion

updateProgress() checks whether nextUpcoming() returns null — meaning every dose for the day has been marked taken — and only then increments the displayed streak number and shows a completion toast. Marking every dose taken and then un-marking one immediately reverts the subtitle back to a "next dose" line and the streak stays at its prior value, since the increment is a direct consequence of the current state rather than a one-time event that could double-fire or fire on a partial day.

A toast that confirms without blocking

The "All doses logged for today" toast rises in from the bottom with a small transform animation and clears itself automatically after roughly 2.6 seconds via setTimeout, celebrating the completion moment without requiring a dismiss tap or interrupting the user from continuing to review their list.

Extending it for a real medication schedule

Swap the four hardcoded <li> items for a schedule fetched from a real prescriptions API (dose name, dosage, time, and any food/timing instructions), persist the taken/upcoming state to a backend rather than only in the DOM so a mark-as-taken action survives an app restart, and drive the streak counter from a real day-over-day adherence log instead of the single-session increment used in this demo.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA medication list renders with a 0/4 progress ring and a "Next: Metformin at 8:00 AM" subtitle.
  2. 2
    Tap a dose’s check buttonIt fills green, the name gets a strikethrough, and the progress ring sweeps forward to reflect the new count.
  3. 3
    Tap it againThe dose reverts to upcoming and the ring animates back, demonstrating the toggle is fully reversible.
  4. 4
    Mark every dose takenThe subtitle switches to "All doses complete," the streak count increments, and a completion toast rises in.
  5. 5
    Watch the toastIt clears itself automatically after about 2.6 seconds without needing a dismiss tap.
  6. 6
    Wire it to a real scheduleReplace the hardcoded list items with a fetched prescription schedule and persist taken state to a backend.

Real-world uses

Common Use Cases

Medication adherence and health-tracking apps
The direct, canonical use case — a daily dose checklist with visible progress and a habit-forming streak mechanic.
Supplement and vitamin routine trackers
The same tap-to-log pattern and progress ring apply directly to any multi-item daily routine, not only prescribed medication.
Caregiver and eldercare companion apps
A clear, low-friction way for a caregiver to confirm doses were taken on behalf of someone else, with the same honest computed-state logic.
Teaching attribute-driven UI state
A clean example of expressing all of an item’s visual states through one data attribute and CSS attribute selectors instead of multiple manually toggled classes.
Related: Mobile Fitness Screen
See the Mobile Fitness Screen for a related progress-ring and daily-goal pattern worth comparing against this one.
Related: Mobile Notifications Screen
See the Mobile Notifications Screen for how a real dose reminder push would typically lead a user into this screen.

Got questions?

Frequently Asked Questions

updateProgress() counts every item whose data-status attribute equals "taken", computes a stroke-dashoffset value from that count against the ring’s known circumference, and applies it to the ring’s foreground circle. A CSS transition on stroke-dashoffset animates the visible sweep rather than jumping instantly.

nextUpcoming() iterates the dose list in its current DOM order and returns the name and time of the first item still marked "upcoming". Because it re-runs after every toggle, the subtitle always reflects an accurate next dose regardless of which item was logged.

Yes — tapping an already-taken item’s check button toggles its data-status back to "upcoming", which reverses every visual state (checkmark, opacity, strikethrough) and recalculates the ring, next-dose subtitle, and streak accordingly.

Only when nextUpcoming() returns null, meaning every dose in the list is currently marked taken. Un-marking any dose afterward reverts the subtitle to a next-dose line without decrementing the streak, since the increment models same-day completion rather than a fragile one-time event.

No — this demo keeps state only in the DOM via data-status attributes, so a page refresh resets every dose to upcoming. A production build should persist each toggle to a backend or local storage so a logged dose survives an app restart.

Yes. Model each dose as an object with a taken boolean in an array or state list, derive the taken count and the next-upcoming dose from that array on every render, and compute the same ring stroke-dashoffset value from the derived count.