Способы смены порядка вывода элементов с помощью CSS
Оригинал статьи: A Few Different CSS Methods for Changing Display Order
Оглавление:В этой статье мы рассмотрим несколько различных методов CSS для переупорядочения вывода элементов HTML.
Цель
Наша раскладка очень простая. В частности, на маленьких экранах (меньше 600px) она будет выглядеть так:
На средних экранах и больше (от 600px) кнопки будут выстраиваться в ряд:
Наша главная задача — поменять порядок кнопок на обратный.
Разметка
Разметка будет самая простая: просто элемент div
, содержащий четыре кнопки:
<div class="boxes">
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
<button>Button 4</button>
</div>
Стили
На маленьком экране у всех кнопок будут одинаковые стили:
.boxes button {
display: block;
width: 100%;
padding: 15px;
border: none;
margin-bottom: 5px;
box-sizing: border-box;
font-size: 1rem;
text-align: center;
text-decoration: none;
background: gold;
color: #000;
}
.boxes button:nth-of-type(even) {
background: #e6c200;
}
На больших экранах мы зададим width: 25%
, остальные стили будут определяться методом CSS, который мы будем применять для задания обратного порядка кнопок.
@media screen and (min-width: 600px) {
/* we skip this property in flexbox and grid methods */
width: 25%;
/* more stuff here */
}
Наконец, у нас будут стили для состояния focus
наших кнопок:
.boxes button:focus {
outline: none;
color: #fff;
background: firebrick;
}
Таким образом, если мы будем использовать для навигации клавишу Tab, наши кнопки при фокусировке станут темно-красными.
Методы упорядочивания колонок
Теперь мы готовы проверить различные подходы CSS для вывода кнопок в реверсивном порядке при превышении областью видимости ширины в 599px.
Метод №1: плавающие блоки
Можно просто добавить блокам float: right
, вот полные стили:
@media screen and (min-width: 600px) {
.boxes button {
float: right;
width: 25%;
}
}
И демо с Codepen:
See the Pen Using Floats for Reverse Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Метод №2: позиционирование
Альтернативным вариантом будет задание позиции элементам, относительной или абсолютной.
По первому варианту (с относительным позиционированием) мы зададим кнопкам, плывущим влево свойство position: relative
и затем расставим их с помощью свойство left
.
Вот CSS:
@media screen and (min-width: 600px) {
.boxes button {
position: relative;
float: left;
width: 25%;
}
.boxes button:nth-of-type(1) {
left: 75%;
}
.boxes button:nth-of-type(2) {
left: 25%;
}
.boxes button:nth-of-type(3) {
left: -25%;
}
.boxes button:nth-of-type(4) {
left: -75%;
}
}
Демо с Codepen:
See the Pen Using Positioning (relative) for Reverse Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Вторым вариантом (с использованием абсолютного позиционирования) мы зададим нашим кнопкам position: absolute
, а с помощью свойства left
разместим их более точно.
Соответствующий CSS:
@media screen and (min-width: 600px) {
.boxes {
position: relative;
}
.boxes button {
position: absolute;
width: 25%;
}
.boxes button:nth-of-type(1) {
left: 75%;
}
.boxes button:nth-of-type(2) {
left: 50%;
}
.boxes button:nth-of-type(3) {
left: 25%;
}
.boxes button:nth-of-type(4) {
left: 0;
}
}
Демо на Codepen:
See the Pen Using Positioning (absolute) for Reverse Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Метод №3: свойство direction
Менее очевиден подход на основе свойства direction
— оно предназначено для смены направления чтения текста. В нашем случае мы задаем direction: rtl
(справа налево) для элемента-обертки, что позволит сменить направление раскладки.
Примечание: для этого примера мы дадим нашим кнопкам поведение элементов таблицы, чтобы создать горизонтальную раскладку.
Вы можете видеть необходимые стили CSS ниже:
@media screen and (min-width: 600px) {
.boxes {
display: table;
width: 100%;
direction: rtl;
}
.boxes button {
display: table-cell;
width: 25%;
}
}
Стоит упомянуть, что если по каким-то причинам мы хотим также изменить направление текста в кнопках, мы можем включить специальное правило для того, чтобы направление символов юникода определялось свойством direction
.
.boxes button {
unicode-bidi: bidi-override;
}
Демо на Codepen:
See the Pen Using `direction` for Reverse Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Метод №4: трансформация
Изящным решением будет оставить кнопкам float: left;
и затем применить transform: scaleX(-1)
к ним и их родителю. Задав отрицательные значения мы сделаем так, что трансформируемый элемент не масштабируется, а переворачивается по горизонтальной оси.
Вот CSS:
@media screen and (min-width: 600px) {
.boxes {
transform: scaleX(-1);
}
.boxes button {
float: left;
transform: scaleX(-1);
width: 25%;
}
}
Демо на Codepen:
See the Pen Using `transform` (scale) for Reverse Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Мы также можем использовать для создания нужного порядка функцию трансформации rotate
. Все, что нам надо добавить кнопкам и их родителю свойство transform: rotateY(180deg)
.
CSS для этого решения:
@media screen and (min-width: 600px) {
.boxes {
transform: rotateY(180deg);
}
.boxes button {
float: left;
transform: rotateY(180deg);
width: 25%;
}
}
Демо на Codepen:
See the Pen Using `transform` (rotate) for Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Метод №5: флексбокс
Флексбокс это еще один способ изменения порядка колонок. В нашем примере мы используем два разных свойства флексбокса для создания нашей раскладки.
Первый подход это сделать родительский элемент кнопок флекс-контейнером и затем добавить flex-direction: row-reverse
, вот так:
@media screen and (min-width: 600px) {
.boxes {
display: flex;
flex-direction: row-reverse;
}
}
Демо на Codepen:
See the Pen Using `flexbox` (flex-direction) for Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Второй вариант с флексбоксом состоит в использовании свойства order
для определения порядка, в котором кнопки должны выводиться.
@media screen and (min-width: 600px) {
.boxes {
display: flex;
}
.boxes button:nth-of-type(1) {
order: 4;
}
.boxes button:nth-of-type(2) {
order: 3;
}
.boxes button:nth-of-type(3) {
order: 2;
}
.boxes button:nth-of-type(4) {
order: 1;
}
}
Демо на Codepen:
See the Pen Using `flexbox` (order) for Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Метод №6: грид-раскладка
Многообещающим решением для расстановки элементов является раскладка на основе CSS Grid. Несмотря на крайне ограниченную поддержку в браузерах на момент написания статьи ее стоит попробовать. Учитывайте, что наш пример будет работать только в Chrome (по умолчанию эта возможность отключена, но ее легко активировать).
Не погружаясь глубоко в детали я опишу два способа с использованием CSS Grid.
Первый вариант это задание родительскому элементу кнопок свойства display: grid;
и использование свойства grid-column
для определения порядка вывода кнопок. В дополнение мы обеспечим попадание всех кнопок в один ряд путем прямого указания этого — grid-row: 1
.
@media screen and (min-width: 600px) {
.boxes {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.boxes button {
grid-row: 1;
}
.boxes button:nth-of-type(1) {
grid-column: 4;
}
.boxes button:nth-of-type(2) {
grid-column: 3;
}
.boxes button:nth-of-type(3) {
grid-column: 2;
}
.boxes button:nth-of-type(4) {
grid-column: 1;
}
}
Демо на Codepen:
See the Pen Using CSS `grid` (grid-column) for Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Второй вариант использования CSS Grid похож на второй способ использования флексбокса. Мы зададим контейнеру свойство display: grid;
, а затем используем свойство order
для определения порядка вывода кнопок.
@media screen and (min-width: 600px) {
.boxes {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.boxes button:nth-of-type(1) {
order: 4;
}
.boxes button:nth-of-type(2) {
order: 3;
}
.boxes button:nth-of-type(3) {
order: 2;
}
.boxes button:nth-of-type(4) {
order: 1;
}
}
Демо на Codepen:
See the Pen Using CSS `grid` (order) for Column Ordering by Envato Tuts+ (@tutsplus) on CodePen.
Напомню, что для тестирования этого метода, вам надо активировать “Experimental Web Platform features” в Chrome.
Порядок исходников и визуальный порядок
Как было показано, мы можем использовать различные подходы CSS для смены порядка наших кнопок. Попробуем пройтись по нашим демо, используя клавиатуру (кликните на пен и нажмите клавишу Tab) для навигации по кнопкам. Вы заметите, что даже, если кнопка с номером 4 выведена первой, фокус сначала появляется на кнопке с номером 1, так как она расположена первой в DOM. То же случится, если мы протестируем наши демо со скринридером (я проводил тесты с NVDA).
Учитывая эту независимость порядка CSS от порядка DOM, нам надо быть крайне осторожными с частями страниц, порядок которых мы изменяем с помощью CSS. Например, свойство флексбокса order
это один из наиболее гибких способов для переупорядочения элементов, согласно спецификации:
Авторы должны использовать order только для визуального, а не логического переупорядочивания контента. Попытка использовать order для логического порядка не сработает.
То же самое спецификация говорит о свойстве order
CSS Grid.
Также как и с переупорядочиванием флекс-элементов, свойство order может использоваться только, когда визуальный порядок надо рассинхронизировать с порядком зачитывания и навигации — иначе надо менять исходники документа.
Примечание: если вы используете второй способ с флексбоксом в Firefox, то вы заметите, что навигация с клавиатуры работает отлично и фокус на средних экранах появляется сначала на кнопке №4. Такое поведение является багом.
Заключение
В этой статье мы проверили различные методы CSS для переупорядочивания элементов HTML. Конечно, не все из этих методов универсальны и перед тем, как выбрать нужный вам, вы должны учесть несколько вещей:
- Браузеры, которые вам надо поддерживать. Некоторые из перечисленных подходов не работают в старых версиях Internet Explorer (т.е. < 10).
- Степень сложности перестановки — это может быть что-то простое, как наш пример или что-то более сложное.
Дополнительные материалы
- HTML Source Order vs CSS Display Order от Adrian Roselli
- Flexbox & the keyboard navigation disconnect от Léonie Watson