If you are really passionate about web performance and you don’t really like JavaScript, then you have come to the right tutorial.
As an experienced web developer at exthem.es, I am personally passionate about building very fast and minimalist websites.
That is why here, I will show you how to create a pure CSS accordion without JavaScript.
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<section class="accordion"> <div class="tab"> <input type="checkbox" name="accordion-1" id="cb1" checked> <label for="cb1" class="tab__label">Checkbox</label> <div class="tab__content"> <p>Pure CSS accordion based on the "input:checked + label" style trick.</p> </div> </div> <div class="tab"> <input type="checkbox" name="accordion-1" id="cb2"> <label for="cb2" class="tab__label">Open multiple</label> <div class="tab__content"> <p>Using <code><input type="checkbox"></code> allows to have several tabs open at the same time.</p> </div> </div> </section> <section class="accordion accordion--radio"> <div class="tab"> <input type="radio" name="accordion-2" id="rd1"> <label for="rd1" class="tab__label">Radio</label> <div class="tab__content"> <p>If you want to have only one tab open, you can use <code><input type="checkbox"></code>.</p> </div> </div> <div class="tab"> <input type="radio" name="accordion-2" id="rd2"> <label for="rd2" class="tab__label">Open single</label> <div class="tab__content"> <p>But if you wanna close the opened tab, you must add a "close" button somewhere, like the one below, that is just another styled radio input.</p> </div> </div> <div class="tab"> <input type="radio" name="accordion-2" id="rd3"> <label for="rd3" class="tab__close">Close open tab ×</label> </div> </section> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
:root { --primary: #227093; --secondary: #ff5252; --background: #eee; --highlight: #ffda79; /* Theme color */ --theme: var(--primary); } *, *::before, *::after { box-sizing: border-box; } body { display: grid; place-content: center; grid-template-columns: repeat(auto-fit, min(100%, 30rem)); min-height: 100vh; place-items: start; gap: 1rem; margin: 0; padding: 1rem; color: var(--primary); background: var(--background); } /* Core styles/functionality */ .tab { position: relative; } .tab input { position: absolute; opacity: 0; z-index: -1; } .tab__content { max-height: 0; overflow: hidden; transition: all 0.35s; } .tab input:checked ~ .tab__content { max-height: 10rem; } /* Visual styles */ .accordion { color: var(--theme); border: 2px solid; border-radius: 0.5rem; overflow: hidden; } .tab__label, .tab__close { display: flex; color: white; background: var(--theme); cursor: pointer; } .tab__label { justify-content: space-between; padding: 1rem; } .tab__label::after { content: "\276F"; width: 1em; height: 1em; text-align: center; transform: rotate(90deg); transition: all 0.35s; } .tab input:checked + .tab__label::after { transform: rotate(270deg); } .tab__content p { margin: 0; padding: 1rem; } .tab__close { justify-content: flex-end; padding: 0.5rem 1rem; font-size: 0.75rem; } .accordion--radio { --theme: var(--secondary); } /* Arrow animation */ .tab input:not(:checked) + .tab__label:hover::after { animation: bounce .5s infinite; } @keyframes bounce { 25% { transform: rotate(90deg) translate(.25rem); } 75% { transform: rotate(90deg) translate(-.25rem); } } |