Русский
Русский
English
Статистика
Реклама

Flexbox

Из песочницы Еще раз о визуализации input типа checkbox и radio. Для тех, кто забыл как

15.07.2020 14:22:53 | Автор: admin
Тема старая и уже, как выяснилось, подзабытая.

Недавно у меня была короткая работа по разработке ТЗ на модернизацию давно существующего проекта. И, в частности дело касалось стилизации пресловутых <input type="checkbox">. Выяснилось, что исполнитель, программист на все руки даже не понял, что я ему на словах объяснял как это сделать. Пришлось делать примеры и, как результат, появился этот текст.

Напомню, что сейчас checkbox и radiobox разные сайты изображают по-разному. Бывает, что не отмеченный input сразу и не разглядишь такой он дизайнерский красивый, а у последних версий Chrome выбранные checkbox стали гнусного цвета циан.

Итак, ситуация


Есть три компании, которые используют некий программный продукт, связанный с заказами, бухгалтерией, складом и пр. Работа с заказчиками, партнерами, исполнителями и пр.

Маркетологи и рекламщики тоже его используют. Что эта система делает неважно, на чем написано неважно.

А важно, что на сайте этого продукта есть много страниц с формами, на которых много input checkbox и radio.

Жалобы сотрудников


Директор: На большом экране плохо видно и незаметны крыжики.
Главбух: На моем компе крыжики выглядят так, у сотрудниц иначе, дома тоже не так, а на планшете совсем иначе.
Маркетолог: А можно, так что бы некоторые не выбранные позиции были красными, а другие выбранные были зелеными?
И т.д., и т.п.

Итак, задача


  1. Минимальными затратами и минимальными изменениями исправить внешний вид checkbox и radiobox.
  2. Сделать стилизацию checkbox и radiobox для разных юзеров. Важно: это закрытый сайт, там всё свои, красоты не нужны, а нужна эффективность восприятия.

Что нельзя


1. Серверную часть трогать нельзя.
2. Файлы javascript трогать нельзя, свой javascript вставлять нельзя.
3. Файлы css трогать нельзя.

А что можно


1. Править html шаблоны.
2. Создать файл стилей для всех юзеров.
4. Создать файл стилей для конкретного юзера или группы юзеров.
А что сделали можно сразу посмотреть на codepen.io, но лучше почитать дальше.

Предварительное изучение показало


1. Почти все <input type="checkbox"> имеют поле name, а которые не имеют, то у них есть id.
2. Все <input type="radio"> имеют поле name, некоторые имеют id.
3. Соответственно, в css к checkbox можно обращаться как по id, так и по name. К radio или по id, или по номеру потомка у родителя.

Фрагменты исходного кода:

/* вариант 1 */<tag><input type="checkbox"> Некий текст</tag>/* вариант 2 */<tag><input type="checkbox"> Некий текст<br><input type="checkbox"> Некий текст</tag>/* вариант 3 */...<label><input type="checkbox"> Некий текст</label>.../* вариант 4 */<td><input id="idxxx" type="checkbox"></td><td><label for="idxxx">Некий текст</label></td>

Так исправим код:

/* вариант 1 */<tag><label class="new-input"><input type="checkbox"><s></s><span>Некий текст</span></label></tag>/* вариант 2 */<tag><label class="new-input"><input type="checkbox"><s></s><span>Некий текст</span></label><br>...</tag>/* вариант 3 */...<label class="new-input"><input type="checkbox"><s></s><span>Некий текст</span></label>.../* вариант 4 */<td><label class="new-input new-input-one"><input id="idxxx" type="checkbox"><s></s></label></td><td><label for="idxxx">Некий текст</label></td>

Всё тоже самое и для <input type="radio">, класс у LABEL тот же.

Что конкретно сделали?


  1. Каждый input (корме варианта 3) обернули тэгом LABEL с нашим классом. Варианту 3 просто добавили класс.
  2. Сразу после input вставили пустой тэг S. Так как сам input будет не видим, то это тэг будет визуализировать это input.
  3. Сопроводительный текст обернули тэгом SPAN (кроме варианта 4). Этот тэг понадобиться, когда будем решать вопрос выравнивания визуального input относительно этого текста.
  4. Варианту 4 добавили еще класс, что бы не осуществлять это выравнивание, раз сопроводительный текст стоит в другой ячейки таблицы. Строго говоря, надо было бы сделать на оборот вариантам 1-3 добавить класс, отвечающий за выравнивание. Но, вариантов 1-3 гораздо больше, чем 4-го и что бы не раздувать html сделано так.

Риторические вопросы и риторические же ответы
1. Зачем тэг S? Ну, не нравится S можно использовать любой другой строчный элемент. Просто он должен быть, его можно стилизовать в зависимости от состояния предшествующего input.

2. Почему тэги S и SPAN без классов? Ну, зачем раздувать html? Тем более, что не очевидно, что одна из конструкций ниже будет работать медленнее другой.

  .new-input > S { }  .new-input > .new-input-S {}

3. Как вы догадались, мне не нравятся идеи БЭМ, тем более идея раздувать html файл обилием упоминаний разных классов. В реальном проекте мы использовали только два класса mni и mnio. :-))

Некоторые предварительные рассуждения и настройки css касательно box-sizing:border-box, нормализации LABEL, селекторов A + B, A ~ B и [attr], псевдоклассов :checked, :disabled и ::before. Кто не уверен, что знает или хочет освежить знания смотрит под катом.

Предварительные рассуждения
1. Напомню, что в старом css (box-sizing:content-box) свойства width и height задают только ширину и высоту содержимого, а padding и border добавляются к этим значениям. box-sizing:border-box меняет схему так, что padding и border включаются в width и height.

2. Проверка показала, что в нашем случае используется старая модель, а менять настройки страниц запрещено. Не наши LABEL это простые строчные элементы, в них только текст. Поэтому стилизуем ВСЕ LABEL.

LABEL {    box-sizing:border-box; cursor:pointer; user-select:none;}LABEL *,LABEL *::before,LABEL *::after {    box-sizing:inherit;}

Т.е., ставим box-sizing:border-box для тэга LABEL, всем его потомкам. Заодно ставим курсор и запрещаем выделение текст (что бы не мешало клику).

3. Комбинация селекторов A + B означает, что стили будут применяться только к селектору B, если он следует сразу ПОСЛЕ селектора A, т.е. только для первого B. С другой стороны, A ~ B означает, что ко всем селекторам B после селектора A, т.е. для первого и последующих.
Естественно, всё в пределах одного родителя.

Как это будем использовать?

<label class="new-input"><input type="checkbox"><s></s><span>Некий текст</span></label><label class="new-input"><input type="radio"><s></s><span>Некий текст</span></label>

/* 1 */.new-input > INPUT + S {}.new-input > INPUT ~ SPAN {}/* 2 */.new-input > INPUT:not(:checked) + S {}.new-input > INPUT:not(:checked) ~ SPAN {}/* 3 */.new-input > INPUT:checked + S {}.new-input > INPUT:checked ~ SPAN {}/* 4 */.new-input > INPUT:disabled + S {}.new-input > INPUT:disabled ~ SPAN {}/* 5 */.new-input > INPUT[type="radio"] + S {}

Первая группа общие стили для тэгов S и SPAN.
Вторая группа стили только когда INPUT НЕ выбран.
Третья стили только когда INPUT выбран.
Четвертая когда INPUT заблокирован.

И, наконец, пятая группа общие стили для тэга S ТОЛЬКО, если он стоит после input radio.
Таким образом, можно изменять стили тэгов S и SPAN в зависимости от состояния input.

4. Поскольку у нас тэг S будет изображать из себя input, то самому input поставим display:none, его не будет видно, а тэг LABEL будет его переключать, а тэг S будет соответственно меняться. Почему не используем html свойство hidden у input? Потому, что на некоторых браузерах hidden у input работает не совсем верно, плюс не будем перегружать html файл.

Итак, начинаем визуализацию input


Пример N 1. Самый простой используем алфавитные символы
html код тот же, а css будет такой:

/* s1 */.new-input > INPUT + S::before {  content: "c";}/* s2 */.new-input > INPUT:checked + S::before {  content: "V";}/* s3 */.new-input > INPUT[type="radio"] + S::before {  content: "r";}/* s4 */.new-input > INPUT[type="radio"]:checked + S::before {  content: "X";}/* s5 */.new-input > INPUT:disabled + S::before {  opacity: 0.5;}/* s6 */.new-input > S {  text-decoration: none;  margin-left: 3px;  margin-right: 6px;}/* s7 */.new-input > S::before {  display: inline-block;  width: 1.25em;  text-align: center;  color: #fafafa;  background-color: #37474f;}/* s8 */.new-input > INPUT[type="radio"] + S::before {  border-radius: 50%;}

Тэг S буде визуализировать input. Но мы разделим его по функционалу: сам тэг S будет отвечать за размещение в LABEL и выравнивание относительно следующего SPAN.

А псевдоэлемент S::before разместится внутри тэга S и будет изображать из себя input.

Строка s1 определяет, какой символ будет помещен в S::before когда input не выбран. В принципе надо было бы написать .new-input > INPUT:not(:checked) + S::before, но некоторые браузеры (например, IE), подобную конструкцию могут и не исполнить.
Строка s2 определяет символ, когда input выбран.
Строки s3 и s4 делают то же для input radio.
Строка s5 описывает, что будет если input заблокирован в данном случае тэг S будет наполовину прозрачным.
Строка s6 определяет выравнивание, в данном случае дает отбивку слева и справа (только в этом примере). Плюс, убирает штатное перечеркивание.
Строка s7 делает квадратик, s8 превращает его в кружок для input radio.

Пример N 1 можно посмотреть на codepen.io. Там представлены нативные input и новые. Первые можно убрать.

Чуток подробнее про display: inline-block, font-size, line-height
Конченая высота строки текста определяется на основе заданных font-size, line-height. При единичном line-height высота будет по font-size, при числовом line-height высота будет по их произведению или, при указании единиц измерения для line-height высоту определит максимальное значение. В примере указан line-height:1.25, поэтому и у S::before указано width:1.25em.

Для S::before указано display: inline-block в этом случае S::before внутри себя будет блоком (можно указать ширину, высоту, рамки и пр.), а снаружи он останется строчным элементом. В дальнейшем об этом будет подробнее.


Вопрос:

Может можно использовать специальные символы? Типа вот этих:

Задать им нужный размер и всё. Нет?

Ответ:

Можно. Но не нужно. Ибо будет большой геморрой и танцы с бубнами по заданию нужного размера, выравнивания по вертикали, обрезке по высоте и прочее. Плюс, разные браузеры с этими символами работают по-разному.
Мы пошли другим путем. Хотя в финальном примере есть реализация этой идеи.

Пример N 2. Рисуем элементы input средствами css

html код тот же, а css будет такой:

/* s1 */.new-input > S::before {  content: "";  display: inline-block;  width: 0.75em;  height: 0.75em;  border: 1px solid currentColor;  padding: 2px;  background-clip: content-box;  border-radius: 20%;}/* s2 */.new-input > INPUT[type="radio"] + S::before {  border-radius: 50%;}/* s3 */.new-input > INPUT:checked + S::before {  background-color: currentColor;}/* s4 */.new-input > INPUT:disabled + S::before {  opacity: 0.5;}/* s5 */.new-input > S {  text-decoration: none;  margin-left: 3px;  margin-right: 6px;}

Строка s1 определяет S::before для визуализации input. Это будет inline-block, ширина и высота которого установлена в 0.75em, что примерно равно высоте прописной буквы и зависит от font-size родителя. Задана тонкая рамка текущим цветом, внутренняя отбивка, небольшое скругление углов. И самое важное! установлено свойство background-clip:content-box. Это очень интересное свойство если будет установлен background-color, то он закрасит только контентную часть и не затронет отбивку (padding). Что нам и надо.

Строка s2 для input типа radio делает S::before круглым.
Строка s3 для отмеченного input устанавливает для S::before background-color текущим цветом. Т.е., рисует внутри квадратик или кружок.
Строка s4 отрабатывает блокировку input, строка s5 дает отбивки слева и справа.

Преимущества этого метода

  1. Всё очень просто. Работает на всех браузерах. Даже у IE10 (в эмуляции у 11-го).
  2. Можно раскрашивать по своему усмотрению.
  3. Раз S::before это inline-block, то он сидит на попе базовой линии ровно и никуда с нее не слезает. Если он по высоте будет больше текста, то просто увеличит высоту строки и останется на базовой линии.
  4. Раз визуализация input находится внутри тэга S, то его можно легко позиционировать и выравнивать.
  5. Размеры S::before в em дают возможность задавать его размер относительно размера текста подписи. Можно, к примеру, поставить предельные значения высоты и ширины.

Недостатки этого метода

В основном в использовании размеров в em. Дело в том, что может возникнуть ситуация когда ширина и высота при расчете (из em в px) будет иметь дробное значение. На обычных компьютерах с обычным экраном округление может произойти не корректно. Например, размеры 12.8px на 12.8px у той же Мозилы могут стать как 13px на 12px. Тогда надо ставить фиксированные размеры. Хотя на современных мониторах и видеокартах, ноутбуках, на планшетах и смартфонах этого не происходит из-за того, что точка (пиксель) браузера состоит из нескольких пикселей экрана.

Пример N 2 можно посмотреть на codepen.io. Там представлены нативные input и новые. Первые можно убрать.
Итак, первую задачу визуализацию input выполнили. Переходим к избранной раскраске.

Раскрашиваем input


html для примера:

<label class="new-input"><input name="chb1" type="checkbox" ...><s></s><span>Некий текст</span></label><label class="new-input"><input id="rb1" type="radio" ...><s></s><span>Некий текст</span></label>

К input типа checkbox будем обращаться по name, к radio по id.

Всё красим в синий

/* только input */.new-input > INPUT[name="chb1"] + S,.new-input > INPUT#rb1 + S {  color: #0091ea;}/* только text */.new-input > INPUT[name="chb1"] ~ SPAN,.new-input > INPUT#rb1 ~ SPAN {  color: #0091ea;}/* или всё */.new-input > INPUT[name="chb1"] ~ *,.new-input > INPUT#rb1 ~ * {  color: #0091ea;}

Помним о специфичности в css, эти стили будут более специфичны, чем базовые и сработают обязательно. Чем они отличаются от описанных выше? Тем, что применяются только к избранным input к тем, что имеет указанное значение name и id.

Тут всё хорошо кроме того, что не выбранные input будут не очень хорошо глядеться тонкая синяя рамка мало заметна.

Красим в зеленый, когда input выбран

/* только input */.new-input > INPUT[name="chb1"]:checked + S,.new-input > INPUT#rb1:checked + S {  color: #00c853;}/* только text */.new-input > INPUT[name="chb1"]:checked ~ SPAN,.new-input > INPUT#rb1:checked ~ SPAN {  color: #00c853;}/* или всё */.new-input > INPUT[name="chb1"]:checked ~ *,.new-input > INPUT#rb1:checked ~ * {  color: #00c853;}

Первый вариант, на мой взгляд, не очень хорош зеленым будут и рамка, и внутренний квадратик/кружок. Можно раскрасить только его.

/* только input и только внутри */.new-input > INPUT[name="chb1"]:checked + S::before,.new-input > INPUT#rb1:checked + S::before {  background-color: #00c853;}

Красим в красный, когда input НЕ выбран

/* только input */.new-input > INPUT[name="chb1"]:not(:checked) + S,.new-input > INPUT#rb1:not(:checked) + S {  color: #d50000;}/* только text */.new-input > INPUT[name="chb1"]:not(:checked) ~ SPAN,.new-input > INPUT#rb1:not(:checked) ~ SPAN {  color: #d50000;}/* или всё */.new-input > INPUT[name="chb1"]:not(:checked) ~ *,.new-input > INPUT#rb1:not(:checked) ~ * {  color: #d50000;}

Логика понятна? Можно и дальше делать более сложные конструкции.

Например, при не выбранном input текст должен быть красным и жирным, а при выбранном внутренний элемент input и текст должен быть зеленым. Элементарно!

/* текст, когда нет выбора */.new-input > INPUT[name="chb1"]:not(:checked) ~ SPAN,.new-input > INPUT#rb1:not(:checked) ~ SPAN {  color: #d50000;  font-weight: bold;}/* внутренний элемент input, когда выбран */ .new-input > INPUT[name="chb1"]:checked + S::before,.new-input > INPUT#rb1:checked + S::before {  background-color: #00c853;}/* текст, когда выбран */ .new-input > INPUT[name="chb1"]:checked ~ SPAN,.new-input > INPUT#rb1:checked ~ SPAN {  color: #00c853;}

А, к примеру, надо обработать целую группу input (10-15 штук). Что бы не писать кучу строк можно найти их общего родителя (.parent_element) и сократить условие.

.parent_element > .new-input > INPUT:not(:checked) ~ SPAN {  color: #d50000;  font-weight: bold;}.parent_element > .new-input > INPUT:checked + S::before {  background-color: #00c853;}.parent_element > .new-input > INPUT:checked ~ SPAN {  color: #00c853;}

Всё можно посмотреть в финальном примере на codepen.io

Вот, вроде как, и всё. Осталось только почесать родимые пятна перфекциониста проблемы выравнивания.

Выравнивание визуального input и сопроводительного текста


Для начала напомню общеизвестные вещи на тему размещения текста, форматирования и прочего. Всё под катом.

Общеизвестные вещи
Буду стараться не применят специальные термины, ибо в дизайне, верстке и css они иногда отличаются. Всё простыми словами.

1. Свойство font-size не определяет размер букв, а только размер знакоместа. Есть базовая линия (baseline), по которой расположены нормальные буквы. У ненормальных g ц нижние элементы свисают ниже её. Есть линия капители (cap height) это верхняя граница нормальной прописной (заглавной) буквы. У ненормальных Ё Й верхние элементы вылезают выше её. Иными словами, размер прописной буквы это расстояние от базовой линии до капители, а знакоместо это чуть больше сверху и снизу. Обычно в нормальных шрифтах высота капители это 75% от высоты знакоместо. К примеру, font-size:16px, а размер буквы Н у шрифта Arial будет 12px. Но, бывают специалисты у шрифтов которых всё не так.

2. Свойство line-height определяет высоту строки. Если его вычисленное значение больше, чем указано в font-size, то браузер разместит текст так, что бы нормальная прописная буква была по середине высоты строки. Есть нюансы, но тут они не важны.

3. Соответственно, в нашем случае тэги S и SPAN должны иметь одинаковые значения font-size и line-height желательно заданные где-то выше у родителей. В нашем случае в примерах font-size:16px и line-height:1.25. Поэтому в примере N1 у S::before ширина указана 1.25em, а высота у него определяется автоматически. А в примере N2 (и финальный пример) у S::before ширина и высота 0.75em, что бы был по высоте с прописную букву. Задав другое значение font-size ничего менять не надо. Естественно, эту величину надо подогнать под конкретный шрифт.

4. Если перед текстом стоит какая-то квадратная или круглая штучка, то любой дизайнер скажет, что она должна быть по высоте с прописную букву. А отбивка между ними должна быть в определенных процентах от размера шрифта. Если высота меньше высоты буквы, то она должна быть визуально значительно меньше, но не меньше 50%. Если больше, то тоже визуально значительно больше, но не больше 150%. А вот чуть-чуть, на пару пикселей больше/меньше это ужас-ужас! Ну, и расположена эта штучка должна быть на базовой линии или по середине без всяких там чуть-чуть.

Зачем я это упомянул? А затем, что перфекционисту глаза режет, когда input криво стоит рядом с текстом или прилипает, или далеко, или чуть меньше, или чуть больше. Мы так делать не должны!

Что будет, если сопроводительный текст в SPAN будет выведен в две или три строки? Очевидно, что он залезет под input. Это не красиво, надо исправить.

Один древний метод такой: тэгу S делаем float:left, а тэгу SPAN display:block и overflow:hidden.

Получится колонка текста. Подразумевается, что у кого-то из них будет соответствующий margin, что даст отбивку между ними. Ну, ещё добавляется геморрой с прекращением float после SPAN. Мы пойдем современным путем применим flexbox. Он тут совершенно к месту.

.new-input {  display: flex;  flex-direction: row;  align-items: start;}.new-input > S {  margin-right: 4px;  flex: 0 0 auto;}.new-input > SPAN {  flex: 0 1 auto;}

В этом случае тэг LABEL (который .new-input) будет flex, S и SPAN будут блоками, разместятся вверху LABEL. Текст в SPAN в случае необходимости будет в несколько строк. Вот из-за этого визуальный input описали в S::before. Независимо от высоты SPAN S::before будет расположен на одной базовой линии с первой строкой SPAN. Как вариант можно было указать align-items:center тогда при однострочном SPAN визуальный input был бы вверху, а при двух строках посередине, а при трех у второй строки. В финальном примере можно переключать расположение input.

Вот и всё


Надеюсь, было интересно и кому-нибудь полезно. Прошу, не сильно меня ругать это мой первый опыт на Хабр.

Пример N 1 просто демонстрация взаимодействия изменения input и соседнего элемента.

Пример N 2 визуализация input средствами css, как основа решения.

Финальный пример всё описанное вместе.

Про конкретную реализацию


Там были обширные формы, где блоки полей возможные для правки конкретным пользователям выделялись слабым фоном, а остальным input имели свойство disabled и служили только для информации. Поэтому стиль .new-input > INPUT:disabled + S::before не применяли.
Подробнее..

Полное визуальное руководство-шпаргалка по Flexbox и Grid туториал

18.11.2020 14:04:51 | Автор: admin


Доброго времени суток, друзья!

Представляю вашему вниманию полное визуальное руководство-шпаргалку по всем свойствам CSS-модулей Flexbox и Grid.

Основные источники: A Complete Guide to Flexbox, A Complete Guide to Grid.

В конце статьи вас ждет небольшой туториал по созданию тренажера по Flexbox.

Без дальнейших предисловий.



Flexbox (Flex, далее по тексту Флекс)


Терминология


Флекс это не отдельное свойство, но целый модуль, включающий набор свойств. Некоторые из этих свойств добавляются к контейнеру (родительскому элементу, известному как флекс-контейнер (flex container, далее по тексту контейнер)), другие к дочерним элементам (известным как флекс-элементы (flex items, далее по тексту элементы)).

Обычный макет основан на потоке из блочных и строчных элементов, а флекс-макет на флекс-потоке (flex-flow directions). Посмотрите на это изображение из спецификации, демонстрирующее ключевые идеи, лежащие в основе флекс-макета.



Элементы располагаются вдоль основной (главной) оси (main axis) (от main-start до main-end) или вдоль поперечной оси (cross axis) (от cross-start до cross-end).

  • основная ось главная ось контейнера, ось, вдоль которой располагаются элементы. Она не обязательно является горизонтальной; это зависит от свойства flex-direction (направление, см. ниже)
  • main-start | main-end элементы располагаются в контейнере от main-start до main-end
  • основной размер (main size) ширина или высота элемента в зависимости от основного измерения (main dimension), основной размер элемента
  • поперечная ось ось, перпендикулярная основной. Ее направление зависит от направления основной оси
  • cross-start | cross-end строки контейнера заполняются элементами, которые располагаются от cross-end до cross-start
  • поперечный размер (cross size) ширина или высота элемента в зависимости от основного измерения



Свойства флекс-контейнера


display

Данное свойство определяет флекс-контейнер; блочный или строчный в зависимости от присвоенного значения. Оно включает флекс-контекст для всех прямых потомков контейнера.

.container {  display: flex; /* или inline-flex */}

Обратите внимание, что свойства CSS-колонок в контейнере не работают.

flex-direction (направление)



Данное свойство определяет основную ось, направление, по которому размещаются элементы в контейнере. Флекс сам по себе (без расширяющих его функционал оберток) реализует концепцию однонаправленного макета. Поэтому элементы размещаются либо в горизональных строках, либо в вертикальных колонках.

.container {  flex-direction: row | row-reverse | column | column-reverse;}

  • row (по умолчанию): элементы располагаются слева направо в ltr или справа налево в rtl
  • row-reverse: обратный row порядок расположения элементов справа налево в ltr или слева направо в rtl
  • column: аналогично row, но сверху вниз
  • column-reverse: аналогично row-reverse, но снизу вверх

flex-wrap (перенос, переход, разделение)



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

.container {  flex-wrap: nowrap | wrap | wrap-reverse;}

  • nowrap (по умолчанию): все элементы располагаются на одной строке
  • wrap: элементы могут располагаться на нескольких строках сверху вниз
  • wrap-reverse: элементы могут располагаться на нескольких строках снизу вверх

flex-flow (поток)

Данное свойство является сокращением для flex-direction и flex-wrap, которые определяют основную и поперечную оси контейнера. Значением по умолчанию является row nowrap.

.container {  flex-flow: column wrap;}

justify-content (выравнивание контента в одной строке)



Данное свойство определяет выравнивание элементов вдоль основной оси. Оно позволяет распределять свободное пространство, оставшееся неиспользованным элементами с фиксированным размером или гибкими элементами, достигшими максимального размера. Оно также позволяет управлять выравниванием при переполнении строки элементами.

.container {  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;}

  • flex-start (по умолчанию): элементы сдвигаются в начало контейнера вдоль основной оси
  • flex-end: элементы сдвигаются в конец контейнера
  • start: элементы сдвигаются в начало контейнера, определяемое значением свойства writing-mode (направление письма)
  • end: элементы сдвигаются в конец контейнера, определяемый значением свойства writing-mode
  • left: элементы прижимаются к левому краю контейнера; без flex-direction поведение аналогично start
  • right: элементы прижимаются к правому краю контейнера; без flex-direction поведение аналогично start
  • center: элементы выравниваются по центру
  • space-between: элементы выравниваются таким образом, что первый элемент находится в начале строки, последний в конце, а остальные элементы равномерно распределяются по оставшемуся пространству
  • space-around: элементы равномерно распределяются с одинаковым пространством по краям. Обратите внимание, что визуально пространство между элементами и краями контейнера не является одинаковым; это объясняется тем, что элементы занимают определенное пространство по обеим сторонам. Первый элемент занимает одну часть пространства от края контейнера, но две части до второго элемента, поскольку второй элемент также занимает одну часть пространства со стороны первого элемента
  • space-evenly: элементы размещаются таким образом, чтобы пространство между любыми двумя элементами являлось одинаковым

Обратите внимание, что поддержка перечисленных свойств разными браузерами различается. Самыми безопасными являются flex-start, flex-end и center.

Что касается дополнительных ключевых слов safe и unsafe, то использование safe позволяет избежать отрисовки элементов за пределами страницы, независимо от позиционирования, что, в свою очередь, исключает возможность появления прокрутки.

align-items (выравнивание элементов)



Данное свойство определяет, как элементы располагаются вдоль поперечной оси. Его можно сравнить с justify-content применительно к поперечной оси (перпендикулярной основной).

.container {  align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;}

  • stretch (по умолчанию): элементы растягиваются, чтобы заполнить весь контейнер (зависит от их min-width/max-width)
  • flex-start / start / self-start: элементы смещаются к началу поперечной оси. Различия между указанными свойствами несущественны и зависят от flex-direction или writing-mode
  • flex-end / end / self-end: элементы смещаются в конец поперечной оси. Различия между указанными свойствами несущественны и зависят от flex-direction или writing-mode
  • center: элементы выравниваются по центру
  • baseline: элементы выравниваются вдоль их основной линии

Ключевые слова-модификаторы safe и unsafe могут использоваться в качестве дополнительных настроек, позволяющих избежать такого выравнивания элементов, которое сделает контент недоступным (недосягаемым, находящимся за пределами страницы).

align-content (выравнивание содержимого в нескольких строках)



Данное свойство определяет выравнивание строк контейнера при наличии свободного пространство вдоль поперечной оси. Оно похоже на justify-content, которое распределяет пространство между отдельными элементами вдоль основной оси.

Обратите внимание, что рассматриваемое свойство применяется только в отношении содержимого контейнера, располагающегося на нескольких строках, когда свойство flex-wrap установлено в значение wrap или wrap-reverse. В отношении однострочного контейнера (когда свойство flex-wrap имеет стандартное значение no-wrap) применение align-content не будет иметь никакого эффекта.

.container {  align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;}

  • normal (по умолчанию): строки находится на обычных позициях
  • flex-start / start: строки сдвигаются в начало контейнера. flex-start зависит от flex-direction, а start от writing-mode
  • flex-end / end: строки сдвигаются в конец контейнера. flex-end зависит от flex-direction, а end от writing-mode
  • center: строки выравниваются по центру
  • space-between: строки располагаются таким образом, что первая строка находится в начале контейнера, последняя в конце, а остальные строки распределяются равномерно
  • space-around: строки располагаются с одинаковым пространством между ними
  • space-evenly: строки располагаются с одинаковым пространством вокруг каждой из них
  • stretch: строки растягиваются, занимая все доступное пространство

Ключевые слова-модификаторы safe и unsafe могут использоваться в качестве дополнительных настроек, позволяющих избежать такого выравнивания элементов, которое сделает контент недоступным (недосягаемым, находящимся за пределами страницы).



Свойства флекс-элементов


order (порядок)



По умолчанию, элементы располагаются в контейнере в том порядке, в котором указаны в разметке. Данное свойство позволяет этим управлять.

.item {  order: 5; /* по умолчанию равняется 0 */}

flex-grow (рост, расширение)



Данное свойство определяет способность элемента к расширению при необходимости. Оно принимает целочисленное значение, которое выступает в качестве пропорции. Пропорция определяет, какое количество доступного пространства в контейнере может занимать элемент.

Если все элементы имеют свойство flex-grow со значением 1, доступное пространство будет между ними распределяться равномерно. Если значением flex-grow одного из элементов является 2, данный элемент будет занимать двойную порцию пространства по сравнению с остальными элементами (или, по крайней мере, попытается это сделать).

.item {  flex-grow: 4; /* по умолчанию 0 */}

Отрицательные значения невалидны.

flex-shrink (сжатие, сокращение)

Данное свойство определяет способность элемента к сжатию при необходимости.

.item {  flex-shrink: 3; /* по умолчанию 1 */}

Отрицательные значения невалидны.

flex-basis

Данное свойство определяет стандартный размер элемента перед распределением оставшегося пространства. Этим размером может быть длина (например, 20%, 5rem и т.д.) или ключевое слово. Ключевое слово auto означает использование значения свойства width или height элемента (раньше вместо auto использовалось main-size). Ключевое слово content означает учет содержимого элемента. Указанное ключевое слово пока плохо поддерживается, поэтому сложно определить разницу между min-content, max-content и fit-content.

.item {  flex-basis:  | auto; /* по умолчанию auto */}

Если значением этого свойства является 0, окружающее элемента пространство не принимается в расчет. Если значением является auto, доступное пространство распределяется согласно значению свойства flex-grow.

flex

Данное свойство является сокращением для flex-grow, flex-shrink и flex-basis. Второй и третий параметры (flex-shrink и flex-basis) являются опциональными. Значением по умолчанию является 0 1 auto, при этом auto можно опустить.

.item {  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]}

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

align-selt (выравнивание отдельного элемента)



Данное свойство позволяет перезаписывать дефолтное или установленное с помощью align-self выравнивание отдельного элемента.

См. объяснение align-items для доступных значений.

.item {  align-self: auto | flex-start | flex-end | center | baseline | stretch;}

Обратите внимание, что float, clear и vertical-align применительно к флекс-элементу не имеют никакого эффекта.

Примеры


Начнем с очень простого примера решения проблемы выравнивания элемента по центру.

.parent {  display: flex;  height: 300px; /* Или любое другое значение */}.child {  width: 100px;  /* Или любое другое значение */  height: 100px; /* Или любое другое значение */  margin: auto;  /* Волшебство! */}

Это работает благодарю тому, что свойство margin со значением auto поглащает все доступное пространство флекс-контейнера. Поэтому установка значения вертикальных внешних отступов в auto приводит к идеальному центрированию элемента по обеим осям.

Теперь попробуем использовать больше свойств. У нас имеется 6 элементов фиксированного размера, способных перестраиваться в зависимости от ширины экрана без участия медиа-запросов. Мы хотим, чтобы доступное пространство основной оси распределялось между элементами равномерно.

.flex-container {  /* Сначала мы создаем контекст флекс-макета */  display: flex;  /* Затем мы определяем направление потока,    позволяя элементам переходить на следующую строку при необходимости   * Указанное свойство и его значения аналогичны следующему:   * flex-direction: row;   * flex-wrap: wrap;   */  flex-flow: row wrap;  /* Наконец, мы определяем, как должно распределяться оставшееся пространство */  justify-content: space-around;}

Готово. Осталось немного стилизовать:



Попробуем что-нибудь еще. Предположим, что в шапке сайта у нас имеется навигационное меню, выровненное по правому краю, и мы хотим, чтобы оно распологалось по центру на средних экранах и выстраивалось в одну колонку на маленьких экранах. Проще простого.

/* Большие экраны */.navigation {  display: flex;  flex-flow: row wrap;  /* Это выравнивает элементы по правому краю вдоль основной оси */  justify-content: flex-end;}/* Средние экраны */@media (max-width: 800px) {  .navigation {    /* На средних экранах мы выравниваем меню по центру за счет равномерного распределения доступного пространства между элементами */    justify-content: space-around;  }}/* Маленькие экраны */@media (max-width: 500px) {  .navigation {    /* На маленьких экранах мы меняем направление основной оси с горизонтального (строка) на вертикальное (колонка) */    flex-direction: column;  }}


Поэкпериментируем с гибкостью элементов. Как насчет создания mobile-first трехколоночного макета с полноразмерной шапкой и подвалом, который не зависит от порядка расположения элементов в разметке.

.wrapper {  display: flex;  flex-flow: row wrap;}/* С помощью flex-basis мы устанавливаем значение ширины элементов в 100% */.wrapper > * {  flex: 1 100%;}/* Порядок расположения элементов в разметке следующий * 1. header * 2. article * 3. aside 1 * 4. aside 2 * 5. footer *//* Средние экраны */@media all and (min-width: 600px) {  /* Мы указываем сайдбарам делить между собой строку */  .aside { flex: 1 auto; }}/* Большие экраны */@media all and (min-width: 800px) {  /* Мы меняем первый сайдбар и main местами   * И указываем main занимать в 2 раза больше места, чем сайдбары   */  .main { flex: 2 0px; }  .aside-1 { order: 1; }  .main    { order: 2; }  .aside-2 { order: 3; }  .footer  { order: 4; }}


Полезные ресурсы



Поддержка



Grid (далее по тексту Грид или Сетка)


CSS Grid Layout на сегодняшний день является самым мощным средством создания макетов страниц. Он представляет собой двунаправленную систему. Это означает, что он может работать как со строками, так и с колонками, в отличие от Флекс, который умеет работать только со строками. Грид включает в себя свойства родительского элемента (Grid Container, грид-контейнер, далее по тексту контейнер) и свойства дочерних элементов (Grid Elements, грид-элементы, далее по тексту элементы).

Терминология


Грид-контейнер (Grid Container, далее по тексту контейнер)

Элемент, которому присвоено свойство display со значением grid, становится грид-контейнером. Данный контейнер является прямым предком всех грид-элементов. В следующем примере элемент div с классом container является грид-контейнером.

<div class="container">  <div class="item item-1"> </div>  <div class="item item-2"> </div>  <div class="item item-3"> </div></div>

Грид-линия (Grid Line, далее по тексту линия)

Разделительная линия, формирующая структуру Сетки. Она может быть вертикальной или горизонтальной и обозначает границу строки или колонки. Желтая линия на изображении ниже это пример вертикальной грид-линии (грид-линии колонки).



Грид-трек (Grid Track, далее по тексту трек или дорожка)

Пространство между двумя смежными линиями. Вы можете думать о треках как о строках или колонках Грида. Вот пример дорожки между второй и третьей линиями.



Грид-область (Grid Area, далее по тексту область)

Общее пространство между четырьмя линиями. Область может занимать любое количество грид-ячеек. Вот пример области между горизонтальными линиями 1 и 3 и вертикальными линиями 1 и 3.



Грид-элемент (Grid Element, далее по тексту элемент)

Дочерний элемент (прямой потомок) контейнера. В следующем примере элементы с классом item являются грид-элементами, а элемент с классом sub-item нет.

<div class="container">  <div class="item"> </div>  <div class="item">    <p class="sub-item"> </p>  </div>  <div class="item"> </div></div>

Грид-ячейка (Grid Cell, далее по тексту ячейка)

Пространство между двумя смежными горизонтальными и вертикальными линиями. Это элементарная единица Сетки. Вот пример ячейки между горизонтальными линиями 1 и 2 и вертикальными линиями 2 и 3.



Пример


Колонки с гибкой шириной, которые автоматически перестраиваются в зависимости от ширины экрана без медиа-запросов.

.grid {  display: grid;  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));  /* Для маленьких экранов можно добавить min() */  /* grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); */  grid-gap: 1rem;  /* Данное свойство является стандартным, но хуже поддерживается */  /* gap: 1rem */}


Свойства грид-контейнера


display

Данное свойство делает элемент грид-контейнером и устанавливает грид-контекст для его содержимого.

.container {  display: grid | inline-grid;}

  • grid блочная Сетка
  • inline-grid строчная Сетка

Обратите внимание, что возможность создания вложенных Гридов была перенесена в спецификацию CSS Grid второго уровня.

grid-template-columns, grid-template-rows

Данные свойства определяют колонки и строки Сетки с разделенными пробелами значениями. Значения представляют собой размер трека, а пробелы линию.

.container {  grid-template-columns:  ... |   ...;  grid-template-rows:  ... |   ...;}

  • <track-size> длина, проценты или фракции свободного пространства Грида (используется единица измерения fr)
  • <line-name> произвольное название

Когда вы оставляете пустое пространство между значениями треков, линиям автоматически присваиваются положительные и отрицательные числа:

.container {  grid-template-columns: 40px 50px auto 50px 40px;  grid-template-rows: 25% 100px auto;}



Вы можете явно указывать названия линий. Обратите внимание на квадратные скобки:

.container {  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];}



Линии могут иметь несколько названий. Здесь, например, вторая линия имеет два названия:

.container {  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];}

Если определение содержит повторяющиеся фрагменты, можно использовать инструкцию repeat для сокращения:

.container {  grid-template-columns: repeat(3, 20px [col-start]);}

Что эквивалентно следующему:

.container {  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];}

Если несколько линий имеют одинаковые имена, можно использовать название линии и количество таких линий.

.item {  grid-column-start: col-start 2;}

Единица fr позволяет установить размер трека как фракцию свободного пространства контейнера. В примере ниже ширина каждого элемента равняется трети ширины контейнера:

.container {  grid-template-columns: 1fr 1fr 1fr;}

Свободное пространство вычисляется после вычитания элементов фиксированного размера. В следующем примере пространство, доступное для распределения с помощью единицы fr не включает 50px:

.container {  grid-template-columns: 1fr 50px 1fr 1fr;}

grid-template-areas

Данное свойство определяет шаблон Сетки с помощью названий областей, определенных в свойствах grid-area. Повторение названий областей заставляет контент расширяться на указанное количество ячеек. Точка означает пустую ячейку. Такой синтаксис позволяет визуализировать структуру Сетки.

.container {  grid-template-areas:    " | . | none | ..."    "...";}

  • <grid-area-name> название области
  • . пустая ячейка
  • none область отсутствует

Пример:

.item-a {  grid-area: header;}.item-b {  grid-area: main;}.item-c {  grid-area: sidebar;}.item-d {  grid-area: footer;}.container {  display: grid;  grid-template-columns: 50px 50px 50px 50px;  grid-template-rows: auto;  grid-template-areas:    "header header header header"    "main main . sidebar"    "footer footer footer footer";}

Этот код создает Сетку шириной в четыре колонки и высотой в три строки. Первая (верхняя) строка полностью занимается шапкой. Средняя строка состоит из двух областей main, одной пустой ячейки и одной области sidebar. Последняя строка подвал.



Каждая строка в определении должна состоять из одинакового количества колонок.

Для обозначения пустой ячейки можно использовать любое количество точек. До тех пор, пока между точками нет проблема, они являются индикатором пустой ячейки.

Обратите внимание, что данный синтаксис применяется для обозначения областей, а не линий. При использовании этого синтаксиса линия каждой стороны области именуется автоматически. Если названием области является foo, то названием начальных (первых) линий (строчной и колоночной) области будет foo-start, а последних foo-end. Это означает, что некоторые линии могут иметь несколько названий, как в рассмотренном примере, где верхняя левая линия имеет три названия: header-start, main-start и footer-start.

grid-template

Данное свойство является сокращением для grid-template-rows, grid-template-columns и grid-template-areas.

.container {  grid-template: none | <grid-template-rows> / <grid-template-columns>;}

  • none сбрасывает значения всех трех свойств до дефолтных
  • <grid-template-rows> / <grid-template-columns> устанавливает свойствам grid-template-rows и grid-template-columns соответствующие значения, а свойству grid-template-areas значение none

Можно использовать более сложный, но в тоже время более удобный синтаксис для определения значений всех трех свойств:

.container {  grid-template:    [row1-start] "header header header" 25px [row1-end]    [row2-start] "footer footer footer" 25px [row2-end]    / auto 50px auto;}

Это эквивалентно следующему:

.container {  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];  grid-template-columns: auto 50px auto;  grid-template-areas:    "header header header"    "footer footer footer";}

Поскольку grid-template не сбрасывает неявные свойства Сетки (такие как grid-auto-columns, grid-auto-rows и grid-auto-flow), что требуется в большинстве случаев, вместо него рекомендуется использовать свойство grid.

column-gap, row-gap, grid-column-gap, grid-row-gap

Данные свойства определяют размеры линий. Другими словами, они определяют величину отступов между колонками/строками.

.container {  /* стандарт */  column-gap: <line-size>;  row-gap: <line-size>;  /* раньше */  grid-column-gap: <line-size>;  grid-row-gap: <line-size>;}

  • <line-size> величина отступов

Пример:

.container {  grid-template-columns: 100px 50px 100px;  grid-template-rows: 80px auto 80px;  column-gap: 10px;  row-gap: 15px;}



Отступы создаются только между колонками/строками, но не по краям Сетки.

Обратите внимание, что свойства grid-column-gap и grid-row-gap в настоящее время переименованы в column-gap и row-gap.

gap, grid-gap

Данное свойство является сокращением для row-gap и column-gap.

.container {  /* стандарт */  gap: <grid-row-gap> <grid-column-gap>;  /* раньше */  grid-gap: <grid-row-gap> <grid-column-gap>;}

  • <grid-row-gap> <grid-column-gap> размеры отступов

Пример:

.container {  grid-template-columns: 100px 50px 100px;  grid-template-rows: 80px auto 80px;  gap: 15px 10px;}

Если значение свойства row-gap не установлено, оно принимает значение свойства column-gap.

Обратите внимание, что свойство grid-gap в настоящее время переименовано в gap.

justify-items

Данное свойство определяет выравнивание элементов в ячейках вдоль строчной (горизонтально) оси (в противоположность своству align-items, определяющему выравнивание вдоль блочной (колоночной, вертикальной) оси). Значение этого свойства применяется ко всем элементам контейнера.

.container {  justify-items: start | end | center | stretch;}

  • start элементы сдвигаются в начало их ячеек (левая граница)
  • end элементы сдвигаются в конец ячеек (правая граница)
  • center элементы распологатся по центру
  • stretch элементы заполняют всю ширину ячеек

.container {  justify-items: start;}



.container {  justify-items: end;}



.container {  justify-items: center;}



.container {  justify-items: stretch;}



Расположение отдельного элемента вдоль строчной оси ячейки контролируется свойством justify-self.

align-items

Данное свойство определяет выравнивание элементов в ячейках вдоль блочной (колоночной, вертикальной) оси (в противоположность свойству justify-items, которое определяет выравнивание вдоль строчной (горизонтальной) оси). Значение этого свойства применяется ко всем элементам контейнера.

.container {  align-items: start | end | center | stretch;}

  • start элементы сдвигаются в начало их ячеек (верхняя граница)
  • end элементы сдвигаются в конеч ячеек (нижняя граница)
  • center элементы располагаются по центру
  • stretch элементы заполняют всю высоту ячеек

.container {  align-items: start;}



.container {  align-items: end;}



.container {  align-items: center;}



.container {  align-items: stretch;}



Расположение отдельного элемента вдоль колоночной оси ячейки контролируется свойством align-self.

place-items

Данное свойство является сокращением для align-items и justify-items.

.container {  place-items: <align-items> <justify-items>;}

  • <align-items> <justify-items> первое значение для align-items, второе для justify-items. Если второе значение отсутствует, первое значение присваивается обоим свойствам.

Пример:

.container {  place-items: center start;}

Элементы располагаются по центру ячеек вдоль колоночной оси и в начале вдоль строчной оси.

justify-content (выравнивание колонок)

Порой общая ширина элементов Сетки (ее колонок) оказывается меньше ширины контейнера. Это может произойти при определении элементов фиксированного размера (с помощью px, например). В этом случае мы можем определить порядок расположения колонок Сетки в контейнере. Данное свойство определяет выравнивание Сетки вдоль строчной оси выравнивание колонок (в противоположность свойству align-content, которое определяет выравнивание Сетки вдоль блочной (колоночной) оси выравнивание строк).

.container {  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;}

  • start сдвигает Сетку в начало контейнера (левая граница)
  • end сдвигает Сетку в конец контейнера (правая граница)
  • center Сетка располагается по центру
  • stretch колонки растягиваются таким образом, чтобы Сетка занимала всю ширину контейнера
  • space-around одинаковое пространство между колонками, и половина такого пространства по краям контейнера
  • space-between первая колонка сдвигается в начало контейнера, последняя в конец, свободное пространство равномерно распределяется между остальными колонками
  • space-evenly одинаковое пространство как между колонками, так и по краям контейнера

.container {  justify-content: start;}



.container {  justify-content: end;}



.container {  justify-content: center;}



.container {  justify-content: stretch;}



.container {  justify-content: space-around;}



.container {  justify-content: space-between;}



.container {  justify-content: space-evenly;}



align-content (выравнивание строк)

Порой общая высота элементов Сетки (ее строк) оказывается меньше высоты контейнера. Это может произойти при определении элементов фиксированного размера (с помощью px, например). В этом случае мы можем определить порядок расположения строк Сетки в контейнере. Данное свойство определяет выравнивание Сетки вдоль блочной (колоночной) оси выравнивание строк (в противоположность свойству justify-content, которое определяет выравнивание Сетки вдоль строчной оси выравнивание колонок).

.container {  align-content: start | end | center | stretch | space-around | space-between | space-evenly;}

  • start сдвигает Сетку в начало контейнера (верхняя граница)
  • end сдвигает Сетку в конец контейнера (нижняя граница)
  • center Сетка располагается по центру
  • stretch строки растягиваются таким образом, чтобы Сетка занимала всю высоту контейнера
  • space-around одинаковое пространство между строками, и половина такого пространства по краям контейнера
  • space-between первая строка сдвигается в начало контейнера, последняя в конец, свободное пространство равномерно распределяется между остальными строками
  • space-evenly одинаковое пространство как между строками, так и по краям контейнера

.container {  align-content: start;}



.container {  align-content: end;}



.container {  align-content: center;}



.container {  align-content: stretch;}



.container {  align-content: space-around;}



.container {  align-content: space-between;}



.container {  align-content: space-evenly;}



place-content

Данное свойство является сокращением для align-content и justify-content.

.container {  place-content: <align-content> <justify-content>;}

  • <align-content> <justify-content> первое значение для align-content, второе для justify-content. Если второе значение отсутствует, первое значение присваивается обоим свойствам.

Пример:

.container {  place-content: center start;}

Строки располагаются по центру контейнера, колонки в начале.

grid-auto-columns, grid-auto-rows (размер неявных треков)

Данные свойства определяют размер автоматически создаваемых дорожек (неявных треков). Неявные треки создаются при наличии большего количества элементов, чем ячеек Сетки, или при размещении элемента за пределами Сетки.

.container {  grid-auto-columns: <track-size> ...;  grid-auto-rows: <track-size> ...;}

  • <track-size> длина, проценты или фракции свободного пространства Сетки (используется единица измерения fr)

Пример:

.container {  grid-template-columns: 60px 60px;  grid-template-rows: 90px 90px;}



Это создает Сетку размером 2х2.

Допустим, мы используем свойства grid-column и grid-row для позиционирования элементов следующим образом:

.item-a {  grid-column: 1 / 2;  grid-row: 2 / 3;}.item-b {  grid-column: 5 / 6;  grid-row: 2 / 3;}



Началом элемента с классом item-b является вертикальная линия 5, а концом вертикальная линия 6, но мы не определили эти линии. Поскольку мы ссылаемся на несуществующие линии, для заполнения отступов создаются неявные треки с нулевой шириной. Мы можем использовать свойство grid-auto-columns для определения ширины неявных дорожек:

.container {  grid-auto-columns: 60px;}



grid-auto-flow

Для позиционирования элементов, находящихся за пределами Сетки, можно использовать алгоритм автоматического размещения (auto-placement algorithm). Рассматриваемое свойство определяет, как должен работать данный алгоритм.

.container {  grid-auto-flow: row | column | row dense | column dense;}

  • row (по умолчанию) алгоритм заполняет текущую строку до предела и, при необходимости, когда ширины текущей строки оказалось недостаточно, создает новую строку
  • column алгоритм заполняет текущую колонку до предела и, при необходимости, когда высоты текущей колонки оказалось недостаточно, создает новую колонку
  • dense интеллектуальное заполнение Сетки при наличии элементов разного размера

Обратите внимание, что dense меняет визуальный порядок расположения элементов, что может плохо отразиться на доступности.

Предположим, что у нас имеется такая разметка:

  <section class="container">  <div class="item-a">item-a</div>  <div class="item-b">item-b</div>  <div class="item-c">item-c</div>  <div class="item-d">item-d</div>  <div class="item-e">item-e</div></section>

Мы определяем Сетку, состоящую из пяти колонок и двух строк, и устанавливаем свойству grid-auto-flow значение row (которое является значением по умолчанию):

.container {  display: grid;  grid-template-columns: 60px 60px 60px 60px 60px;  grid-template-rows: 30px 30px;  grid-auto-flow: row;}

При размещении элементов в Сетке, мы определяем места только двух элементов:

.item-a {  grid-column: 1;  grid-row: 1 / 3;}.item-e {  grid-column: 5;  grid-row: 1 / 3;}

Поскольку значением свойства grid-auto-flow является row, наша Сетка выглядит так, как показано на изображении ниже. Обратите внимание на расположение элементов с классами item-b, item-c и item-d (предпочтение отдается строкам):



Если поменять значение свойства grid-auto-flow на column, Сетка будет выглядеть следующим образом (предпочтение отдается колонкам):



grid

Данное свойство является сокращением для grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns и grid-auto-flow (обратите внимание, что в одном объявлении могут содержаться только явные или неявные свойства).

  • none все свойства принимают значения по умолчанию
  • <grid-template> аналогично сокращению grid-template
  • <grid-template-rows> / [auto-flow && dense?] <grid-auto-columns>? определяет значение для grid-template-rows. Если справа от слэша имеется ключевое слово auto-flow, значением свойства grid-auto-flow становится column. Если в дополнение к auto-flow указано ключевое слово dense, алгоритм автоматического размещения упаковывает элементы соответствующим образом. Если значение для свойства grid-auto-columns опущено, его значением становится auto
  • [auto-flow && dense?] <grid-auto-rows>? / <grid-template-columns> определяет значение для grid-template-columns. Если слева от слэша имеется ключевое слово auto-flow, значением свойства grid-auto-flow становится row. Если в дополнение к auto-flow указано ключевое слово dense, алгоритм автоматического размещения упаковывает элементы соответствующим образом. Если значение для свойства grid-auto-rows опущено, его значением становится auto

Следующие два блока кода эквиваленты:

.container {  grid: 100px 300px / 3fr 1fr;}

.container {  grid-template-rows: 100px 300px;  grid-template-columns: 3fr 1fr;}

Следующие два блока кода эквиваленты:

.container {  grid: auto-flow / 200px 1fr;}

.container {  grid-auto-flow: row;  grid-template-columns: 200px 1fr;}

Следующие два блока кода эквиваленты:

.container {  grid: auto-flow dense 100px / 1fr 2fr;}

.container {  grid-auto-flow: row dense;  grid-auto-rows: 100px;  grid-template-columns: 1fr 2fr;}

И следующие два блока кода также эквиваленты:

.container {  grid: 100px 300px / auto-flow 200px;}

.container {  grid-template-rows: 100px 300px;  grid-auto-flow: column;  grid-auto-columns: 200px;}

В данном случае мы можем использовать более сложный, но в тоже время более удобный синтаксис для одновременного определения свойств grid-template-areas, grid-template-rows и grid-template-columns и установки прочих свойств в дефолтные значения. Что для этого нужно сделать, так это определить названия линий и размеры треков с соответствующими областями на одной строке. Это проще продемонстрировать на примере:

.container {  grid: [row1-start] "header header header" 1fr [row1-end]        [row2-start] "footer footer footer" 25px [row2-end]        / auto 50px auto;}

Это равнозначно следующему:

.container {  grid-template-areas:    "header header header"    "footer footer footer";  grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];  grid-template-columns: auto 50px auto;}

Свойства грид-элементов


Обратите внимание, что свойства float, display: inline-block, display: table-cell, vertical-align и column-*, применяемые к грид-элементу, не имеют никакого эффекта.

grid-column-start, grid-column-end, grid-row-start, grid-row-end

Данные свойства определяют положение элемента в Сетке через привязку к определенным линиям. grid-column-start / grid-row-start это начальные линии элемента, а grid-column-end / grid-row-end конечные.

.item {  grid-column-start: <number> | <name> | span <number> | span <name> | auto;  grid-column-end: <number> | <name> | span <number> | span <name> | auto;  grid-row-start: <number> | <name> | span <number> | span <name> | auto;  grid-row-end: <number> | <name> | span <number> | span <name> | auto;}

  • <line> может быть числом (привязка осуществляется к номеру линии) или названием (привязка осществляется к названию линии)
  • span <number> элемент будет растянут на указанное количество треков
  • span <name> элемент будет растягиваться до достижения линии с указанным названием
  • auto автоматическое расположение, автоматическое расширение или дефолтное растягивание на одну колонку

.item-a {  grid-column-start: 2;  grid-column-end: five;  grid-row-start: row1-start;  grid-row-end: 3;}



.item-b {  grid-column-start: 1;  grid-column-end: span col4-start;  grid-row-start: 2;  grid-row-end: span 2;}



Если значения свойств grid-column-end / grid-row-end не определены, элемент займет 1 трек по умолчанию.

Элементы могут перекрывать друг друга. Вы можете использовать свойство z-index для управления порядком наложения элементов.

grid-column, grid-row

Данные свойства являются сокращением для grid-column-start + grid-column-end и grid-row-start + grid-row-end, соответственно.

.item {  grid-column: <start-line> / <end-line> | <start-line> / span <value>;  grid-row: <start-line> / <end-line> | <start-line> / span <value>;}

  • <start-line> / <end-line> значения аналогичны значениям оригинальных свойств, включая span

Пример:

.item-c {  grid-column: 3 / span 2;  grid-row: third-line / 4;}



Если конечная линия не определена, элемент по умолчанию будет занимать 1 трек.

grid-area

Данное свойство определяет название элемента, которое используется в качестве значения в свойстве grid-template-areas. grid-area также может использоваться как сокращение для grid-row-start + grid-column-start + grid-row-end + grid-column-end.

.item {  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;}

  • <name> произвольное название элемента
  • <row-start> / <column-start> / <row-end> / <column-end> могут быть числами или названиями линий

Присвоение названия элементу:

.item-d {  grid-area: header;}

Сокращение для grid-row-start + grid-column-start + grid-row-end + grid-column-end:

.item-d {  grid-area: 1 / col4-start / last-line / 6;}



justify-self

Данное свойство определяет выравнивание элемента в ячейке вдоль строчной оси (в противоположность свойству align-self, которое определяет выравнивание вдоль блочной (колоночной) оси). Это свойство применяется к элементу внутри отдельной ячейки.

.item {  justify-self: start | end | center | stretch;}

  • start элемент сдвигается в начало ячейки (левая граница)
  • end элемент сдвигается в конец ячейки (правая граница)
  • center элемент располагается по центру
  • stretch элемент заполняет всю ширину ячейки

.item-a {  justify-self: start;}



.item-a {  justify-self: end;}



.item-a {  justify-self: center;}



.item-a {  justify-self: stretch;}



Для управления выравниванием всех элементов Сетки вдоль строчной оси используется свойство justify-items.

align-self

Данное свойство определяет выравнивание элемента в ячейке вдоль блочной (колоночной) оси (в противоположность свойству justify-self, которое определяет выравнивание вдоль строчной оси). Это свойство применяется к элементу внутри отдельной ячейки.

.item {  align-self: start | end | center | stretch;}

  • start элемент сдвигается в начало ячейки (верхняя граница)
  • end элемент сдвигается в конец ячейки (нижняя граница)
  • center элемент располагается по центру
  • stretch элемент заполняет всю высоту ячейки

.item-a {  align-self: start;}



.item-a {  align-self: end;}



.item-a {  align-self: center;}



.item-a {  align-self: stretch;}



Для управления выравниванием всех элементов Сетки вдоль блочной (колоночной) оси используется свойство align-items.

place-self

Данное свойство является сокращением для align-self и justify-self.

  • auto значение по умолчанию
  • <align-self> / <justify-self> первое значение для align-self, второе для justify-self. Если второе значение опущено, первое значение применяется к обоим свойствам

.item-a {  place-self: center;}



.item-a {  place-self: center stretch;}



Специальные функции и ключевые слова

  • При определении размеров строк и колонок можно использовать не только обычные единицы измерения, такие как px, rem, % и т.д., но и такие ключевые слова, как min-content, max-content, auto и, пожалуй, самое полезное фракции (fr). grid-template-columns: 200px 1fr 2fr min-content
  • Вы также можете использовать функции, которые делают элементы масштабируемыми. Например, так можно определить элемент, шириной в 1fr, способный сжиматься до 200px: grid-template-columns: 1fr minmax(200px, 1fr)
  • Функция repeat() используется для быстрого определения повторяющихся элементов: grid-template-columns: repeat(10, 1fr) (десять колонок, шириной в 1fr)
  • Сочетание названных возможностей позволяет добиться невероятной гибкости макета, например: grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) (из примера в начале раздела про Грид)

Полезные ресурсы



Поддержка



Туториал


В данном туториале мы создадим простой тренажер по основным свойствам Flexbox.



Разметка

<main>  <div id="controls">    <div id="buttons">      <button data-btn="addBtn">Add Item</button>      <button data-btn="removeBtn">Remove Item</button>    </div>    <fieldset id="flexContainerProps">      <legend>Flex Container Props</legend>      <label for="flexDirection">flex-direction</label>      <select id="flexDirection">        <option value="row" selected>row</option>        <option value="row-reverse">row-reverse</option>        <option value="column">column</option>        <option value="column-reverse">column-reverse</option>      </select>      <label for="flexWrap">flex-wrap</label>      <select id="flexWrap">        <option value="nowrap">nowrap</option>        <option value="wrap" selected>wrap</option>        <option value="wrap-reverse">wrap-reverse</option>      </select>      <label for="justifyContent">justify-content</label>      <select id="justifyContent">        <option value="flex-start">flex-start</option>        <option value="flex-end">flex-end</option>        <option value="center" selected>center</option>        <option value="space-between">space-between</option>        <option value="space-around">space-around</option>        <option value="space-evenly">space-evenly</option>      </select>      <label for="alignItems">align-items</label>      <select id="alignItems">        <option value="flex-start">flex-start</option>        <option value="flex-end">flex-end</option>        <option value="center" selected>center</option>        <option value="stretch">stretch</option>        <option value="baseline">baseline</option>      </select>      <label for="alignContent">align-content</label>      <select id="alignContent">        <option value="flex-start" selected>flex-start</option>        <option value="flex-end">flex-end</option>        <option value="center">center</option>        <option value="stretch">stretch</option>        <option value="space-between">space-between</option>        <option value="space-around">space-around</option>        <option value="space-evenly">space-evenly</option>      </select>    </fieldset>    <fieldset id="flexItemProps">      <legend>Flex Item Props</legend>      <label for="order">order</label>      <input        id="order"        type="number"        min="-5"        max="5"        step="1"        value="0"      />      <label for="flexGrow">flex-grow</label>      <input        id="flexGrow"        type="number"        min="0"        max="5"        step="1"        value="0"      />      <label for="flexShrink">flex-shrink</label>      <input        id="flexShrink"        type="number"        min="1"        max="6"        step="1"        value="1"      />      <label for="alignSelf">align-self</label>      <select id="alignSelf">        <option value="auto" selected>auto</option>        <option value="flex-start">flex-start</option>        <option value="flex-end">flex-end</option>        <option value="center">center</option>        <option value="stretch">stretch</option>        <option value="baseline">baseline</option>      </select>    </fieldset>  </div>  <div id="flexContainer">    <div class="flex-item selected">1</div>    <div class="flex-item">2</div>    <div class="flex-item">3</div>    <div class="flex-item">4</div>    <div class="flex-item">5</div>    <div class="flex-item">6</div>  </div></main>

Здесь у нас имеется флекс-контейнер (flexContainer) с шестью флекс-элементами (flex-item) и контейнер (controls) для управления переключением свойств флекс-контейнера (flexContainerProps) и выбранного (selected) флекс-элемента (flexItemProps). Также во втором контейнере у есть две кнопки (buttons): одна для добавление элемента во флекс-контейнер (addBtn), другая для удаления последнего флекс-элемента (removeBtn).

Стили

main {  display: flex;  justify-content: center;  align-items: center;}#controls {  margin-right: 0.4rem;}#buttons {  margin: 0.4rem;  display: flex;  flex-wrap: wrap;  justify-content: center;}button {  margin: 0.2rem;}label {  display: block;  margin: 0.4rem;}select {  width: 100%;}#flexContainer {  width: 600px;  height: 600px;  border: 1px dashed #222;  border-radius: 4px;  display: flex;  flex-wrap: wrap;  justify-content: center;  align-items: center;}.flex-item {  min-width: 178px;  min-height: 178px;  background: radial-gradient(circle, yellow, orange);  border: 1px solid #222;  border-radius: 4px;  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);  color: #222;  font-size: 2rem;  display: flex;  justify-content: center;  align-items: center;  user-select: none;  cursor: pointer;}.flex-item:nth-child(2n) {  min-width: 158px;  min-height: 158px;}.flex-item:nth-child(3n) {  min-width: 198px;  min-height: 198px;}.flex-item.selected {  background: radial-gradient(circle, lightgreen, darkgreen);}

Флекс-элементы должны быть разного размера и при этом гибкими. Мы добиваемся этого с помощью min-width/min-height и nth-child. Выбранный элемент имеет класс selected с другим цветом фона.

Скрипт

// Получаем контейнеры и кнопкиconst controls = document.querySelector('#controls')const buttons = document.querySelector('#buttons')const flexContainer = document.querySelector('#flexContainer')// Обрабатываем нажатие кнопкиbuttons.addEventListener('click', (e) => {  // Нас интересует только нажатие кнопки  if (e.target.tagName !== 'BUTTON') return  // Получаем название кнопки  const { btn } = e.target.dataset  switch (btn) {    // Если нажата кнопка для добавления элемента во флекс-контейнер    case 'addBtn':      // Максимальное количество элементов составляет 6 единиц      // При большем количестве произойдет переполнение флекс-контейнера      // Определяем порядковый номер элемента      const num = document.querySelectorAll('.flex-item').length + 1      // Проверяем, что в контейнере находится меньше 7 элементов      // Если это так      if (num < 7) {        // Создаем новый элемент "div"        const newItem = document.createElement('div')        // Добавляем ему соответствующий класс        newItem.className = 'flex-item'        // Нумеруем его        newItem.textContent = num        // И помещаем во флекс-контейнер        flexContainer.append(newItem)      }      break    // Если нажата кнопка для удаления флекс-элемента    case 'removeBtn':      // Определяем индекс последнего элемента      const index = document.querySelectorAll('.flex-item').length - 1      // Проверяем, что индекс последнего элемента больше 0      // Мы не хотим удалять единственный флекс-элемент      if (index > 0) {        // Определяем элемент, подлежащий удалению        const itemToRemove = document.querySelectorAll('.flex-item')[index]        // И удаляем его        itemToRemove.remove()      }      break  }})// Обрабатываем изменения селектов и инпутовcontrols.addEventListener('change', (e) => {  // Получаем название измененного свойства  const prop = e.target.id  // Получаем значение измененного свойства  const value = e.target.value  // Проверяем, какое свойство изменилось  // Свойство флекс-контейнера или свойство выбранного флекс-элемента  // И добавляем соответствующие свойства и значения  if (e.target.parentElement.id === 'flexContainerProps') {    flexContainer.style[prop] = value  } else {    const selectedItem = document.querySelector('.selected')    selectedItem.style[prop] = value  }})// Обрабатываем выбор флекс-элементаflexContainer.addEventListener('click', (e) => {  // Нас интересует только клик по не выбранному флекс-элементу  if (    e.target.className !== 'flex-item' ||    e.target.classList.contains('selected')  )    return  // Нам нужно удалить класс "selected" у текущего выбранного элемента  if (document.querySelector('.selected') !== null)    document.querySelector('.selected').classList.remove('selected')  // И добавить его новому выбранному элементу  e.target.classList.add('selected')  // При выборе флекс-элемента нам необходимо получить значения его "флекс-свойств"  // И присвоить их соответствующим инпутам и селекту  // Это позволяет изменять свойства выбранного флекс-элемента  // Переключаться на другой элемент  // Возвращаться к первому, и редактировать ранее измененные свойства  // Вспомогательная функция для получения значения определенного свойства указанного элемента  // Значением по умолчанию второго параметра функции является выбранный флекс-элемент  const getStyle = (property, element = e.target) =>    getComputedStyle(element).getPropertyValue(property)  // Воспользуемся тем, что мы можем обращаться к DOM-элементам, имеющим атрибут "id", напрямую  // Обратите внимание, что делать так не рекомендуется  order.value = getStyle('order')  flexGrow.value = getStyle('flex-grow')  flexShrink.value = getStyle('flex-shrink')  alignSelf.value = getStyle('align-self')})

Как видите, ничего сложного. Конечно, функционал получившегося тренажера весьма ограничен. Однако, полагаю, этого вполне достаточно для понимания работы основных свойств Flexbox.

Рекомендую попробовать создать аналогичный тренажер по основным свойствам Grid это будет отличной практикой и позволит как следует во всем разобраться.



Вам также может показаться интересным один из моих последних проектов Современный стартовый HTML-шаблон.

Благодарю за внимание и хорошего дня.
Подробнее..

Полное руководство по CSS Flex опыт использования

20.04.2021 00:18:08 | Автор: admin

Как и CSS Grid, Flex Box довольно сложен, потому что состоит из двух составляющих: контейнера и элементов внутри него.

Когда я начал изучать Flex, я хотел увидеть все, на что он способен. Но мне не удалось найти подробное руководство с примерами всех возможностей. Поэтому я решил самостоятельно создать диаграммы свойств Flex с высоты птичьего полета.

Это все, на что способен Flex.Это все, на что способен Flex.

Но давайте рассмотрим каждую диаграмму отдельно. К концу этого руководства по Flex вы узнаете обо всех его возможностях.

CSS Flex или Flex Box

Flex это набор правил для автоматического растягивания нескольких столбцов и строк внутри родительского контейнера.

display:flex

В отличие от многих других свойств CSS, в Flex есть основной контейнер и вложенные в него элементы. Некоторые свойства CSS-Flex относятся только к контейнеру. А другие можно применить только к элементам внутри него.

Вы можете думать о flex-элементе как о родительском контейнере со свойством display: flex. Элемент, помещенный в контейнер, называется item. Каждый контейнер имеет границы начала(flex-start) и конца гибкости(flex-end), как показано на этой диаграмме.

Горизонтальная (main) и вертикальная (cross) оси

Хотя список элементов представлен линейно, необходимо обращать внимание на строки и столбцы. По этой причине Flex включает в себя координатные оси. Горизонтальная ось называется main-axis, а вертикальная cross-axis.

Чтобы управлять шириной содержимого контейнера и промежутками между элементами, которые растягиваются вдоль main-axis, необходимо использовать Justify-content. Для управления вертикальными изменениями элементов необходимо использовать align-items.

Если у вас есть 3 столбца и 6 элементов, Flex автоматически создаст вторую строку для размещения оставшихся элементов. Если у вас в списке более 6 элементов, будут созданы дополнительные строки.

По умолчанию, элементы Flex равномерно распределяются внутри контейнера по горизонтальной оси. Мы рассмотрим различные свойства и значения.

Вы можете определять количество столбцов.Вы можете определять количество столбцов.

Распределение строк и столбцов внутри родительского элемента определяется свойствами CSS Flex flex-direction, flex-wrap и некоторыми другими, которые будут продемонстрированы дальше.

:У нас есть произвольное n-количество элементов, расположенных в контейнере. По умолчанию элементы растягиваются слева направо. Однако направление можно изменить. :У нас есть произвольное n-количество элементов, расположенных в контейнере. По умолчанию элементы растягиваются слева направо. Однако направление можно изменить.

Direction

Можно задать направление движения элементов (по умолчанию слева направо).

flex-direction: row-reverse изменяет направление движения списка элементов. По умолчанию стоит значение row, что означает движение слева направо.

Wrap

flex-wrap: wrap определяет перенос элементов на другую строку, когда в родительском контейнере заканчивается место.

Flow

flex-flow включает в себя flex-direction и flex-wrap, что позволяет определять их с помощью одного свойства.

Примеры:

  • flex-flow: row wrap определяет значения flex-direction как row и flex-wrap как wrap.

  • flex-flow:row wrap-reverse (перенос элементов вверх)

  • flex-flow:row wrap (стандартный перенос элементов); justify-content: space-between (пробел между элементами);

  • flex-flow: row-reverse wrap (направление движения справа налево со стандартным переносом сверху вниз)

  • flex-flow: row-reverse wrap-reverse (направление движения справа налево и обратный перенос элементов);

  • flex-flow: row wrap; justify-content: space-between; (стандартный перенос и направление; расстояние между элементами)

Направление можно изменить, чтобы сделать вертикальную ось главной.

Когда мы меняем flex-direction на column, свойство flex-flow ведет себя точно так же, как и в предыдущих примерах. За исключением wrap-reverse, когда элементы переносятся снизу вверх.

justify-content

Я получил много просьб прояснить приведенный выше пример. Для этого я создал анимацию:

Анимированные возможности justify-content. Анимированные возможности justify-content.

Надеюсь, эта CSS-анимация поможет лучше понять работу justify content.

Свойства следующие:flex-direction:row; justify-content: flex-start | flex-end | center | space-between | space-around | stretch | space-evenly. В этом примере мы используем только 3 элемента в строке.

Нет никаких ограничений на количество элементов, которые можно использовать в Flex. Эти диаграммы демонстрируют только поведение элементов, когда одно из перечисленных значений применяется к свойству justify-content .

То же свойство justify-content используется для выравнивания элементов, когда flex-direction: column. То же свойство justify-content используется для выравнивания элементов, когда flex-direction: column.

Packing Flex Lines (согласно спецификации Flex)

Я не уверен, реализовано ли это в каком-либо браузере, но когда-то это было частью спецификации CSS-flex и, вероятно, стоит упомянуть об этом для полноты картины.

В спецификации Flex это называется Packing Flex Lines. По сути, это работает так же, как в примерах выше. Однако стоит обратить внимание, что интервал расположен между целыми группами элементов. Это полезно, когда вы хотите создать зазоры между группами.

Packing Flex Lines, но теперь с flex-direction: column Packing Flex Lines, но теперь с flex-direction: column

align-items

align-items контролирует выравнивание элементов по горизонтали относительно родительского контейнера.

flex-basis

flex-basis работает аналогично другому свойству CSS: min-width. Оно увеличивает размер элемента в зависимости от содержимого. Если свойство не задействуется, то используется значение по умолчанию.

flex-grow

flex-grow применяется к конкретному элементу и масштабирует его относительно суммы размеров всех других элементов в той же строке, которые автоматически корректируются в соответствии с заданным значением свойства. В примере значение flex-grow для элементов было установлено на 1, 7 и (3 и 5) в последней строке.

flex-shrink

flex-shrink это противоположность flex-grow. В примере значение flex-shrink равно 7. При таком значении размер элемента равен 1/7 размера окружающих его элементов (размер которых автоматически скорректирован).

При работе с отдельными элементами можно использовать только одно свойство из трёх: flex-grow , flex-shrink или flex-base.

order

Используя свойство order , можно изменить естественный порядок элементов.

justify-items

И последнее, что нужно для тех, кто хочет использовать CSS Grid вместе с Flex Box... justify-items в CSS Grid похожи на justify-content в Flex. Свойства, описанные на приведенной выше диаграмме, не будут работать в Flex, но в значительной степени эквивалентны сетке для выравнивания содержимого ячеек.

Опыт веб-студии ITSOFT

Мы в веб-студии ITSOFT перешли на Flex в 2010 году. В основе всех наших новых проектов лежит именно эта технология. Наш опыт показал, что она позволяет создавать адаптивные и кроссбраузерные сайты с действительно красивым дизайном.

При использовании Flex нужно учитывать, что:

  • Flex-элементы по умолчанию ужимаются под свое содержимое; Это может пригодиться, когда есть блоки, размер которых изначально неизвестен и зависит от количества контента.

    Примеры: пункты меню в https://ketoplus.ru/

  • Внешние отступы flex-элементов не схлопываются и не выпадают, в отличие от блочной модели.

    Схлопывание и выпадание отступов полезно, в основном, при верстке текстовых страниц, поэтому во избежание путаницы в отступах при создании сеток отсутствие такого поведения приходится очень кстати.

    Пример: блоки в http://velpharm.ru/about/veltrade/

  • Flex-элементы умеют перераспределять свободное пространство вокруг себя, таким образом меняя свои размеры;

    Больше не нужно вручную задавать ширину в процентах флекс-элементам, если необходимо равномерно заполнить все пространство флекс-контейнера. Браузер сам рассчитает размеры и распределит элементы по флекс-контейнеру.

    Пример: главная страница http://oflomil.ru/

  • Внутри одного флекс-контейнера можно менять порядок флекс-элементов, хотя в DOM-дереве порядок остается неизменным.

    Бывают макеты страниц, в которых порядок следования элементов отличается на мобильной и десктопной версиях. Flex справится с задачей.

    Пример: разный порядок следования логотипа и навигации в шапке в мобильной и десктопной версиях (http://elmucin.ru/).

  • Flex-элементу можно задать не только горизонтальные автоматические отступы, но и вертикальные; к тому же есть специальные свойства, с помощью которых очень просто выравнивать элементы внутри флекс-контейнера по горизонтали или вертикали.

    Пример: кнопка всегда находится в нижней части карточки статьи (https://rabiet.ru/experts/), блок продукция (https://stomatofit.ru/#products).

  • Flex-элементы могут переноситься на следующую строку, если указано соответствующее свойство.

    Эта особенность полезна в каталогах и различных списках, где изначально количество всех элементов неизвестно. Если их станет слишком много и предусмотрен перенос, то страница в этом случае не развалится.

    Пример: каталог Велфарм (http://velpharm.ru/catalog/), блок Где купить (http://valosemid/#partners, https://gopantomid.ru/)

Стоит отметить, что Flexbox поддерживается в Internet Explorer 10-11, хоть и с некоторыми оговорками.

Некоторые интересные фишки Flex мы реализовали на сайте oflomil.ru. На разводящей странице есть 3 столбца на всю высоту видимой области экрана. На мобильном они трансформируются в 3 строки, каждая из которых равномерно занимает место в видимой части экрана. На продуктовых страницах без единого скрипта реализована бегущая строка. Текстовые элементы расположены в ряд благодаря inline-flex. Все свободное пространство в ряду распределено между этими элементами равномерно. Наш собственный сайт также свёрстан с использованием Flex.

Реализация бегущей строки с Flex Реализация бегущей строки с Flex

Из недостатков можно отметить то, что Flex не хватает при верстке писем. Не во всех почтовых клиентах он работает корректно.

В скором времени большую распространённость получит технология Grid. Однако Grid не замена Flexbox. Флексы в связке с гридами помогут решать задачи, которые раньше были сложными или вовсе невозможными. К примеру, Masonry-раскладка одна из тех вещей, которую нельзя полноценно реализовать на данный момент. После появления возможностей спецификации Grid Layout 3 уровня в браузерах, реализация такой раскладки станет возможной и к тому же простой.

Источники: оригинал руководства с картинками


Дата-центр ITSOFT размещение и аренда серверов и стоек в двух дата-центрах в Москве. За последние годы UPTIME 100%. Размещение GPU-ферм и ASIC-майнеров, аренда GPU-серверов, лицензии связи, SSL-сертификаты, администрирование серверов и поддержка сайтов.

Подробнее..

Горизонтальный блог

25.12.2020 16:21:43 | Автор: admin

image


Всё больше новостные сайты и блоги превращаются в длинную портянку которую от статьи к статье надо долго мотать по вертикали. Чтобы облегчить прокрутку одни сайты скрывают часть статьи под спойлером. Другие сайты отображают часть статьи в ленте а для прочтения её заставляют перейти на отдельную страницу.


Я подумал почему бы не воспользоваться горизонталью? Разработчики браузеров дали достаточно CSS инструментов чтобы выстроить статьи по горизонтали и сделать удобный переход между ними.


Я создал минимальную демку которая работает за счёт CSS и имеет такие свойства:


  1. Статьи выстраиваются по горизонтали.
  2. Часть статьи не надо скрывать под спойлером так как вертикальная прокрутка для каждой статьи индивидуальна.
  3. На следующую статью можно перейти из любого места предыдущей прокрутив колёсико мышки с зажатым Shift или смахнув статью влево на планшете.

В статье я разберу СSS используемый для горизонтального блога.


Пример HTML
<html>    <head>        <title>horizontal blog demo</title>        <link href="horizontal-blog.css" rel="stylesheet">        <link href="css-min-fix.css" rel="stylesheet">    </head>    <body>        <div class="hb-viewport">            <div class="hb-container">                <article class="hb-page">                    <h1>Lorem ipsum dolor sit amet</h1>                    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Leo integer malesuada nunc vel risus...                </article>                <article class="hb-page">                    <h1>Consectetur a erat nam at lectus urna duis</h1>                    Consectetur a erat nam at lectus urna duis. Cursus vitae congue mauris rhoncus aenean. Quis auctor elit sed vulputate mi sit amet mauris commodo. Odio pellentesque diam volutpat commodo sed...                </article>              </div>        </div>    </body></html>

Разбираем CSS


horizontal-blog.css:
/*
Это окно через которое пользователь читает содержимое статьи. Изначально его функции выполнял :root элемент но я решил отвязаться от структуры html документа.
*/


.hb-viewport{

/*
Избавляемся от отступа поумолчанию у body не трогая стили css body.
*/


    position: absolute;    top: 0;    left: 0;

/*
Задаём размеры viewport размером видимой области окна чтобы была возможна прокрутка по горизонтали.
*/


    width: 100vw;    height: 100vh;

/*
Задаём прокрутку по горизонтали а вертикальную скрываем так как нужно чтобы прокручивалась вниз каждая статья индивидуально.
*/


    overflow-x: auto;    overflow-y: hidden;

/*
Чтобы облегчить прокрутку задаём автоматическое выравнивание прокрутки по горизонтали.
*/


    scroll-snap-type: x mandatory;

/*
Скрываем горизонтальную полосу прокрутки так как по умолчанию в Firefox она не скрывается и перекрывает последние строки текста. Благодаря этому правилу мы можем вывести указатель за пределы .hb-viewport и прочитать перекрытый горизонтальной полосой прокрутки текст.
*/


    scrollbar-width: none;}

/*
Показываем горизонтальную полосу прокрутки. Это позволяет пользоваться ей когда указатель находится внутри .hb-viewport
*/


.hb-viewport:hover{    scrollbar-width: auto;}

/*
Благодаря display: flex; .hb-container выстраивает своё содержимое в длинную горизонтальную полосу.
*/


.hb-container{    display: flex;}

/*
.hb-page содержит в себе статью.
*/


.hb-page{

/*
Чтобы статью индивидуально можно было прокручивать по вертикали ограничиваем её по высоте её размером видимой части окна.
*/


    max-height: 100vh;

/*
Скрываем то что не влезло добавляя полосу прокрутки по необходимости.
*/


    overflow-y: auto;

/*
Привязываем выравнивание прокрутки по центру .hb-page.
*/


    scroll-snap-align: center;

/*
Задаём ширину статьи до 80 символов для удобства чтения и добавляем поля по бокам до 100vw.
*/


    min-width: min(80ch, 100vw);    padding: 0 calc((100vw - 80ch) / 2);}

Поправляем CSS


Есть проблема с моим Firefox на Android планшете который перестал обновляться с версии 68.11. Он не поддерживает css функцию min(). Можно это поправить при помощи директивы @supports и @media.


css-min-fix.css:
/*
Проверяем что браузер не поддерживает min.
*/


@supports not (min-width: min(80ch, 100vw)) {

/*
Задаём ширину по умолчанию в 100vw.
*/


    .hb-page{        min-width: 100vw;    }

/*
Если видимая часть окна шире 80 символов то задаём ширину 80 символов.
*/


    @media screen and (min-width: 80ch) {      .hb-page{          min-width: 80ch;      }    }}

Готово


Теперь статьи блога выстроены горизонтально и от статьи к статье можно переходить мотая влево в право. Ну а сами статьи прокручиваются вверх вниз независимо и из любой части предыдущей статьи можно перейти в начало следующей.


Ссылки


Подробнее..
Категории: Css , Flexbox , Scroll-snap

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru