image

Знаю, звучит толсто. Но это правда возможно. Почти. Предлагаемый мной способ вряд ли применим в крупных проектах, но в мелких, для себя, типа «сайтов про кота», вполне рабочее решение. Возможность сортировки нам предоставит flexbox и css-переменные (они же custom properties) и js тут не потребуется.

Для начала создадим простой список критериев сортировки, который можно видеть почти в каждом интернет-магазине – по умолчанию, по цене (возрастание/убывание), по алфавиту (возрастание/убывание):

<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>

А так же сам сортируемый список. В этом списке каждый элемент имеет название товара (в данном случае «Первый», «Второй» и т.п. и цену товара).

<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;
}

Что означает отсортировать список? Это значит, нам нужно поменять взаимное расположение элементов в списке. Потомкам flex-блока можно задать свойство order для изменения порядка их следования в блоке. Если order не задан для элемента, его значение равно нулю. Элемент с большим значением order будет поставлен ближе к концу блока, элемент с меньшим – ближе к началу. Таким образом, нам нужно всего лишь добавить некие сведения о порядке расположения элементов списка в свойство order каждого элемента. В этом нам помогут css-переменные (inline-css тут для наглядности).

<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>

И подставив в order значение из css-переменной мы получим элементы расставленные в нужном порядке.

/* по умолчанию */
#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);
}

Для сортировки по возрастанию/убыванию можно использовать свойство flex-direction:

#q3:checked ~ .wrapper,
#q5:checked ~ .wrapper {
	flex-direction: column-reverse;
}

К сожалению, сразу становится очевидна проблема «почти», о которой я упомянул в начале – порядок следования элементов, заданный в css-переменных должен быть определен заранее. И если с ценой это не представляет особой проблемы, можно просто указать значение в переменной --cost как есть, то с остальными сортировками, по умолчанию и по алфавиту, придется заранее раздать элементам индексы. К плюсам решения можно отнести то, что изменения в порядке сортировки применяются мгновенно.

> Вот рабочий прототип

Комментарии (5)


  1. dro1d
    21.02.2018 16:00

    Еще один очевидный минус, о котором не указал автор: выделение текста — поскольку порядок текст всегда один, меняется только отображение на экране, то при попытке выделить текст может выделиться, например, первый, пятый и последний элемент списка.


  1. TanyaS
    21.02.2018 16:13
    +1

    Буквально на днях читала о подобном у Романа Комарова, а чуть позже на CSS-live, где поясняется, что так делать не следует.


  1. pepelsbey
    21.02.2018 16:27
    +1

    Только не надо делать вид, что это рабочее решение. Оно недоступно с клавиатуры, для скринридеров и не выглядит проще. В чём, собственно, профит решений на чистом CSS? В том, что вам не нужно писать JS? На любом сайте уже куча JS.


    Давайте сделаем правильный выбор между плохой сортировкой на CSS и хорошей на JS.


    1. namikiri
      21.02.2018 16:44
      +1

      Только не надо делать вид, что Malbolge — хороший язык программирования.
      Понятное дело, что это решение не просто костыльное, оно откровенно странное и абсолютно неприменимое, настолько же, насколько применим 3D-движок на Excel.
      Оно сделано забавы ради и интереса для.


    1. Alexmaru
      21.02.2018 19:51

      Профита нет, кроме того, что формально — это вычисления на не предназначенном (не тьюринг-полном) для этого языке.