Law Firm — Legal FAQ
An accessible FAQ accordion for a law firm that groups common questions by Fees, Process, Consultations and Confidentiality, supports full keyboard navigation with single-open behavior, and includes a live search box that filters questions and answers as the visitor types.
MCP
Code
:root {
--navy: #1b2a4a;
--navy-d: #101b33;
--gold: #b08d57;
--gold-soft: #efe3cf;
--ink: #1a1f2b;
--muted: #5b6577;
--bg: #f5f3ee;
--white: #ffffff;
--line: #e3ddd1;
--radius: 12px;
--shadow: 0 1px 2px rgba(16, 27, 51, 0.04), 0 8px 24px rgba(16, 27, 51, 0.06);
--serif: "Georgia", "Times New Roman", serif;
--sans: "Inter", system-ui, -apple-system, sans-serif;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
body {
font-family: var(--sans);
color: var(--ink);
background: var(--bg);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.faq {
max-width: 760px;
margin: 0 auto;
padding: 56px 24px 72px;
}
/* ---------- Header ---------- */
.faq__head {
text-align: center;
margin-bottom: 40px;
}
.faq__eyebrow {
margin: 0 0 10px;
font-size: 0.72rem;
letter-spacing: 0.22em;
text-transform: uppercase;
font-weight: 600;
color: var(--gold);
}
.faq__title {
font-family: var(--serif);
font-weight: 400;
font-size: clamp(2rem, 5vw, 2.8rem);
color: var(--navy);
margin: 0 0 8px;
letter-spacing: -0.01em;
}
.faq__title::after {
content: "";
display: block;
width: 56px;
height: 2px;
background: var(--gold);
margin: 18px auto 0;
}
.faq__lede {
max-width: 520px;
margin: 18px auto 0;
color: var(--muted);
font-size: 1.02rem;
}
/* ---------- Search ---------- */
.faq__search {
position: relative;
margin: 28px auto 0;
max-width: 460px;
}
.faq__search-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
width: 18px;
height: 18px;
color: var(--muted);
pointer-events: none;
}
.faq__search-input {
width: 100%;
font-family: var(--sans);
font-size: 0.98rem;
color: var(--ink);
background: var(--white);
border: 1px solid var(--line);
border-radius: 999px;
padding: 13px 44px 13px 44px;
box-shadow: var(--shadow);
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.faq__search-input::placeholder {
color: #9aa1ad;
}
.faq__search-input:focus {
outline: none;
border-color: var(--gold);
box-shadow: 0 0 0 3px var(--gold-soft);
}
.faq__search-clear {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
width: 28px;
height: 28px;
border: none;
background: transparent;
color: var(--muted);
font-size: 1.4rem;
line-height: 1;
cursor: pointer;
border-radius: 50%;
transition: background 0.15s ease, color 0.15s ease;
}
.faq__search-clear:hover {
background: var(--bg);
color: var(--navy);
}
.faq__search-clear:focus-visible {
outline: 2px solid var(--gold);
outline-offset: 2px;
}
.faq__count {
margin: 14px 0 0;
min-height: 1.2em;
font-size: 0.82rem;
color: var(--muted);
}
/* ---------- Groups ---------- */
.faq__group {
margin-bottom: 36px;
}
.faq__group[hidden] {
display: none;
}
.faq__group-title {
font-family: var(--serif);
font-weight: 400;
font-size: 1.15rem;
color: var(--navy);
margin: 0 0 14px;
padding-bottom: 10px;
border-bottom: 1px solid var(--gold);
display: inline-block;
}
/* ---------- Items ---------- */
.faq__item {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--radius);
margin-bottom: 12px;
overflow: hidden;
box-shadow: var(--shadow);
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.faq__item[hidden] {
display: none;
}
.faq__item:hover {
border-color: #cdbfa6;
}
.faq__item.is-open {
border-color: var(--gold);
}
.faq__q-wrap {
margin: 0;
font-size: inherit;
font-weight: inherit;
}
.faq__q {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
text-align: left;
background: transparent;
border: none;
cursor: pointer;
padding: 18px 20px;
font-family: var(--sans);
font-size: 1rem;
font-weight: 500;
color: var(--navy);
transition: background 0.15s ease;
}
.faq__q:hover {
background: #faf8f3;
}
.faq__q:focus-visible {
outline: 2px solid var(--gold);
outline-offset: -2px;
}
.faq__q-text {
flex: 1;
}
.faq__q-text mark {
background: var(--gold-soft);
color: var(--navy);
border-radius: 3px;
padding: 0 2px;
}
.faq__chevron {
flex: none;
width: 12px;
height: 12px;
border-right: 2px solid var(--gold);
border-bottom: 2px solid var(--gold);
transform: rotate(45deg);
transform-origin: center;
transition: transform 0.22s ease;
margin-top: -4px;
}
.faq__item.is-open .faq__chevron {
transform: rotate(-135deg);
margin-top: 2px;
}
.faq__a {
padding: 0 20px 20px;
color: var(--muted);
font-size: 0.96rem;
animation: faq-slide 0.22s ease;
}
.faq__a p {
margin: 0;
}
.faq__a mark {
background: var(--gold-soft);
color: var(--navy);
border-radius: 3px;
padding: 0 2px;
}
@keyframes faq-slide {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ---------- Empty state ---------- */
.faq__empty {
text-align: center;
color: var(--muted);
background: var(--white);
border: 1px dashed var(--line);
border-radius: var(--radius);
padding: 32px 20px;
}
.faq__empty a {
color: var(--gold);
}
/* ---------- Footer ---------- */
.faq__foot {
text-align: center;
margin-top: 28px;
padding-top: 28px;
border-top: 1px solid var(--line);
color: var(--muted);
}
.faq__link {
color: var(--navy);
font-weight: 600;
text-decoration: none;
border-bottom: 1px solid var(--gold);
transition: color 0.15s ease;
}
.faq__link:hover {
color: var(--gold);
}
.faq__link:focus-visible {
outline: 2px solid var(--gold);
outline-offset: 3px;
}
/* ---------- Responsive ---------- */
@media (max-width: 520px) {
.faq {
padding: 40px 16px 56px;
}
.faq__q {
padding: 16px;
font-size: 0.95rem;
}
.faq__a {
padding: 0 16px 16px;
}
.faq__lede {
font-size: 0.96rem;
}
}
@media (prefers-reduced-motion: reduce) {
.faq__chevron,
.faq__a,
.faq__item,
.faq__search-input {
transition: none;
animation: none;
}
}(function () {
"use strict";
var list = document.getElementById("faq-list");
if (!list) return;
var searchInput = document.getElementById("faq-search");
var clearBtn = document.querySelector(".faq__search-clear");
var countEl = document.getElementById("faq-count");
var emptyEl = document.getElementById("faq-empty");
var groups = Array.prototype.slice.call(list.querySelectorAll("[data-group]"));
var items = Array.prototype.slice.call(list.querySelectorAll("[data-item]"));
var buttons = items.map(function (item) {
return item.querySelector(".faq__q");
});
// Cache original text for highlight reset.
items.forEach(function (item) {
var q = item.querySelector(".faq__q-text");
var a = item.querySelector(".faq__a p");
item._qText = q ? q.textContent : "";
item._aText = a ? a.textContent : "";
item._qEl = q;
item._aEl = a;
});
/* ---------- Accordion (single-open) ---------- */
function setOpen(item, open) {
var btn = item.querySelector(".faq__q");
var panel = item.querySelector(".faq__a");
item.classList.toggle("is-open", open);
btn.setAttribute("aria-expanded", open ? "true" : "false");
if (open) {
panel.hidden = false;
} else {
panel.hidden = true;
}
}
function toggle(item) {
var isOpen = item.classList.contains("is-open");
items.forEach(function (other) {
if (other !== item) setOpen(other, false);
});
setOpen(item, !isOpen);
}
buttons.forEach(function (btn) {
btn.addEventListener("click", function () {
toggle(btn.closest("[data-item]"));
});
});
/* ---------- Keyboard navigation ---------- */
function visibleButtons() {
return buttons.filter(function (b) {
return !b.closest("[data-item]").hidden;
});
}
list.addEventListener("keydown", function (e) {
var current = document.activeElement;
if (!current || !current.classList || !current.classList.contains("faq__q")) return;
var vis = visibleButtons();
var idx = vis.indexOf(current);
if (idx === -1) return;
var next = null;
switch (e.key) {
case "ArrowDown":
next = vis[idx + 1] || vis[0];
break;
case "ArrowUp":
next = vis[idx - 1] || vis[vis.length - 1];
break;
case "Home":
next = vis[0];
break;
case "End":
next = vis[vis.length - 1];
break;
default:
return;
}
if (next) {
e.preventDefault();
next.focus();
}
});
/* ---------- Live search ---------- */
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function highlight(el, text, query) {
if (!el) return;
if (!query) {
el.textContent = text;
return;
}
var re = new RegExp("(" + escapeRegExp(query) + ")", "ig");
el.innerHTML = text.replace(re, "<mark>$1</mark>");
}
function filter(rawQuery) {
var query = rawQuery.trim().toLowerCase();
var matches = 0;
items.forEach(function (item) {
var hay = (item._qText + " " + item._aText).toLowerCase();
var hit = query === "" || hay.indexOf(query) !== -1;
item.hidden = !hit;
if (hit) {
matches++;
highlight(item._qEl, item._qText, query);
highlight(item._aEl, item._aText, query);
} else {
// collapse hidden items to keep state tidy
setOpen(item, false);
}
});
// Hide groups with no visible items.
groups.forEach(function (group) {
var anyVisible = group.querySelector("[data-item]:not([hidden])");
group.hidden = !anyVisible;
});
// Empty state + count.
if (emptyEl) emptyEl.hidden = matches !== 0;
if (countEl) {
if (query === "") {
countEl.textContent = "";
} else if (matches === 0) {
countEl.textContent = "No matching questions.";
} else {
countEl.textContent =
matches + (matches === 1 ? " question matches" : " questions match") + ' "' + rawQuery.trim() + '"';
}
}
if (clearBtn) clearBtn.hidden = query === "";
}
if (searchInput) {
searchInput.addEventListener("input", function () {
filter(searchInput.value);
});
}
if (clearBtn) {
clearBtn.addEventListener("click", function () {
searchInput.value = "";
filter("");
searchInput.focus();
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Legal FAQ — Whitmore & Hale LLP</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="faq">
<header class="faq__head">
<p class="faq__eyebrow">Whitmore & Hale LLP</p>
<h1 class="faq__title">Frequently Asked Questions</h1>
<p class="faq__lede">
Answers to the questions clients ask us most — about fees, our process,
consultations and how we protect your confidence.
</p>
<div class="faq__search">
<label class="sr-only" for="faq-search">Search questions</label>
<svg class="faq__search-icon" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M21 21l-4.35-4.35M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
/>
</svg>
<input
id="faq-search"
class="faq__search-input"
type="search"
placeholder="Search the FAQ…"
autocomplete="off"
/>
<button class="faq__search-clear" type="button" hidden aria-label="Clear search">
×
</button>
</div>
<p class="faq__count" id="faq-count" role="status" aria-live="polite"></p>
</header>
<div class="faq__list" id="faq-list">
<!-- Fees & Billing -->
<section class="faq__group" data-group>
<h2 class="faq__group-title">Fees & Billing</h2>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-fees-1"
aria-expanded="false"
aria-controls="a-fees-1"
>
<span class="faq__q-text">How do you charge for your services?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-fees-1" role="region" aria-labelledby="q-fees-1" hidden>
<p>
Most matters are billed at an hourly rate ranging from $280 to $520 depending on the
attorney and complexity. For certain matters — wills, fixed-scope contracts, and some
immigration filings — we offer a flat fee quoted in advance so you know the cost up front.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-fees-2"
aria-expanded="false"
aria-controls="a-fees-2"
>
<span class="faq__q-text">Do you require a retainer?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-fees-2" role="region" aria-labelledby="q-fees-2" hidden>
<p>
For ongoing representation we ask for a retainer — typically between $2,500 and $7,500 —
held in a client trust account. We bill against it monthly and send an itemized statement;
any unused balance is refunded when your matter concludes.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-fees-3"
aria-expanded="false"
aria-controls="a-fees-3"
>
<span class="faq__q-text">Are there any hidden costs?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-fees-3" role="region" aria-labelledby="q-fees-3" hidden>
<p>
No. Beyond legal fees you may incur third-party costs such as court filing fees, expert
witnesses or courier charges. We disclose every anticipated expense in your engagement
letter and obtain your approval before incurring anything substantial.
</p>
</div>
</div>
</section>
<!-- Our Process -->
<section class="faq__group" data-group>
<h2 class="faq__group-title">Our Process</h2>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-proc-1"
aria-expanded="false"
aria-controls="a-proc-1"
>
<span class="faq__q-text">What happens after I retain the firm?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-proc-1" role="region" aria-labelledby="q-proc-1" hidden>
<p>
Your lead attorney opens the matter, gathers documents, and sends a written case plan
within five business days. You will have a single point of contact and a secure portal
to share files and track progress at every stage.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-proc-2"
aria-expanded="false"
aria-controls="a-proc-2"
>
<span class="faq__q-text">How long will my case take?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-proc-2" role="region" aria-labelledby="q-proc-2" hidden>
<p>
Timelines vary widely. A contract review may take a week; a contested litigation matter
can span a year or more. After our initial review we give you a realistic estimate and
update it whenever circumstances — or the opposing party — change.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-proc-3"
aria-expanded="false"
aria-controls="a-proc-3"
>
<span class="faq__q-text">How often will I hear from my attorney?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-proc-3" role="region" aria-labelledby="q-proc-3" hidden>
<p>
We commit to acknowledging your messages within one business day and to a substantive
update at least every two weeks while your matter is active — sooner whenever something
meaningful happens.
</p>
</div>
</div>
</section>
<!-- Consultations -->
<section class="faq__group" data-group>
<h2 class="faq__group-title">Consultations</h2>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-cons-1"
aria-expanded="false"
aria-controls="a-cons-1"
>
<span class="faq__q-text">Is the first consultation free?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-cons-1" role="region" aria-labelledby="q-cons-1" hidden>
<p>
We offer a complimentary 20-minute introductory call to understand your situation and
confirm we are the right fit. A full consultation — typically 60 minutes — is billed at
$150, which we credit toward your matter if you choose to retain us.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-cons-2"
aria-expanded="false"
aria-controls="a-cons-2"
>
<span class="faq__q-text">Can we meet remotely?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-cons-2" role="region" aria-labelledby="q-cons-2" hidden>
<p>
Yes. We meet by secure video or telephone for clients across the state, and in person at
our downtown office on Marquette Avenue. Evening appointments are available on Tuesdays
and Thursdays by request.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-cons-3"
aria-expanded="false"
aria-controls="a-cons-3"
>
<span class="faq__q-text">What should I bring to my consultation?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-cons-3" role="region" aria-labelledby="q-cons-3" hidden>
<p>
Bring any contracts, correspondence, court papers or notices related to your matter, plus
a short timeline of events. The more context you can share, the more specific our initial
guidance can be.
</p>
</div>
</div>
</section>
<!-- Confidentiality -->
<section class="faq__group" data-group>
<h2 class="faq__group-title">Confidentiality</h2>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-conf-1"
aria-expanded="false"
aria-controls="a-conf-1"
>
<span class="faq__q-text">Is what I tell you kept private?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-conf-1" role="region" aria-labelledby="q-conf-1" hidden>
<p>
Yes. Communications with our attorneys are protected by attorney-client privilege, even
during the free introductory call. We do not disclose your information to third parties
without your written consent except where the law requires it.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-conf-2"
aria-expanded="false"
aria-controls="a-conf-2"
>
<span class="faq__q-text">How is my data stored and protected?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-conf-2" role="region" aria-labelledby="q-conf-2" hidden>
<p>
Files are stored in an encrypted, access-controlled document system. Only the attorneys
and staff assigned to your matter can view them, every access is logged, and we retain
records in accordance with our written retention policy.
</p>
</div>
</div>
<div class="faq__item" data-item>
<h3 class="faq__q-wrap">
<button
class="faq__q"
id="q-conf-3"
aria-expanded="false"
aria-controls="a-conf-3"
>
<span class="faq__q-text">Does privilege survive if I don't hire you?</span>
<span class="faq__chevron" aria-hidden="true"></span>
</button>
</h3>
<div class="faq__a" id="a-conf-3" role="region" aria-labelledby="q-conf-3" hidden>
<p>
It does. Anything you share while seeking legal advice remains privileged whether or not
you ultimately retain the firm, so you can speak candidly during your consultation.
</p>
</div>
</div>
</section>
<p class="faq__empty" id="faq-empty" hidden>
No questions match your search. Try a different term or
<a href="#faq-search">clear the search</a>.
</p>
</div>
<footer class="faq__foot">
<p>
Still have a question?
<a class="faq__link" href="#">Book a free 20-minute call →</a>
</p>
</footer>
</main>
<script src="script.js"></script>
</body>
</html>Legal FAQ
A trust-first FAQ section styled for an authoritative law firm — navy and gold, a serif voice for headings and Inter for the answers. Questions are organized into four categories: Fees & Billing, Our Process, Consultations, and Confidentiality, each rendered as an accessible disclosure accordion.
Every question is a real <button> with aria-expanded and aria-controls, so the whole list is
keyboard- and screen-reader-friendly. Opening one item closes the others (single-open behavior),
arrow keys move between questions, and Home / End jump to the first and last. A search box at the top
filters questions and answers live, highlighting matches, hiding empty categories, and showing a
graceful empty state when nothing matches.
All behavior is vanilla JavaScript — no libraries, no build step. Drop the three files in and adapt the questions to your own practice.
Illustrative UI only — not legal advice and not a substitute for a licensed attorney.