IT/웹 개발

간단하게 만드는 아코디언 메뉴 - HTML 전용 태그 활용

방금일어남 2024. 9. 10. 10:20

아코디언 메뉴란?

아코디언 메뉴는 사용자가 항목을 클릭할 때마다 내용을 펼치거나 접는 UI를 의미합니다.

일반적으로 '아코디언 메뉴' 또는 '아코디언 패널'이라고 부릅니다.

 

주로 공간을 절약하거나 정보 계층 구조를 관리하는 데 사용합니다.

 

 

 


아코디언 전용 태그

혹시 HTML 기본 태그에 아코디언 전용 태그가 있다는 사실 알고 계셨나요?

HTML5에서 <details> 태그는 아코디언 기능을 지원합니다.

 

기본 HTML 구조입니다.

<details>
  <summary>Details</summary>
  Something small enough to escape casual notice.
</details>

 

OUTPUT

 

Details Something small enough to escape casual notice.

 

<details> 태그만 사용해도 바로 아코디언 메뉴를 구현할 수 있습니다.

하지만 이 상태는 너무 투박하기 때문에 약간의 스타일링을 하겠습니다.

 


CSS로 스타일링

 

# 아이콘 커스텀

 

기본 상태에서는 <summary> 부분에 닫힘 상태('►')와 열림 상태('▼')를 나타내는 기본 ::marker로 표시됩니다.

저는 이 부분을 커스텀하겠습니다.

 

기본 ::marker의 내용을 지우고, ::before::after를 활용해서 원하는 아이콘을 넣어줬습니다.

details>summary::marker {
    content: '';	/* 기본 아이콘 지우기 */
}

details>summary::before {
    content: 'Q';	/* 커스텀 아이콘 */
}

details>summary::after {
    content: '';
    
    /* 커스텀 아이콘 */
    /* 아이콘 크기를 조절하기 위해 content 대신 background 사용 */
    display: inline-block;
    width: 16px;
    height: 16px;
    background-image: url('./ic_arrow_down.png');
    background-size: cover;
}

details[open]>summary::after {
    transform: scaleY(-1);
}

# 애니메이션

 

JS를 사용하지 않고, 순수 CSS로 <details> 태그의 확장 및 축소에 애니메이션 효과를 줄 수 있습니다.

체크박스를 통해, 사용자의 상호작용을 감지하는 방법입니다.

 

체크박스를 <details> 태그의 형제 위치에 선언하고, <label> 태그를 <summary> 태그 안에 삽입합니다.

<input type="checkbox" name="check-summary" id="check-summary">
<details open>
    <summary><label for="check-summary">아코디언 메뉴란?</label></summary>
    <div class="content">
        <p>
            아코디언 메뉴는 사용자가 항목을 클릭할 때마다 내용을 펼치거나 접는 UI를 의미합니다.<br>
            일반적으로 '아코디언 메뉴' 또는 '아코디언 패널'이라고 부릅니다.
        </p>
        <p>주로 공간을 절약하거나 정보 계층 구조를 관리하는 데 사용합니다.</p>
    </div>
</details>

 

CSS에서는 max-height를 사용하여 <details> 태그의 내용을 숨깁니다.

details {
    max-height: 2em;	/* 최대 높이를 2em로 설정하여 summary만 보이도록 합니다 */
    overflow: hidden;	/* max-height를 초과하는 내용은 숨깁니다 */
    transition: max-height 400ms ease-out;	/* max-height가 변경될 때 애니메이션 효과를 추가합니다 */
}

 

인접 형제 선택자를 사용하여 체크박스가 체크되었을 때 <details> 태그의 max-height를 변경합니다.

max-height가 변경되면 transition 속성에 의해 애니메이션이 적용됩니다.

#check-summary:checked+details {
    max-height: 250px;
}

 


최종 코드

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>details</title>

    <style>
        body {
            width: 1050px;
            margin: 0 auto;
            padding: 100px;
        }

        #check-summary {
            display: none;
        }

        details {
            width: 100%;
            text-align: left;
            margin: 0 0 24px 0;

            max-height: 2em;	/* 최대 높이를 2em로 설정하여 summary만 보이도록 합니다 */
            overflow: hidden;	/* max-height를 초과하는 내용은 숨깁니다 */
            transition: max-height 400ms ease-out;	/* max-height가 변경될 때 애니메이션 효과를 추가합니다 */
        }

        details:last-child {
            margin: 0 0 0 0;
        }

        #check-summary:checked+details {
            max-height: 250px;
        }

        details>summary {
            width: 100%;
        }

        details>summary::marker {
            content: '';
        }

        details>summary>label[for="check-summary"] {
            display: flex;
            font-size: 22px;
            font-weight: bold;
            letter-spacing: 0px;
            line-height: 1.18;
            color: #05309D;
            margin: 0 0 24px 0;
            cursor: pointer;
        }

        details>summary>label[for="check-summary"]::before {
            content: 'Q';	/* 커스텀 아이콘 */
            margin: 0 24px 0 0;
        }

        details>summary>label[for="check-summary"]::after {
            content: '';
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url('./ic_arrow_down.png');
            background-size: cover;
            margin: 0 0 0 auto;
        }

        #check-summary:checked+details>summary>label[for="check-summary"]::after {
            transform: scaleY(-1);
        }

        details>.content {
            font-size: 18px;
            font-weight: var(--font-weight-regular);
            letter-spacing: 0px;
            line-height: 1.4;
            color: #181B21;
            background-color: #F7F8F8;
            border-radius: 10px;
            padding: 32px 24px;
        }
    </style>
</head>

<body>
    <input type="checkbox" name="check-summary" id="check-summary">
    <details open>
        <summary><label for="check-summary">아코디언 메뉴란?</label></summary>
        <div class="content">
            <p>
                아코디언 메뉴는 사용자가 항목을 클릭할 때마다 내용을 펼치거나 접는 UI를 의미합니다.<br>
                일반적으로 '아코디언 메뉴' 또는 '아코디언 패널'이라고 부릅니다.
            </p>
            <p>주로 공간을 절약하거나 정보 계층 구조를 관리하는 데 사용합니다.</p>
        </div>
    </details>
</body>

</html>

 

OUTPUT

 

아코디언 메뉴는 사용자가 항목을 클릭할 때마다 내용을 펼치거나 접는 UI를 의미합니다.
일반적으로 '아코디언 메뉴' 또는 '아코디언 패널'이라고 부릅니다.

주로 공간을 절약하거나 정보 계층 구조를 관리하는 데 사용합니다.

 

 


Reference

[1] https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details

[2] https://www.w3schools.com/tags/tag_details.asp

[3] https://dev.to/jgustavoas/how-to-fully-animate-the-details-html-element-with-only-css-no-javascript-2n88