While building the FAQ page for LoanPlannerPro’s mortgage calculator, I faced a common decision: how to structure the questions and answers semantically. After considering various approaches, I chose the often-overlooked <dl>
(definition list) element, and here’s why this choice makes perfect sense for FAQ pages.
The Semantic Choice
The <dl>
element, along with its companions <dt>
(definition term) and <dd>
(definition description), creates a natural semantic structure for question-answer pairs:
1<dl className="faq-list">
2 <dt>
3 What is a mortgage?
4 </dt>
5 <dd>
6 A mortgage is a loan used to purchase real estate...
7 </dd>
8</dl>
This structure perfectly represents the relationship between questions and answers, making it ideal for FAQ pages.
Technical Benefits
1. Semantic HTML Excellence
The definition list structure provides clear semantic meaning:
<dt>
naturally represents the question<dd>
holds the corresponding answer- The pairing is explicit in the markup
2. Accessibility Advantages
Screen readers understand and announce definition lists properly, providing better navigation for users with disabilities. The semantic relationship between questions and answers is preserved programmatically.
3. SEO Optimization
Search engines better understand the question-answer relationship, potentially improving:
- Featured snippet eligibility
- Voice search results
- Rich results in search pages
Implementation in React
Here’s how I implemented an interactive FAQ component using <dl>
:
1const FAQItem = ({ question, children }) => {
2 const id = useId();
3 const { openItemId, toggleItem } = useFAQ();
4 const isOpen = openItemId === id;
5
6 const handleToggle = () => {
7 toggleItem(id);
8 };
9
10 return (
11 <>
12 <dt
13 className="text-xl font-medium cursor-pointer flex justify-between items-center py-2"
14 onClick={handleToggle}
15 >
16 <span>{question}</span>
17 {isOpen ? (
18 <ChevronUp className="h-5 w-5 text-blue-500" />
19 ) : (
20 <ChevronDown className="h-5 w-5 text-blue-500" />
21 )}
22 </dt>
23 {isOpen && (
24 <dd className="my-4">
25 {children}
26 </dd>
27 )}
28 </>
29 );
30};
Managing Toggle State: Context vs Local State
For the toggle functionality, I used React Context to manage which FAQ item is open:
1const FAQContext = createContext();
2
3export const FAQProvider = ({ children }) => {
4 const [openItemId, setOpenItemId] = useState(null);
5
6 const toggleItem = (id) => {
7 setOpenItemId(openItemId === id ? null : id);
8 };
9
10 return (
11 <FAQContext.Provider value={{ openItemId, toggleItem }}>
12 {children}
13 </FAQContext.Provider>
14 );
15};
Why Context?
This approach ensures only one FAQ item is open at a time, creating an accordion-style behavior. When a user clicks a new question, the previously open one automatically closes.
Alternative: Simpler Local State
If you don’t need the accordion behavior, you could simplify by using local state in each FAQ item:
1const SimpleFAQItem = ({ question, children }) => {
2 const [isOpen, setIsOpen] = useState(false);
3
4 return (
5 <>
6 <dt
7 className="text-xl font-medium cursor-pointer"
8 onClick={() => setIsOpen(!isOpen)}
9 >
10 <span>{question}</span>
11 {isOpen ? <ChevronUp /> : <ChevronDown />}
12 </dt>
13 {isOpen && <dd className="my-4">{children}</dd>}
14 </>
15 );
16};
This simpler approach allows multiple FAQs to be open simultaneously, which might actually be better for user experience depending on your use case.
Styling Considerations
Definition lists are easily styled with modern CSS, whether using utility classes (like Tailwind) or custom styles:
1.faq-list dt {
2 @apply text-xl font-medium cursor-pointer;
3}
4
5.faq-list dd {
6 @apply mb-4 text-gray-700;
7}
Practical Example
Here’s a complete example from the LoanPlannerPro FAQ page:
1<FAQProvider>
2 <h2 className="text-2xl border-b-1 mb-4 pb-4 text-blue-500">
3 General Mortgage Questions
4 </h2>
5
6 <dl className="faq-list">
7 <FAQItem question="What is a mortgage?">
8 <p>A mortgage is a loan used to purchase real estate
9 where the property itself serves as collateral...</p>
10 </FAQItem>
11
12 <FAQItem question="How does a mortgage work?">
13 <p>With a mortgage, you borrow money from a lender
14 to buy a home...</p>
15 </FAQItem>
16 </dl>
17</FAQProvider>
Alternative Approaches
While other structures are possible:
- Divs with headings: Less semantic
- Unordered lists: Don’t convey the question-answer relationship
- Sections with headers: More verbose and less specific
The <dl>
element provides the most appropriate semantic meaning for FAQ content.
Conclusion
Using definition lists for FAQ pages offers multiple benefits:
- Semantic accuracy: The HTML structure matches the content meaning
- Accessibility: Better screen reader support
- SEO advantages: Clearer content relationships for search engines
- Maintainability: Clean, logical code structure
By choosing <dl>
elements for your FAQ pages, you’re creating a more accessible, SEO-friendly, and semantically correct web experience. The implementation at LoanPlannerPro’s FAQ page demonstrates these benefits in practice.
Next time you’re building an FAQ page, consider the humble <dl>
element – it might be exactly what you need.