Для начала нам будет нужно объявить переменные которые мы и будем сортировать в CSS:
:root{
--val1: 12;
--val2: 16;
--val3: 9;
--val4: 14;
--val5: 7;
...
Это условно массив чисел [15,5,14,7,13]. И минус решения пузырьковой сортировки на CSS является то, что каждый кейс и условие мы должны прописать явно. (И конечно же нагрузка на браузер и ваше устройство). Далее сохраним переменные в новые, которые будут изменяться и пересчитаываться:
...
--arr1s0: var(--val1);
--arr2s0: var(--val2);
--arr3s0: var(--val3);
--arr4s0: var(--val4);
--arr5s0: var(--val5);
Пример на codepen — https://codepen.io/GrahamTheDev/pen/ExGJMzm
Погружаемся в детали
// Создаем boolean переменные с агрегацией значений переменных, фактически нужно предусмотреть все возможные варианты.
--is-1-greater-2-step-1: Min(1, Max(var(--arr1s0) - var(--arr2s0), 0));
--is-2-greater-1-step-2: Min(1, Max(var(--arr2s0) - var(--arr1s0), 0));
...
В JS код бы выглядел более понятно, нужно просто сравнить оба числа и результат ноль будет означать что первое число меньше второго:
let pos1 = 4;
let pos2 = 8;
let diff1and2 = pos1 - pos2;
let OneGreaterOrZero = Math.max(diff1and2, 0);
let result = Math.min(1, OneGreaterOrZero);
console.log(diff1and2, OneGreaterOrZero, result); // -4, 0, 0
Далее для изменяемых переменных мы должны поменять местами значения, если они больше/меньше соседа:
--arr1s1: calc(var(--is-2-greater-1-step-1) * var(--arr1s0) + var(--is-1-greater-2-step-1) * var(--arr2s0));
--arr2s1: calc(var(--is-1-greater-2-step-1) * var(--arr1s0) + var(--is-2-greater-1-step-1) * var(--arr2s0));
Более понятный пример из JS:
// первые 2 значения
origArray = [7,2];
// у нас уже есть результаты в переменных, какая из них больше:
oneIsGreater = 1;
twoIsGreater = 0;
// т.к наш булеан это 1 или 0, то при умножении сбрасывается левое или правое значение и получаем по простой формуле перестановку в массиве.
newArray[0] = (twoIsGreater * origArray[0]) + (oneIsGreater * origArray[1]);
newArray[1] = (oneIsGreater * origArray[0]) + (twoIsGreater * origArray[1]);
// со значениями, это выглядит так:
newArray[0] = 0 * 7 + 1 * 2; //2
newArray[1] = 1 * 7 + 0 * 2; //7
И в связи с тем, что в CSS нету циклов, нужно вручную сравнить рядом стоящие значения и пройтись несколько раз. Сама анимация довольно просто работает, у нас для переменных arr1s0… используется персональный див, где есть динамический расчет размера и своя анимация.
В целом полезно узнать особенности применений CSS в разных ситуациях, пусть они даже будут такими специфичными когда должные 60 фпс браузера говорит «памагите» — всё равно такие кейсы расширяют кругозор.