A fitness app profile screen in pure CSS and vanilla JavaScript: an avatar inside a level progress ring, total stats, weekly activity bars, an achievements badge grid with a details bottom sheet and a personal records list. It is an HTML mobile template for mobile websites and PWAs and can be packaged as a native app with Capacitor. Use it for running, cycling or gym apps.
How it works
The root .fpr-app is a 430 px app column with a sticky top bar and a sticky bottom tab bar (Home, Activity, a central Record button, Challenges, Profile).
The .fpr-ring is an SVG with a track circle and a .fpr-ring__value circle. The script reads data-fpr-progress (0–100), measures the circle and sets stroke-dasharray and stroke-dashoffset, so the ring fills to the right point; a "Lv 12" chip sits on its edge.
The Activity card draws seven .fpr-bars__day bars from the WEEKS object in script.js. Each fill height is set through the --fpr-h custom property relative to BAR_MAX. Today's bar is highlighted with .is-today, days that have not happened yet get a hatched .is-future track, and the header shows the total time and the change against the same days last week. The "This week / Last week" segmented buttons use aria-pressed and redraw the chart.
Each achievement is a .fpr-badge button whose details live in data-title, data-text, data-status, data-icon and, for locked ones, data-progress. Tapping a badge opens the native <dialog> .fpr-sheet as a bottom sheet with a large icon, description, status and a progress bar. Escape, the Done and close buttons, and a tap on the backdrop close it, and focus returns to the badge.
The avatar photo comes from Unsplash; replace it with the user's own image.
Customization
--fpr-accent,--fpr-accent-darkand--fpr-accent-softinstyle.css: ring, bars, record icons and Record button.data-fpr-progresson.fpr-ring: level progress in percent.WEEKSandBAR_MAXinscript.js: daily active minutes (Monday first) and the minutes that fill a bar.- Badge colours: modifiers such as
.fpr-badge--goldor.fpr-badge--tealset--fpr-b-bg,--fpr-b-fgand--fpr-b-ring. - Add
.is-locked, a lock icon anddata-progressto a badge to show it as not yet earned. - Add or remove
.fpr-recordrows for other personal bests (lifts, swims, rides).
Use cases
- Running and cycling apps: show level, weekly minutes and best times.
- Gym and workout trackers: a gamified member profile with badges.
- Corporate step and wellbeing challenges: progress and rewards for each employee.
- Sports club PWAs: athlete profile pages packaged with Capacitor.
Accessibility
Each bar has hidden text such as "Friday (today): 38 minutes", the ring has a text equivalent ("68 percent of the way to Level 13") and locked badges announce "locked". The bottom sheet is a modal <dialog> labelled by its heading, so focus is trapped while open. The tab bar marks the current page with aria-current, targets are at least 44 px and the sheet animation is disabled under prefers-reduced-motion.