Clinic — Services / Specialties
A calm services and specialties page for a fictional clinic, leading with a warm hero and category filter chips that live-filter a responsive grid of specialty cards. Each card pairs a soft gradient icon, a category tag, a short blurb and Learn more plus Book actions, lifting gently on hover. Chip counts update from the markup, a live result line and empty state keep things clear, and a footer CTA band invites booking. Vanilla JS only.
MCP
الكود
:root {
--teal: #129c93;
--teal-d: #0c7a73;
--teal-700: #0a655f;
--teal-50: #e7f5f3;
--coral: #ff7a66;
--coral-soft: #ffe6df;
--ink: #16322f;
--ink-2: #3a534f;
--muted: #6b827e;
--bg: #f1f7f6;
--white: #ffffff;
--line: rgba(16, 50, 47, 0.1);
--line-2: rgba(16, 50, 47, 0.18);
--ok: #2f9e6f;
--warn: #d98a2b;
--danger: #d4503e;
--font: "Inter", system-ui, -apple-system, sans-serif;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
--shadow-1: 0 1px 2px rgba(16, 50, 47, 0.05), 0 4px 14px rgba(16, 50, 47, 0.06);
--shadow-2: 0 16px 40px rgba(12, 122, 115, 0.16);
--shadow-lift: 0 18px 38px rgba(12, 122, 115, 0.18);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font);
background: var(--bg);
color: var(--ink);
-webkit-font-smoothing: antialiased;
line-height: 1.5;
}
button {
font: inherit;
}
:focus-visible {
outline: 3px solid rgba(18, 156, 147, 0.45);
outline-offset: 2px;
border-radius: 6px;
}
/* ── Layout ── */
.page {
max-width: 1080px;
margin: 0 auto;
padding: 40px 20px 48px;
display: flex;
flex-direction: column;
gap: 28px;
}
/* ── Hero ── */
.hero {
display: flex;
flex-direction: column;
gap: 14px;
}
.eyebrow {
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--teal-d);
}
.hero h1 {
font-size: clamp(1.9rem, 4vw, 2.6rem);
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.1;
max-width: 18ch;
}
.lede {
font-size: 1.02rem;
color: var(--ink-2);
max-width: 62ch;
}
/* ── Filter chips ── */
.filters {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 6px;
}
.chip {
border: 1px solid var(--line-2);
background: var(--white);
border-radius: 999px;
padding: 9px 16px;
font-weight: 600;
font-size: 0.88rem;
color: var(--ink-2);
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
box-shadow: var(--shadow-1);
transition: background 0.16s, color 0.16s, border-color 0.16s, transform 0.12s;
}
.chip:hover {
border-color: var(--teal);
color: var(--teal-d);
}
.chip:active {
transform: translateY(1px);
}
.chip.is-active {
background: var(--teal-d);
border-color: var(--teal-d);
color: #fff;
}
.chip-count {
display: inline-grid;
place-items: center;
min-width: 20px;
height: 20px;
padding: 0 6px;
border-radius: 999px;
background: var(--teal-50);
color: var(--teal-d);
font-size: 0.72rem;
font-weight: 700;
}
.chip.is-active .chip-count {
background: rgba(255, 255, 255, 0.22);
color: #fff;
}
.result-line {
font-size: 0.85rem;
color: var(--muted);
font-weight: 500;
min-height: 1.2em;
}
/* ── Grid ── */
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 18px;
}
/* ── Service card ── */
.svc {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 22px;
display: flex;
flex-direction: column;
gap: 10px;
box-shadow: var(--shadow-1);
position: relative;
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.svc:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lift);
border-color: rgba(18, 156, 147, 0.35);
}
.svc.is-hidden {
display: none;
}
.svc-tag {
align-self: flex-start;
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
padding: 4px 10px;
border-radius: 999px;
}
.svc-tag.primary {
background: var(--teal-50);
color: var(--teal-d);
}
.svc-tag.specialist {
background: var(--coral-soft);
color: #c4503a;
}
.svc-tag.diagnostic {
background: rgba(47, 158, 111, 0.14);
color: var(--ok);
}
.svc-icon {
width: 52px;
height: 52px;
display: grid;
place-items: center;
border-radius: var(--r-md);
background: linear-gradient(150deg, var(--teal-50), #d9efec);
font-size: 1.5rem;
margin-top: 4px;
}
.svc h2 {
font-size: 1.12rem;
font-weight: 700;
letter-spacing: -0.01em;
margin-top: 2px;
}
.svc-blurb {
font-size: 0.9rem;
color: var(--muted);
flex: 1;
}
.svc-foot {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-top: 8px;
padding-top: 14px;
border-top: 1px solid var(--line);
}
.link-more {
border: none;
background: transparent;
color: var(--teal-d);
font-weight: 600;
font-size: 0.86rem;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 0;
transition: gap 0.16s, color 0.16s;
}
.link-more:hover {
color: var(--teal-700);
gap: 10px;
}
/* ── Buttons ── */
.btn {
border: none;
border-radius: 10px;
padding: 9px 18px;
font-weight: 600;
font-size: 0.86rem;
cursor: pointer;
transition: transform 0.12s, background 0.16s, box-shadow 0.16s;
}
.btn:active {
transform: translateY(1px);
}
.btn.book {
background: var(--teal);
color: #fff;
box-shadow: 0 6px 14px rgba(18, 156, 147, 0.25);
}
.btn.book:hover {
background: var(--teal-d);
}
/* ── Empty state ── */
.empty {
text-align: center;
color: var(--muted);
font-weight: 500;
padding: 40px 0;
font-size: 0.95rem;
}
.empty[hidden] {
display: none;
}
/* ── CTA band ── */
.cta {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 22px;
background: linear-gradient(135deg, var(--teal-d), var(--teal-700));
color: #fff;
border-radius: var(--r-lg);
padding: 32px 34px;
box-shadow: var(--shadow-2);
}
.cta-text h2 {
font-size: 1.5rem;
font-weight: 800;
letter-spacing: -0.02em;
}
.cta-text p {
margin-top: 6px;
color: rgba(255, 255, 255, 0.86);
font-size: 0.95rem;
max-width: 46ch;
}
.cta-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.btn.cta-primary {
background: var(--white);
color: var(--teal-d);
padding: 12px 22px;
}
.btn.cta-primary:hover {
background: #f0fbf9;
}
.btn.cta-secondary {
background: rgba(255, 255, 255, 0.12);
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.4);
padding: 12px 22px;
}
.btn.cta-secondary:hover {
background: rgba(255, 255, 255, 0.2);
}
/* ── Footer ── */
.page-foot {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 8px;
color: var(--muted);
font-size: 0.84rem;
padding-top: 8px;
}
/* ── Toast ── */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translateX(-50%);
background: var(--ink);
color: #fff;
padding: 13px 20px;
border-radius: 12px;
font-size: 0.9rem;
font-weight: 500;
box-shadow: var(--shadow-2);
z-index: 50;
max-width: 90vw;
}
/* ── Responsive ── */
@media (max-width: 520px) {
.page {
padding: 28px 16px 40px;
gap: 22px;
}
.grid {
grid-template-columns: 1fr;
}
.cta {
padding: 26px 22px;
flex-direction: column;
align-items: flex-start;
}
.cta-actions {
width: 100%;
}
.cta-actions .btn {
flex: 1;
}
.filters {
overflow-x: auto;
flex-wrap: nowrap;
padding-bottom: 4px;
-webkit-overflow-scrolling: touch;
}
.chip {
flex: 0 0 auto;
}
}(function () {
"use strict";
var grid = document.getElementById("grid");
var cards = Array.prototype.slice.call(grid.querySelectorAll(".svc"));
var chips = Array.prototype.slice.call(document.querySelectorAll(".chip"));
var resultLine = document.getElementById("result-line");
var empty = document.getElementById("empty");
var LABELS = {
all: "services",
primary: "primary care services",
specialist: "specialist services",
diagnostic: "diagnostic services",
};
var current = "all";
/* ── Toast helper ── */
var toastEl = document.getElementById("toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.hidden = false;
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.hidden = true;
}, 2600);
}
/* ── Live category counts ── */
function computeCounts() {
var counts = { all: cards.length, primary: 0, specialist: 0, diagnostic: 0 };
cards.forEach(function (card) {
var cat = card.getAttribute("data-cat");
if (counts[cat] != null) counts[cat] += 1;
});
Object.keys(counts).forEach(function (key) {
var el = document.getElementById("count-" + key);
if (el) el.textContent = String(counts[key]);
});
}
/* ── Filtering ── */
function applyFilter(filter) {
current = filter;
var visible = 0;
cards.forEach(function (card) {
var match = filter === "all" || card.getAttribute("data-cat") === filter;
card.classList.toggle("is-hidden", !match);
if (match) visible += 1;
});
chips.forEach(function (chip) {
var active = chip.getAttribute("data-filter") === filter;
chip.classList.toggle("is-active", active);
chip.setAttribute("aria-selected", active ? "true" : "false");
});
empty.hidden = visible !== 0;
var label = LABELS[filter] || "services";
resultLine.textContent =
visible === 0
? "No " + label + " to show."
: "Showing " + visible + " " + (visible === 1 ? "service" : label) + ".";
}
/* ── Chip clicks + keyboard roving focus ── */
chips.forEach(function (chip, i) {
chip.addEventListener("click", function () {
applyFilter(chip.getAttribute("data-filter"));
});
chip.addEventListener("keydown", function (e) {
var next = null;
if (e.key === "ArrowRight" || e.key === "ArrowDown") next = chips[i + 1] || chips[0];
else if (e.key === "ArrowLeft" || e.key === "ArrowUp") next = chips[i - 1] || chips[chips.length - 1];
else if (e.key === "Home") next = chips[0];
else if (e.key === "End") next = chips[chips.length - 1];
if (next) {
e.preventDefault();
next.focus();
applyFilter(next.getAttribute("data-filter"));
}
});
});
/* ── Card actions: Learn more / Book / Call ── */
document.addEventListener("click", function (e) {
var btn = e.target.closest("[data-action]");
if (!btn) return;
var action = btn.getAttribute("data-action");
var name = btn.getAttribute("data-name") || "this service";
if (action === "learn") {
toast("Opening details for " + name + " — illustrative only.");
} else if (action === "book") {
toast("Booking request started for " + name + ".");
} else if (action === "call") {
toast("Call Northpoint Clinic at (555) 014-8821.");
}
});
/* ── Init ── */
computeCounts();
applyFilter("all");
})();<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
/>
<link rel="stylesheet" href="style.css" />
<title>Services & Specialties · Northpoint Clinic</title>
</head>
<body>
<main class="page">
<header class="hero">
<p class="eyebrow">Northpoint Clinic</p>
<h1>Care for every stage of life</h1>
<p class="lede">
From everyday check-ups to specialist consultations and on-site
diagnostics, our team brings compassionate, coordinated care under one
roof. Explore our services below and book the care you need.
</p>
<div class="filters" role="tablist" aria-label="Filter services by category">
<button class="chip is-active" role="tab" aria-selected="true" data-filter="all">
All <span class="chip-count" id="count-all">0</span>
</button>
<button class="chip" role="tab" aria-selected="false" data-filter="primary">
Primary care <span class="chip-count" id="count-primary">0</span>
</button>
<button class="chip" role="tab" aria-selected="false" data-filter="specialist">
Specialists <span class="chip-count" id="count-specialist">0</span>
</button>
<button class="chip" role="tab" aria-selected="false" data-filter="diagnostic">
Diagnostics <span class="chip-count" id="count-diagnostic">0</span>
</button>
</div>
<p class="result-line" id="result-line" aria-live="polite"></p>
</header>
<section class="grid" id="grid" aria-label="Services and specialties">
<article class="svc" data-cat="primary">
<span class="svc-tag primary">Primary care</span>
<div class="svc-icon" aria-hidden="true">🩺</div>
<h2>Family Medicine</h2>
<p class="svc-blurb">
Annual physicals, preventive screenings and same-day visits for the
whole family, led by Dr. Lena Okafor.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Family Medicine">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Family Medicine">Book</button>
</div>
</article>
<article class="svc" data-cat="primary">
<span class="svc-tag primary">Primary care</span>
<div class="svc-icon" aria-hidden="true">🧒</div>
<h2>Pediatrics</h2>
<p class="svc-blurb">
Well-child visits, immunisations and gentle care for newborns through
adolescents in a calm, kid-friendly suite.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Pediatrics">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Pediatrics">Book</button>
</div>
</article>
<article class="svc" data-cat="primary">
<span class="svc-tag primary">Primary care</span>
<div class="svc-icon" aria-hidden="true">💚</div>
<h2>Women's Health</h2>
<p class="svc-blurb">
Routine wellness exams, contraceptive counselling and prenatal support
in a private, unhurried setting.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Women's Health">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Women's Health">Book</button>
</div>
</article>
<article class="svc" data-cat="specialist">
<span class="svc-tag specialist">Specialist</span>
<div class="svc-icon" aria-hidden="true">❤️</div>
<h2>Cardiology</h2>
<p class="svc-blurb">
Heart-health assessments, ECG review and ongoing management of blood
pressure and rhythm with Dr. Ravi Patel.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Cardiology">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Cardiology">Book</button>
</div>
</article>
<article class="svc" data-cat="specialist">
<span class="svc-tag specialist">Specialist</span>
<div class="svc-icon" aria-hidden="true">🌿</div>
<h2>Dermatology</h2>
<p class="svc-blurb">
Skin checks, mole mapping and treatment for acne, eczema and other
common conditions with Dr. Maya Bloom.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Dermatology">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Dermatology">Book</button>
</div>
</article>
<article class="svc" data-cat="specialist">
<span class="svc-tag specialist">Specialist</span>
<div class="svc-icon" aria-hidden="true">🦴</div>
<h2>Orthopaedics</h2>
<p class="svc-blurb">
Care for joint pain, sports injuries and mobility concerns, with
physiotherapy referrals where helpful.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Orthopaedics">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Orthopaedics">Book</button>
</div>
</article>
<article class="svc" data-cat="specialist">
<span class="svc-tag specialist">Specialist</span>
<div class="svc-icon" aria-hidden="true">🧠</div>
<h2>Neurology</h2>
<p class="svc-blurb">
Evaluation of headaches, dizziness and nerve concerns, with a focus on
clear explanations and shared decisions.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Neurology">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Neurology">Book</button>
</div>
</article>
<article class="svc" data-cat="specialist">
<span class="svc-tag specialist">Specialist</span>
<div class="svc-icon" aria-hidden="true">🫁</div>
<h2>Pulmonology</h2>
<p class="svc-blurb">
Support for asthma, persistent cough and breathing difficulties,
including spirometry and inhaler reviews.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Pulmonology">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Pulmonology">Book</button>
</div>
</article>
<article class="svc" data-cat="diagnostic">
<span class="svc-tag diagnostic">Diagnostics</span>
<div class="svc-icon" aria-hidden="true">🧪</div>
<h2>Laboratory</h2>
<p class="svc-blurb">
On-site blood draws and routine panels with most results delivered to
your portal within 24 hours.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Laboratory">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Laboratory">Book</button>
</div>
</article>
<article class="svc" data-cat="diagnostic">
<span class="svc-tag diagnostic">Diagnostics</span>
<div class="svc-icon" aria-hidden="true">🩻</div>
<h2>Imaging & X-Ray</h2>
<p class="svc-blurb">
Digital X-ray and ultrasound performed in-clinic by our radiography
team, with reports shared the same week.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Imaging & X-Ray">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Imaging & X-Ray">Book</button>
</div>
</article>
<article class="svc" data-cat="diagnostic">
<span class="svc-tag diagnostic">Diagnostics</span>
<div class="svc-icon" aria-hidden="true">👁️</div>
<h2>Vision Screening</h2>
<p class="svc-blurb">
Quick visual-acuity and eye-pressure checks, with referral to a
partner ophthalmologist when needed.
</p>
<div class="svc-foot">
<button class="link-more" data-action="learn" data-name="Vision Screening">
Learn more <span aria-hidden="true">→</span>
</button>
<button class="btn book" data-action="book" data-name="Vision Screening">Book</button>
</div>
</article>
</section>
<p class="empty" id="empty" hidden>No services match this category.</p>
<section class="cta" aria-label="Book an appointment">
<div class="cta-text">
<h2>Ready to see someone?</h2>
<p>
Booking takes under two minutes. Choose a service, pick a time that
suits you, and we'll confirm by email.
</p>
</div>
<div class="cta-actions">
<button class="btn cta-primary" data-action="book" data-name="an appointment">
Book an appointment
</button>
<button class="btn cta-secondary" data-action="call">Call the clinic</button>
</div>
</section>
<footer class="page-foot">
<span>Northpoint Clinic · 48 Harbour Lane, Suite 200</span>
<span>Mon–Fri 8am–6pm · Sat 9am–1pm</span>
</footer>
</main>
<div class="toast" id="toast" hidden role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Services / Specialties
A marketing-style services page for Northpoint Clinic. A warm hero introduces the practice, then a row of category chips — All, Primary care, Specialists and Diagnostics — sits above a responsive grid of twelve specialty cards. Each card leads with a soft gradient icon and a category tag, a clear title, an empathetic blurb naming a fictional clinician, and a tidy footer with a Learn more link and a teal Book button.
The chips live-filter the grid: selecting one shows only matching specialties, updates each chip’s count, refreshes a quiet result line and reveals an empty state when nothing matches. Counts are derived from the markup, so adding or removing a card just works. The chips form a roving tablist you can drive with the arrow keys, Home and End, and cards lift gently on hover for a tactile feel.
Every action — Learn more, Book and the footer call-to-action band — routes through a small
toast() helper for friendly, non-blocking feedback. The whole page is plain HTML, CSS and vanilla
JavaScript, responsive down to roughly 360px, with aria roles, visible focus states and AA-contrast
clinical copy throughout.
Illustrative UI only — not intended for real medical use.