
I know it sounds fat. But it is really possible. Nearly. The method proposed by me is hardly applicable in large projects, but in small ones, for oneself, such as “cat websites”, it is quite a working solution. The ability to sort will be provided by flexbox and css-variables (they are custom properties), and js will not be required here.
To begin with, we will create a simple list of sorting criteria, which can be seen in almost every online store - by default, by price (ascending / descending), alphabetically (ascending / descending):
<input id="q1" type="radio" name="sort" checked> <label for="q1"> </label><br> <input id="q2" type="radio" name="sort"> <label for="q2"> , </label><br> <input id="q3" type="radio" name="sort"> <label for="q3"> , </label><br> <input id="q4" type="radio" name="sort"> <label for="q4"> , </label><br> <input id="q5" type="radio" name="sort"> <label for="q5"> , </label><br>
As well as the list itself is sorted. In this list, each element has the name of the product (in this case, "First", "Second", etc., and the price of the product).
')
<div class="wrapper"> <div class="item"> - 20000</div> <div class="item"> - 17550</div> <div class="item"> - 17549</div> <div class="item"> - 17549</div> <div class="item"> - 17549</div> </div>
.wrapper { display: flex; flex-direction: column; }
What does it mean to sort the list? This means we need to change the relative position of the elements in the list. The descendants of a flex block can be given an order property to change the order in which they are followed in a block. If order is not specified for an item, its value is zero. An element with a higher order value will be placed closer to the end of the block, an element with a smaller value will be placed closer to the beginning. Thus, we only need to add some information about the order of the elements of the list in the order property of each element. This will help us css-variables (inline-css here for clarity).
<div class="wrapper"> <div class="item" style="--default: 1; --cost: 20000; --title: 2;"> - 20000 </div> <div class="item" style="--default: 2; --cost: 17550; --title: 1;"> - 17550 </div> <div class="item" style="--default: 3; --cost: 17549; --title: 4;"> - 17549 </div> <div class="item" style="--default: 4; --cost: 17549; --title: 5;"> - 17549 </div> <div class="item" style="--default: 5; --cost: 17549; --title: 3;"> - 17549 </div> </div>
And substituting in order the value of the css-variable, we get the elements arranged in the correct order.
#q1:checked ~ .wrapper > .item { order: var(--default); } #q2:checked ~ .wrapper > .item, #q3:checked ~ .wrapper > .item { order: var(--cost); } #q4:checked ~ .wrapper > .item, #q5:checked ~ .wrapper > .item { order: var(--title); }
To sort ascending / descending, you can use the flex-direction property:
#q3:checked ~ .wrapper, #q5:checked ~ .wrapper { flex-direction: column-reverse; }
Unfortunately, the problem of “almost”, which I mentioned at the beginning, becomes obvious - the order of the elements specified in the css-variables must be determined in advance. And if this does not pose a special problem with the price, you can simply specify the value in the --cost variable as it is, then with the remaining sorts, by default and alphabetically, you will have to distribute the indexes to the elements in advance. The advantages of the solution include the fact that changes in the sort order are applied instantly.
→ Here is a working
prototype