HTML details와 summary로 접근 가능한 FAQ 만들기

··설명 약 6분·작성: 해비·블로그 소개

HTML details와 summary로 JavaScript 없이 FAQ를 어떻게 만드나요?

FAQ는 details 안에 질문용 summary와 답변을 넣으면 됩니다. 브라우저가 열림·닫힘과 기본 키보드 조작을 제공합니다. open 속성을 붙이면 처음부터 답변이 열린 상태로 시작합니다.

적용 조건·범위: 완료 기준: 세 질문을 JavaScript 없이 열고 닫을 수 있고, Tab으로 각 질문에 도달하며 초점 위치가 보입니다. HTML에 open을 적으면 열린 상태로 시작하지만, 사용자는 이후 summary를 조작해 다시 닫거나 열 수 있습니다. 이 결과는 TaskFlow 프로젝트 없이 확인할 수 있습니다.

공식 문서 참고: MDN: details·summary의 기본 열림과 키보드 동작

독립 예제

HTML details와 summary로 접근 가능한 FAQ 만들기 · 독립 실습

FAQ 제목을 클릭하거나 Tab·Enter로 열고 닫아 보세요.

예제 크게 보기 (새 탭)
<!doctype html>
<html lang="ko">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>HTML details와 summary로 접근 가능한 FAQ 만들기</title></head>
<body>
<section class="faq">
  <h2>자주 묻는 질문</h2>


  <details>
    <summary>
      회원가입이 필요한가요?
    </summary>
    <p>
      현재 예제에서는 별도 가입 없이 사용할 수 있다고 가정합니다.
    </p>
  </details>


  <details>
    <summary>
      모바일에서도 사용할 수 있나요?
    </summary>
    <p>
      반응형 레이아웃을 적용해 작은 화면에서도 사용할 수 있습니다.
    </p>
  </details>
</section>

</body>
</html>

혼자 확인하기

독자 질문: JavaScript 없이 키보드로도 열 수 있는 FAQ를 어떻게 만들까요?

  1. 위 독립 예제의 section이 포함된 전체 HTML을 빈 faq.html 파일에 저장해 브라우저로 엽니다. 두 질문의 답변은 처음에 닫혀 있어야 합니다.
  2. 마우스로 첫 질문을 열고 닫습니다. 이어서 Tab으로 첫 summary에 초점을 옮기고 Enter 또는 Space를 눌러 다시 열고 닫습니다. 브라우저의 기본 초점 표시도 확인합니다.
  3. 첫 details 시작 태그를 <details open>으로 바꾼 뒤 새로고침합니다. 첫 답변만 처음부터 열려 있어야 합니다. open을 제거하면 다시 닫힌 상태로 시작합니다.
  4. 같은 형식으로 세 번째 질문과 답변을 직접 추가합니다. 질문은 summary, 답변은 details 안의 p에 넣습니다.

완료 기준: 세 질문을 JavaScript 없이 열고 닫을 수 있고, Tab으로 각 질문에 도달하며 초점 위치가 보입니다. HTML에 open을 적으면 열린 상태로 시작하지만, 사용자는 이후 summary를 조작해 다시 닫거나 열 수 있습니다. 이 결과는 TaskFlow 프로젝트 없이 확인할 수 있습니다.

기본 구조

<details>
  <summary>
    TaskFlow는 무료인가요?
  </summary>
  <p>
    현재 학습용 예제에서는 무료 서비스 화면을 가정합니다.
  </p>
</details>

summary가 disclosure의 label 역할을 합니다.

details와 summary로 FAQ를 구성하면 기본 열기·닫기 동작과 키보드 조작을 활용할 수 있습니다.
개념 설명용 일러스트. details와 summary로 FAQ를 구성하면 기본 열기·닫기 동작과 키보드 조작을 활용할 수 있습니다. 이미지 원본 열기

open attribute

초기 상태를 열린 상태로 만들 수 있습니다.

<details open>
  ...
</details>

JavaScript 없이 HTML attribute만으로 초기 상태를 지정할 수 있습니다.

키보드 동작

summary는 기본적으로 focus 가능한 interactive control처럼 동작합니다.

Tab으로 이동하고 Enter 또는 Space 등 브라우저 기본 동작으로 열고 닫을 수 있습니다.

따라서 summary 내부를 별도 button으로 중복 감싸는 구조는 피합니다.

marker

브라우저 기본 marker를 사용할 수 있습니다.

디자인상 변경이 필요하면 ::marker 또는 summary::before 등을 검토할 수 있지만 open/closed 상태를 시각적으로 완전히 숨기지 않는 것이 좋습니다.

.faq summary {
  cursor: pointer;
  font-weight: 700;
}

focus

기본 focus를 제거하지 않습니다.

.faq summary:focus-visible {
  outline: 2px solid #171717;
  outline-offset: 4px;
}

자주 발생하는 오류

summary 대신 div를 클릭 가능하게 만듭니다

native keyboard 동작과 semantics를 잃을 수 있습니다.

outline을 없앱니다

키보드 사용자가 현재 focus 위치를 알기 어려워집니다.

FAQ 제목 없이 details만 나열합니다

section 주제를 설명하는 h2를 함께 두면 문서 구조가 명확합니다.

학습 완료 체크리스트

  • details와 summary 역할을 설명할 수 있습니다.
  • open attribute를 사용할 수 있습니다.
  • native keyboard 동작을 유지할 수 있습니다.
  • focus indicator를 제거하지 않을 수 있습니다.
  • JavaScript 없이 FAQ를 구성할 수 있습니다.

독립 실습은 여기서 마칠 수 있습니다. 아래 선택 실습은 TaskFlow 프로젝트 파일로 진행합니다.

선택 실습: 할 일 앱에 적용하기

TaskFlow는 간단한 서비스 화면에서 시작해 할 일 앱으로 이어 만드는 예제입니다. 이 선택 실습에서는 HTML과 CSS로 이번 화면을 만듭니다.

TaskFlow에 FAQ section을 추가합니다.

선택: 연재 프로젝트와 전체 자료

연재 프로젝트를 이어 만드는 분을 위한 자료입니다. 이 글의 개념과 예제만 찾으셨다면 필요한 파일과 실행 방법만 펼쳐보세요.

TaskFlow 프로젝트 적용

HTML details와 summary로 접근 가능한 FAQ 만들기 · 단계별 TaskFlow

TaskFlow 누적 5단계입니다. FAQ 제목을 클릭하거나 Tab·Enter로 열고 닫아 보세요.

예제 크게 보기 (새 탭)

실행 가능한 시작본과 이번 단계

이번 단계 시작 ZIP을 새 폴더에 압축 해제합니다. 이 ZIP은 직전 단계의 완료 파일과 같으며 앞 글의 코드를 따로 모을 필요가 없습니다. 이번 단계 완료 ZIP은 다른 폴더에 풀어 비교합니다.

문의 앞에 원문의 세 질문 FAQ를 추가하고 details·summary 스타일을 연결합니다.

  1. index.html: 이 파일의 기존 내용을 아래 완료 파일 전체와 대조하여 교체합니다. 다른 파일은 유지합니다.
  2. style.css: 이 파일의 기존 내용을 아래 완료 파일 전체와 대조하여 교체합니다. 다른 파일은 유지합니다.

짧은 코드 예제는 변경 위치를 설명합니다. 파일 전체를 작성하거나 교체할 때는 완료 파일 전체를 사용하세요. 생략 표시가 있는 부분 코드를 파일 전체로 저장하지 않습니다.

실행: ZIP의 index.html을 브라우저에서 엽니다. 외부 서버나 npm 설치 없이 로컬 HTML·CSS·이미지를 사용합니다. 문의 폼은 서버 전송을 연결하지 않은 문서 예제입니다. 연습 값만 사용하고 입력 형식을 확인합니다.

직접 확인할 결과: 질문 세 개의 내용을 열고 닫을 수 있고 문의 폼과 기존 카드가 남아 있습니다.

전체 파일·코드 보기

완료 파일 전체

index.html 전체 파일

<!DOCTYPE html>
<html lang="ko">
 <head>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
  <title>
   TaskFlow
  </title>
  <link href="./style.css" rel="stylesheet"/>
 </head>
 <body>
  <header class="site-header">
   <div class="page site-header__inner">
    <a class="brand" href="#home">
     TaskFlow
    </a>
    <nav aria-label="주요 메뉴" class="nav">
     <a href="#features">
      기능
     </a>
     <a href="#contact">
      문의
     </a>
    </nav>
   </div>
  </header>
  <main class="page" id="home">
   <section>
    <h1>
     해야 할 일을 한눈에 정리하세요
    </h1>
    <p>
     TaskFlow는 오늘의 작업을 빠르게 정리하는 서비스입니다.
    </p>
   </section>
   <section id="features">
    <h2>
     주요 기능
    </h2>
    <div class="feature-list">
     <article class="card feature-card">
      <span class="feature-card__badge">
       NEW
      </span>
      <h3>
       빠른 작업 추가
      </h3>
      <p>
       해야 할 일을 바로 기록할 수 있습니다.
      </p>
     </article>
     <article class="card">
      <h3>
       간단한 분류
      </h3>
      <p>
       해야 할 일을 구분합니다.
      </p>
     </article>
     <article class="card">
      <h3>
       진행 확인
      </h3>
      <p>
       완료 여부를 확인합니다.
      </p>
     </article>
    </div>
   </section>
   <section class="faq" id="faq">
    <h2>
     자주 묻는 질문
    </h2>
    <details>
     <summary>
      TaskFlow는 어떤 서비스인가요?
     </summary>
     <p>
      해야 할 일을 빠르게 정리하는 작업 관리 서비스 예제입니다.
     </p>
    </details>
    <details>
     <summary>
      모바일에서도 볼 수 있나요?
     </summary>
     <p>
      작은 화면부터 설계한 반응형 레이아웃을 사용합니다.
     </p>
    </details>
    <details>
     <summary>
      문의는 어디서 하나요?
     </summary>
     <p>
      아래 문의 폼을 이용할 수 있습니다.
     </p>
    </details>
   </section>
   <section id="contact">
    <h2>
     문의하기
    </h2>
    <form>
     <div class="form-field">
      <label for="name">
       이름
      </label>
      <input autocomplete="name" id="name" name="name" type="text"/>
     </div>
     <div class="form-field">
      <label for="email">
       이메일
      </label>
      <input autocomplete="email" id="email" name="email" type="email"/>
     </div>
     <div class="form-field">
      <label for="message">
       문의 내용
      </label>
      <textarea id="message" name="message" rows="5"></textarea>
     </div>
     <button type="submit">
      문의 보내기
     </button>
    </form>
   </section>
  </main>
  <footer class="site-footer">
   <div class="page">
    <p>
     © TaskFlow
    </p>
   </div>
  </footer>
  <a class="help-button" href="#contact">
   문의
  </a>
 </body>
</html>

style.css 전체 파일

:root {
  color: #171717;
  background: #f5f5f5;
}


*,
*::before,
*::after {
  box-sizing: border-box;
}


body {
  margin: 0;
  font-family:
    Arial,
    sans-serif;
  line-height: 1.6;
  color: #171717;
  background: #f5f5f5;
}


.page {
  width: min(
    100% - 32px,
    960px
  );
  margin-inline: auto;
}


.site-header,
.site-footer {
  padding-block: 20px;
}


main {
  padding-block: 48px;
}


section + section {
  margin-top: 64px;
}


.card {
  padding: 24px;
  border: 1px solid #d7d7d7;
  background: #fff;
}


form {
  display: grid;
  gap: 16px;
}


.form-field {
  display: grid;
  gap: 8px;
}


input,
textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid #b8b8b8;
  background: #fff;
}


button {
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid #171717;
  background: #171717;
  color: #fff;
}

a { color: inherit; }
input, textarea, button { font: inherit; }
h1 { font-size: 32px; font-weight: 700; }
h2 { font-size: 24px; }
h3 { font-size: 20px; }

.site-header__inner {
  display: flex;
  flex-direction: column;
  gap: 12px;
}


.nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
}


.feature-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}


@media (min-width: 48rem) {
  .site-header__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }


  .feature-list {
    flex-direction: row;
  }


  .feature-list > * {
    flex: 1;
  }
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: #f5f5f5;
  border: 1px solid #ddd;
}


.feature-card {
  position: relative;
}


.feature-card__badge {
  position: absolute;
  top: 12px;
  right: 12px;
  padding: 4px 8px;
  border: 1px solid #171717;
  background: #fff;
  font-size: 12px;
}


.help-button {
  position: fixed;
  right: 16px;
  bottom: 16px;
  min-width: 44px;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid #171717;
  background: #171717;
  color: #fff;
  text-decoration: none;
}

.faq {
  display: grid;
  gap: 12px;
}


.faq details {
  border: 1px solid #d7d7d7;
  background: #fff;
}


.faq summary {
  padding: 16px;
  cursor: pointer;
  font-weight: 700;
}


.faq details p {
  margin: 0;
  padding: 0 16px 16px;
}


.faq summary:focus-visible {
  outline: 2px solid #171717;
  outline-offset: 2px;
}

위 파일과 ZIP의 동명 파일은 동일합니다. 회차별 README·CHANGES 문서는 ZIP에 포함합니다. 생성 산출물·node_modules·실제 환경 변수 파일은 포함하지 않습니다.

index.html

<section
  class="faq"
  id="faq"
>
  <h2>
    자주 묻는 질문
  </h2>


  <details>
    <summary>
      TaskFlow는 어떤 서비스인가요?
    </summary>
    <p>
      해야 할 일을 빠르게 정리하는 작업 관리 서비스 예제입니다.
    </p>
  </details>


  <details>
    <summary>
      모바일에서도 볼 수 있나요?
    </summary>
    <p>
      작은 화면부터 설계한 반응형 레이아웃을 사용합니다.
    </p>
  </details>


  <details>
    <summary>
      문의는 어디서 하나요?
    </summary>
    <p>
      아래 문의 폼을 이용할 수 있습니다.
    </p>
  </details>
</section>

style.css

.faq {
  display: grid;
  gap: 12px;
}


.faq details {
  border: 1px solid #d7d7d7;
  background: #fff;
}


.faq summary {
  padding: 16px;
  cursor: pointer;
  font-weight: 700;
}


.faq details p {
  margin: 0;
  padding: 0 16px 16px;
}


.faq summary:focus-visible {
  outline: 2px solid #171717;
  outline-offset: 2px;
}

시작본과 이번 변경

CSS position 완전 이해: relative·absolute·fixed·sticky 실습의 완료 체크포인트를 시작본으로 사용합니다.

기존 index.html main의 문의 영역 근처에 faq section을 추가하고 style.css에 summary·열린 답변·focus-visible 규칙을 넣습니다. 질문 세 개를 키보드로 모두 조작하고 확대 시 잘림을 확인합니다.

연속 프로젝트 선수 조건

  • 기본 HTML 시맨틱 구조와 keyboard focus 개념을 알고 있으면 좋습니다.
  • JavaScript 없이 native HTML 요소를 우선 사용하는 기준으로 진행합니다.

이전 체크포인트

publishing-step-04-position

이번 목표

TaskFlow에 FAQ section을 추가합니다.

실행 확인

  • Tab으로 각 summary에 이동합니다.
  • keyboard만으로 열고 닫아 봅니다.
  • open 상태와 closed 상태를 눈으로 구분할 수 있는지 확인합니다.
  • 200% zoom에서도 내용이 잘리지 않는지 확인합니다.

완료 체크포인트

publishing-step-05-faq

다음 학습

다음 글에서는 반복 카드와 요금제처럼 열 정렬이 필요한 영역을 CSS Grid로 구성합니다.

글 소개·학습 준비·전체 목차
HTML details와 summary로 접근 가능한 FAQ 만들기 대표 일러스트

웹 퍼블리싱 · 5 / 15 · 필수 학습 · details와 summary FAQ

FAQ를 만들기 위해 처음부터 div와 JavaScript click event를 직접 작성할 필요는 없습니다.

HTML의 details와 summary는 열림/닫힘 상태와 키보드 상호작용을 브라우저가 기본으로 제공하는 native disclosure 요소입니다.

이번 글에서 배우는 내용

  • details
  • summary
  • open attribute
  • native disclosure 동작
  • keyboard 접근성
  • marker 스타일
  • FAQ를 div click으로 재구현하지 않는 기준

먼저 알아야 할 내용

기본 HTML 요소와 Tab 키 초점 이동을 알면 됩니다. JavaScript 설치나 이전 화면은 필요하지 않습니다.

목차

이 글이 도움이 되었나요?

조회 중

읽음 기록

읽음 — / 전체 15개 · 필수 13개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기