Splitting items into two separate lists, with counts. Click an item to toggle. No JavaScript.
Blog post: Checkbox Trickery with CSS
Splitting items into two separate lists, with counts. Click an item to toggle. No JavaScript.
Blog post: Checkbox Trickery with CSS
| <!-- | |
| Checkbox Trickery with CSS: | |
| http://codersblock.com/blog/checkbox-trickery-with-css/ | |
| --> | |
| <div class="container"> | |
| <h1>Will's Summer To-Do List</h1> | |
| <div class="items"> | |
| <input id="item1" type="checkbox" checked> | |
| <label for="item1">Create a to-do list</label> | |
| <input id="item2" type="checkbox"> | |
| <label for="item2">Take down Christmas tree</label> | |
| <input id="item3" type="checkbox"> | |
| <label for="item3">Learn Ember.js</label> | |
| <input id="item4" type="checkbox"> | |
| <label for="item4">Binge watch every episode of MacGyver</label> | |
| <input id="item5" type="checkbox"> | |
| <label for="item5">Alphabetize everything in the fridge</label> | |
| <input id="item6" type="checkbox"> | |
| <label for="item6">Do 10 pull-ups without dropping</label> | |
| <h2 class="done" aria-hidden="true">Done</h2> | |
| <h2 class="undone" aria-hidden="true">Not Done</h2> | |
| </div> | |
| </div> |
| @import url(https://fonts.googleapis.com/css?family=Roboto:500,700); | |
| *, *::before, *::after { | |
| box-sizing: border-box; | |
| } | |
| html { | |
| min-height: 100%; | |
| } | |
| body { | |
| margin: 20px; | |
| color: #435757; | |
| font: 500 1.2em/1.2 'Roboto', sans-serif; | |
| } | |
| .container { | |
| max-width: 450px; | |
| margin: 0 auto; | |
| border-top: 5px solid #435757; | |
| background-color: rgba(255, 255, 255, .2); | |
| box-shadow: 0 0 20px rgba(0, 0, 0, .1); | |
| user-select: none; | |
| } | |
| h1 { | |
| margin: 0; | |
| padding: 20px; | |
| background-color: rgba(255, 255, 255, .4); | |
| font-size: 1.8em; | |
| text-align: center; | |
| } | |
| .items { | |
| display: flex; | |
| flex-direction: column; | |
| padding: 20px; | |
| counter-reset: done-items undone-items; | |
| } | |
| h2 { | |
| position: relative; | |
| margin: 0; | |
| padding: 10px 0; | |
| font-size: 1.2em; | |
| } | |
| h2::before { | |
| content: ''; | |
| display: block; | |
| position: absolute; | |
| top: 10px; | |
| bottom: 10px; | |
| left: -20px; | |
| width: 5px; | |
| background-color: #435757; | |
| } | |
| h2::after { | |
| display: block; | |
| float: right; | |
| font-weight: normal; | |
| } | |
| .done { | |
| order: 2; | |
| } | |
| .done::after { | |
| content: ' (' counter(done-items) ')'; | |
| } | |
| .undone { | |
| order: 1; | |
| } | |
| .undone::after { | |
| content: ' (' counter(undone-items) ')'; | |
| } | |
| /* hide inputs offscreen, but at the same vertical positions as the correpsonding labels, so that tabbing scrolls the viewport as expected */ | |
| input { | |
| display: block; | |
| height: 53px; | |
| margin: 0 0 -53px -9999px; | |
| order: 2; | |
| outline: none; | |
| counter-increment: undone-items; | |
| } | |
| input:checked { | |
| order: 4; | |
| counter-increment: done-items; | |
| } | |
| label { | |
| display: block; | |
| position: relative; | |
| padding: 15px 0 15px 45px; | |
| border-top: 1px dashed #fff; | |
| order: 2; | |
| cursor: pointer; | |
| animation: undone .5s; | |
| } | |
| label::before { | |
| content: '\f10c'; /* circle outline */ | |
| display: block; | |
| position: absolute; | |
| top: 11px; | |
| left: 1px; | |
| font: 1.5em 'FontAwesome'; | |
| } | |
| label:hover, input:focus + label { | |
| background-color: rgba(255, 255, 255, .2); | |
| } | |
| input:checked + label { | |
| order: 4; | |
| animation: done .5s; | |
| } | |
| input:checked + label::before { | |
| content: '\f058'; /* circle checkmark */ | |
| } | |
| @keyframes done { | |
| 0% { | |
| opacity: 0; | |
| background-color: rgba(255, 255, 255, .4); | |
| transform: translateY(20px); | |
| } | |
| 50% { | |
| opacity: 1; | |
| background-color: rgba(255, 255, 255, .4); | |
| } | |
| } | |
| @keyframes undone { | |
| 0% { | |
| opacity: 0; | |
| background-color: rgba(255, 255, 255, .4); | |
| transform: translateY(-20px); | |
| } | |
| 50% { | |
| opacity: 1; | |
| background-color: rgba(255, 255, 255, .4); | |
| } | |
| } |