|$ curl https://forge-ai.dev/api/markdown?path=docs/components/accordions
$cat docs/accordions.md
updated Recently·12 min read·published
Accordions
◆CSS◆HTML◆UI◆Intermediate
Collapsible sections with pure CSS details/summary elements and interactive JavaScript accordions with animated open/close.
Details/Summary
Native HTML accordion using the <details> and <summary> elements — no JavaScript needed, fully accessible.
details
Live
untitled.html
HTML
| 1 | <div class="wrapper"> |
| 2 | <details class="accordion" open> |
| 3 | <summary class="accordion-header"> |
| 4 | What is this component? |
| 5 | <span class="icon"> |
| 6 | − |
| 7 | </span> |
| 8 | </summary> |
| 9 | <div class="accordion-body"> |
| 10 | This is a native HTML accordion built with the details and summary elements. It supports open state by default using the open attribute, and browsers handle all the show/hide logic natively. |
| 11 | </div> |
| 12 | </details> |
| 13 | <details class="accordion"> |
| 14 | <summary class="accordion-header"> |
| 15 | How does it work? |
| 16 | <span class="icon"> |
| 17 | + |
| 18 | </span> |
| 19 | </summary> |
| 20 | <div class="accordion-body"> |
| 21 | The details element creates a disclosure widget. When open, its contents are visible. The summary element provides the visible label. Clicking the summary toggles the open state automatically. |
| 22 | </div> |
| 23 | </details> |
| 24 | <details class="accordion"> |
| 25 | <summary class="accordion-header"> |
| 26 | What are the benefits? |
| 27 | <span class="icon"> |
| 28 | + |
| 29 | </span> |
| 30 | </summary> |
| 31 | <div class="accordion-body"> |
| 32 | Zero JavaScript required, built-in keyboard navigation (Enter/Space to toggle), screen reader friendly, and semantic HTML that works with any CSS framework. |
| 33 | </div> |
| 34 | </details> |
| 35 | </div> |
untitled.css
CSS
| 1 | .wrapper { |
| 2 | max-width:450px; |
| 3 | margin:16px auto; |
| 4 | display:flex; |
| 5 | flex-direction:column; |
| 6 | gap:8px; |
| 7 | padding:0 16px |
| 8 | } |
| 9 | .accordion { |
| 10 | border-radius:8px; |
| 11 | border:1px solid #2A2A2A; |
| 12 | overflow:hidden; |
| 13 | background:#111; |
| 14 | transition:border-color .2s |
| 15 | } |
| 16 | .accordion[open] { |
| 17 | border-color:#00FF41/30 |
| 18 | } |
| 19 | .accordion-header { |
| 20 | display:flex; |
| 21 | align-items:center; |
| 22 | justify-content:space-between; |
| 23 | padding:14px 16px; |
| 24 | font-size:13px; |
| 25 | font-weight:600; |
| 26 | font-family:system-ui, |
| 27 | sans-serif; |
| 28 | color:#E0E0E0; |
| 29 | cursor:pointer; |
| 30 | user-select:none; |
| 31 | list-style:none; |
| 32 | transition:color .2s |
| 33 | } |
| 34 | .accordion-header::-webkit-details-marker { |
| 35 | display:none |
| 36 | } |
| 37 | .accordion-header:hover { |
| 38 | color:#00FF41 |
| 39 | } |
| 40 | .icon { |
| 41 | font-size:16px; |
| 42 | color:#666; |
| 43 | transition:transform .2s |
| 44 | } |
| 45 | .accordion[open] .icon { |
| 46 | color:#00FF41 |
| 47 | } |
| 48 | .accordion-body { |
| 49 | padding:0 16px 14px; |
| 50 | font-size:12px; |
| 51 | font-family:system-ui, |
| 52 | sans-serif; |
| 53 | color:#A0A0A0; |
| 54 | line-height:1.6; |
| 55 | border-top:1px solid #2A2A2A; |
| 56 | padding-top:12px; |
| 57 | margin-top:0 |
| 58 | } |
JavaScript Accordion
Custom accordion with animated open/close, single-item-only mode (one open at a time), and smooth height transitions.
js-accordion
Live
untitled.html
HTML
| 1 | <div class="wrapper" id="accordion-group"> |
| 2 | <div class="js-accordion open"> |
| 3 | <button class="js-header" data-index="0"> |
| 4 | <span> |
| 5 | Account Settings |
| 6 | </span> |
| 7 | <svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 8 | <polyline points="6 9 12 15 18 9"/> |
| 9 | </svg> |
| 10 | </button> |
| 11 | <div class="js-body" style="max-height:200px"> |
| 12 | <div class="js-inner"> |
| 13 | <label class="field"> |
| 14 | <span> |
| 15 | Full Name |
| 16 | </span> |
| 17 | <input type="text" value="Jane Doe" readonly/> |
| 18 | </label> |
| 19 | <label class="field"> |
| 20 | <span> |
| 21 | |
| 22 | </span> |
| 23 | <input type="email" value="jane@example.com" readonly/> |
| 24 | </label> |
| 25 | </div> |
| 26 | </div> |
| 27 | </div> |
| 28 | <div class="js-accordion"> |
| 29 | <button class="js-header" data-index="1"> |
| 30 | <span> |
| 31 | Notifications |
| 32 | </span> |
| 33 | <svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 34 | <polyline points="6 9 12 15 18 9"/> |
| 35 | </svg> |
| 36 | </button> |
| 37 | <div class="js-body"> |
| 38 | <div class="js-inner"> |
| 39 | <label class="toggle-field"> |
| 40 | <span> |
| 41 | Email notifications |
| 42 | </span> |
| 43 | <input type="checkbox" checked/> |
| 44 | </label> |
| 45 | <label class="toggle-field"> |
| 46 | <span> |
| 47 | Push notifications |
| 48 | </span> |
| 49 | <input type="checkbox"/> |
| 50 | </label> |
| 51 | <label class="toggle-field"> |
| 52 | <span> |
| 53 | SMS alerts |
| 54 | </span> |
| 55 | <input type="checkbox"/> |
| 56 | </label> |
| 57 | </div> |
| 58 | </div> |
| 59 | </div> |
| 60 | <div class="js-accordion"> |
| 61 | <button class="js-header" data-index="2"> |
| 62 | <span> |
| 63 | Privacy |
| 64 | </span> |
| 65 | <svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 66 | <polyline points="6 9 12 15 18 9"/> |
| 67 | </svg> |
| 68 | </button> |
| 69 | <div class="js-body"> |
| 70 | <div class="js-inner"> |
| 71 | <p class="privacy-text"> |
| 72 | Your privacy settings control how your data is used and shared. Review and adjust your preferences below. |
| 73 | </p> |
| 74 | <button class="action-btn"> |
| 75 | Manage Privacy |
| 76 | </button> |
| 77 | </div> |
| 78 | </div> |
| 79 | </div> |
| 80 | </div> |
untitled.css
CSS
| 1 | .wrapper { |
| 2 | max-width:450px; |
| 3 | margin:16px auto; |
| 4 | display:flex; |
| 5 | flex-direction:column; |
| 6 | gap:6px; |
| 7 | padding:0 16px |
| 8 | } |
| 9 | .js-accordion { |
| 10 | border-radius:8px; |
| 11 | border:1px solid #2A2A2A; |
| 12 | overflow:hidden; |
| 13 | background:#111; |
| 14 | transition:border-color .2s |
| 15 | } |
| 16 | .js-accordion.open { |
| 17 | border-color:#00FF41/30 |
| 18 | } |
| 19 | .js-header { |
| 20 | display:flex; |
| 21 | align-items:center; |
| 22 | justify-content:space-between; |
| 23 | width:100%; |
| 24 | padding:14px 16px; |
| 25 | font-size:13px; |
| 26 | font-weight:600; |
| 27 | font-family:system-ui, |
| 28 | sans-serif; |
| 29 | color:#E0E0E0; |
| 30 | cursor:pointer; |
| 31 | border:none; |
| 32 | background:transparent; |
| 33 | transition:color .2s |
| 34 | } |
| 35 | .js-header:hover { |
| 36 | color:#00FF41 |
| 37 | } |
| 38 | .arrow { |
| 39 | transition:transform .3s ease; |
| 40 | color:#666 |
| 41 | } |
| 42 | .open .arrow { |
| 43 | transform:rotate(180deg); |
| 44 | color:#00FF41 |
| 45 | } |
| 46 | .js-body { |
| 47 | max-height:0; |
| 48 | overflow:hidden; |
| 49 | transition:max-height .3s ease |
| 50 | } |
| 51 | .js-inner { |
| 52 | padding:0 16px 14px; |
| 53 | border-top:1px solid #2A2A2A; |
| 54 | padding-top:12px |
| 55 | } |
| 56 | .field { |
| 57 | display:flex; |
| 58 | flex-direction:column; |
| 59 | gap:4px; |
| 60 | margin-bottom:10px |
| 61 | } |
| 62 | .field span { |
| 63 | font-size:10px; |
| 64 | color:#666; |
| 65 | text-transform:uppercase; |
| 66 | letter-spacing:.5px |
| 67 | } |
| 68 | .field input { |
| 69 | padding:8px 10px; |
| 70 | border-radius:6px; |
| 71 | border:1px solid #2A2A2A; |
| 72 | background:#0A0A0A; |
| 73 | color:#E0E0E0; |
| 74 | font-size:12px; |
| 75 | font-family:system-ui, |
| 76 | sans-serif |
| 77 | } |
| 78 | .toggle-field { |
| 79 | display:flex; |
| 80 | align-items:center; |
| 81 | justify-content:space-between; |
| 82 | padding:8px 0; |
| 83 | font-size:12px; |
| 84 | color:#C0C0C0; |
| 85 | font-family:system-ui, |
| 86 | sans-serif |
| 87 | } |
| 88 | .toggle-field input[type=checkbox] { |
| 89 | width:36px; |
| 90 | height:20px; |
| 91 | appearance:none; |
| 92 | background:#333; |
| 93 | border-radius:10px; |
| 94 | position:relative; |
| 95 | cursor:pointer; |
| 96 | transition:background .2s |
| 97 | } |
| 98 | .toggle-field input[type=checkbox]:checked { |
| 99 | background:#00FF41 |
| 100 | } |
| 101 | .toggle-field input[type=checkbox]::after { |
| 102 | content:''; |
| 103 | position:absolute; |
| 104 | top:2px; |
| 105 | left:2px; |
| 106 | width:16px; |
| 107 | height:16px; |
| 108 | border-radius:50%; |
| 109 | background:#fff; |
| 110 | transition:transform .2s |
| 111 | } |
| 112 | .toggle-field input[type=checkbox]:checked::after { |
| 113 | transform:translateX(16px) |
| 114 | } |
| 115 | .privacy-text { |
| 116 | font-size:12px; |
| 117 | color:#A0A0A0; |
| 118 | line-height:1.5; |
| 119 | margin-bottom:12px |
| 120 | } |
| 121 | .action-btn { |
| 122 | padding:8px 16px; |
| 123 | border-radius:6px; |
| 124 | font-size:12px; |
| 125 | font-weight:600; |
| 126 | font-family:system-ui, |
| 127 | sans-serif; |
| 128 | cursor:pointer; |
| 129 | border:1px solid #00FF41; |
| 130 | background:transparent; |
| 131 | color:#00FF41; |
| 132 | transition:all .2s |
| 133 | } |
| 134 | .action-btn:hover { |
| 135 | background:#00FF41; |
| 136 | color:#0A0A0A |
| 137 | } |
untitled.js
JavaScript
| 1 | document.querySelectorAll('.js-header').forEach(btn=>{btn.addEventListener('click',()=>{const accordion=btn.parentElement;const body=accordion.querySelector('.js-body');const isOpen=accordion.classList.contains('open');document.querySelectorAll('.js-accordion.open').forEach(el=>{if(el!==accordion){el.classList.remove('open');el.querySelector('.js-body').style.maxHeight='0'}});if(isOpen){accordion.classList.remove('open');body.style.maxHeight='0'}else{accordion.classList.add('open');body.style.maxHeight=body.scrollHeight+'px'}})}) |
FAQ Style
FAQ-style accordion with compact design, larger click targets, and smooth transitions.
faq
Live
untitled.html
HTML
| 1 | <div class="wrapper"> |
| 2 | <div class="faq-item"> |
| 3 | <button class="faq-q"> |
| 4 | How do I reset my password? |
| 5 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"> |
| 6 | <polyline points="6 9 12 15 18 9"/> |
| 7 | </svg> |
| 8 | </button> |
| 9 | <div class="faq-a"> |
| 10 | <p> |
| 11 | Go to Settings > Security > Reset Password. Enter your email address and we'll send you a reset link. The link expires in 24 hours. |
| 12 | </p> |
| 13 | </div> |
| 14 | </div> |
| 15 | <div class="faq-item"> |
| 16 | <button class="faq-q"> |
| 17 | Can I export my data? |
| 18 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"> |
| 19 | <polyline points="6 9 12 15 18 9"/> |
| 20 | </svg> |
| 21 | </button> |
| 22 | <div class="faq-a"> |
| 23 | <p> |
| 24 | Yes. Navigate to Settings > Data > Export. You can download your data as JSON, CSV, or PDF. Large exports are emailed as a zip file. |
| 25 | </p> |
| 26 | </div> |
| 27 | </div> |
| 28 | <div class="faq-item"> |
| 29 | <button class="faq-q"> |
| 30 | Is there a mobile app? |
| 31 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"> |
| 32 | <polyline points="6 9 12 15 18 9"/> |
| 33 | </svg> |
| 34 | </button> |
| 35 | <div class="faq-a"> |
| 36 | <p> |
| 37 | Our mobile app is available on iOS and Android. Download it from the App Store or Google Play Store for on-the-go access. |
| 38 | </p> |
| 39 | </div> |
| 40 | </div> |
| 41 | </div> |
untitled.css
CSS
| 1 | .wrapper { |
| 2 | max-width:500px; |
| 3 | margin:16px auto; |
| 4 | display:flex; |
| 5 | flex-direction:column; |
| 6 | gap:6px; |
| 7 | padding:0 16px |
| 8 | } |
| 9 | .faq-item { |
| 10 | border-radius:8px; |
| 11 | border:1px solid #2A2A2A; |
| 12 | overflow:hidden; |
| 13 | background:#111 |
| 14 | } |
| 15 | .faq-q { |
| 16 | display:flex; |
| 17 | align-items:center; |
| 18 | justify-content:space-between; |
| 19 | width:100%; |
| 20 | padding:16px; |
| 21 | font-size:13px; |
| 22 | font-weight:500; |
| 23 | font-family:system-ui, |
| 24 | sans-serif; |
| 25 | color:#E0E0E0; |
| 26 | cursor:pointer; |
| 27 | border:none; |
| 28 | background:transparent; |
| 29 | transition:color .2s; |
| 30 | text-align:left |
| 31 | } |
| 32 | .faq-q:hover { |
| 33 | color:#00FF41 |
| 34 | } |
| 35 | .faq-q svg { |
| 36 | transition:transform .3s ease; |
| 37 | color:#666; |
| 38 | flex-shrink:0 |
| 39 | } |
| 40 | .faq-q.active svg { |
| 41 | transform:rotate(180deg); |
| 42 | color:#00FF41 |
| 43 | } |
| 44 | .faq-a { |
| 45 | max-height:0; |
| 46 | overflow:hidden; |
| 47 | transition:max-height .3s ease; |
| 48 | padding:0 16px; |
| 49 | font-size:12px; |
| 50 | font-family:system-ui, |
| 51 | sans-serif; |
| 52 | color:#A0A0A0; |
| 53 | line-height:1.6; |
| 54 | border-top:1px solid transparent |
| 55 | } |
| 56 | .faq-a.open { |
| 57 | max-height:200px; |
| 58 | padding:0 16px 14px; |
| 59 | border-top-color:#2A2A2A |
| 60 | } |
| 61 | .faq-a p { |
| 62 | margin:0; |
| 63 | padding-top:12px |
| 64 | } |
untitled.js
JavaScript
| 1 | document.querySelectorAll('.faq-q').forEach(btn=>{btn.addEventListener('click',()=>{const answer=btn.nextElementSibling;const isOpen=answer.classList.contains('open');document.querySelectorAll('.faq-a.open').forEach(el=>{el.classList.remove('open');el.previousElementSibling.classList.remove('active')});if(!isOpen){answer.classList.add('open');btn.classList.add('active')}})}) |