Using Definition Lists for FAQ Pages: A Semantic HTML Approach

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.

Share this post