От автора: в этом уроке мы разберем несколько CSS методов по изменению порядка HTML элементов.
Наша цель
Мы хотим построить очень простой макет, особенно на маленьких экранах (т.е. <600px). Вот так он будет выглядеть:
На средних и больших экранах (т.е. выше или равно 600px) макет должен быть таким:
Самая сложная задача – найти способ перевернуть порядок кнопок.
Разметка
Разметка будет очень простая, обычный div с четырьмя кнопками внутри:
1 2 3 4 5 6 |
<div class="boxes"> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> </div> |
Базовые стили
На маленьких экранах у всех кнопок общие стили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.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 метода, который мы используем для инверсии порядка кнопок.
1 2 3 4 5 6 |
@media screen and (min-width: 600px) { /* в методах с flexbox и сеткой мы пропускаем это свойство */ width: 25%; /* тут код */ } |
Осталось добавить стили кнопкам в состоянии focus:
1 2 3 4 5 |
.boxes button:focus { outline: none; color: #fff; background: firebrick; } |
Если при помощи клавиши Tab перемещаться по кнопкам, кнопка с фокусом изменит цвет на темно-красный.
Методы с изменением порядка колонок
Теперь мы готовы протестировать несколько способов по изменению порядка кнопок на экранах шириной больше 599px.
Метод №1: обтекания
Один из быстрых способов – добавить кнопкам правое обтекание. Дополнительный CSS код:
1 2 3 4 5 6 |
@media screen and (min-width: 600px) { .boxes button { float: right; width: 25%; } } |
Метод №2: позиционирование
Можно спозиционировать элементы, относительно или абсолютно. В первом случае мы сдвигаем все кнопки влево при помощи свойства position: relative и при помощи свойства left выстраиваем их в ряд.Для этого нам нужен следующий CSS код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@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%; } } |
Во втором случае кнопкам можно было бы задать свойство position: absolute и с помощью свойства left более точно настроить их позиционирование.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@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; } } |
Метод №3: свойство direction
Менее очевидный способ – свойство direction. Обычно, в таком случае резервируется некоторое пространство под развернутый текст. В нашем случае мы задаем свойство direction: rtl (справа налево) контейнеру, что мгновенно меняет порядок элементов в макете. Обратите внимание: в этом примере элементам задается поведение ячеек таблицы для того, чтобы выстроить их в один ряд.
1 2 3 4 5 6 7 8 9 10 11 12 |
@media screen and (min-width: 600px) { .boxes { display: table; width: 100%; direction: rtl; } .boxes button { display: table-cell; width: 25%; } } |
Также стоит сказать, что если по каким-либо причинам нам захочется сменить направление текста кнопок, можно использовать специальное правило:
1 2 3 |
.boxes button { unicode-bidi: bidi-override; } |
Метод №4: трансформации
Изящный метод. Кнопкам необходимо добавить левое обтекание и свойство transform: scaleX(-1). Также данное свойство необходимо прописать для родительского блока. Отрицательное значение не увеличивает элементы. На самом деле, они просто отражаются по горизонтальной оси.
1 2 3 4 5 6 7 8 9 10 11 |
@media screen and (min-width: 600px) { .boxes { transform: scaleX(-1); } .boxes button { float: left; transform: scaleX(-1); width: 25%; } } |
Для достижения нужного эффекта можно даже использовать функцию трансформации rotate. Нужно всего лишь добавить свойство transform: rotateY(180deg) к кнопкам и родительскому блоку.
1 2 3 4 5 6 7 8 9 10 11 |
@media screen and (min-width: 600px) { .boxes { transform: rotateY(180deg); } .boxes button { float: left; transform: rotateY(180deg); width: 25%; } } |
Метод №5: flexbox
Изменить порядок колонок можно и с помощью flexbox. В нашем случае мы можем воспользоваться двумя свойствами flexbox для достижения необходимого эффекта. В первом случае родительский блок кнопок необходимо превратить в флекс контейнер и добавить к нему свойство flex-direction: row-reverse.
1 2 3 4 5 6 |
@media screen and (min-width: 600px) { .boxes { display: flex; flex-direction: row-reverse; } } |
Второй способ – превратить родительский блок в флекс контейнер и с помощью свойство order задавать порядок кнопок.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@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; } } |
Метод №6: CSS сетка
CSS сетка – один из самых лучших способов изменения порядка элементов. Несмотря на скудную поддержку в браузерах на момент написания статьи, давайте попробуем данный способ. Данный пример будет работать только в Chrome, в котором необходимое CSS свойство по умолчанию не поддерживается. Однако при помощи простых шагов мы можем активировать это свойство.
Не вдаваясь в детали, давайте разберем два способа. Первый способ – превратить родительский блок в grid-контейнер и с помощью свойства grid-column задавать порядок расположения кнопок. Также мы добавим свойство grid-row: 1, чтобы все кнопки были на одном ряду.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@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; } } |
Второй способ с сетками похож на второй способ с flexbox. Необходимо превратить родительский блок в grid-контейнер и с помощью свойства order задавать порядок отображения кнопок.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@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; } } |
Данное демо работает только с включенным флагом «Experimental Web Platform features» в Chrome.
Исходный порядок или визуальный порядок
Мы показали, что изменить порядок следования кнопок можно разными CSS способами. Давайте еще раз взглянем на все демо и с помощью клавиатуры пройдемся по кнопкам (при помощи клавиши Tab). Вы заметите, что даже если кнопка 4 визуально стоит первой, то первой получит фокус кнопка 1, так как она расположена первой в DOM. То же самое будет, если протестировать демо в скрин ридерах (я тестировал в NVDA).
Учитывая разницу между порядком в DOM и CSS, необходимо крайне осторожно работать с частями сайта, которые были перестроены при помощи CSS. К примеру, flexbox свойство order одно из самых гибких для изменения порядка отображения элементов, однако в спецификации говорится: «Редакторы должны использовать свойство order только для визуального, не логического изменения порядка контента. Стили, в которых свойство order используется для логического изменения порядка, неприемлемы.»
То же самое говорится в спецификации и про свойство order в сетках: «При изменении порядка флекс элементов свойство order должно использоваться только в случаях, когда визуальный порядок не должен совпадать с порядком чтения текста скрин ридерами и порядком меню. В противном случае документ должен быть перестроен.»
Обратите внимание: если вы тестировали второй способ с flexbox в браузере Firefox, вы могли заметить, что навигация с клавиатурой работает, но на средних экранах первый фокус получает кнопка 4. Это баг.
Заключение
В этом уроке мы рассмотрели разные CSS методы по изменению порядка отображения HTML элементов. Не все методы подходят на все случаи. Перед выбором нужно учесть:
Какие браузеры вы будете поддерживать. К примеру, некоторые из вышеупомянутых способов не работают в старых версиях IE (<10).
Сложность перестроения. Перестроение будет простым, как в наших примерах, или что-то посложнее?
Если вы знаете другие методы по изменению порядка кнопок, пишите о них в комментариях.
Редакция: George Martsoukos
Источник: //webdesign.tutsplus.com/
Редакция: Команда webformyself.