Как стать автором
Обновить
3379.97
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

Магия CSS на практике: советы по вёрстке от гика. Часть 5

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров7.4K


Хабр, привет! Я снова пришёл к вам со статьёй, где показываю мои любимые техники вёрстки. Моя цель — поделиться опытом с вами. Я использую не только трюки известных экспертов, есть лично мои придумки. Но, пожалуйста, относитесь к этому контенту, как просто альтернативному мнению. Мои техники не являются единственными правильными решениями.


Сегодня мы рассмотрим:

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

Давайте посмотрим, что я вам подготовил.


▍ Мои правила при работе с отступами


При входе во фронтенд все знакомятся с тем, как установить отступ между двумя элементами. В этот момент человек узнаёт про внешние и внутренние отступы и учится применять их. Кажется, этот аспект очень простой. Наверное, вы уже думаете: «Стас, зачем ты про это рассказываешь?».


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


Отображен список смартфонов. Ниже отображается кнопка Показать еще

Как вы видите, есть список товаров и кнопка «Показать ещё». Между ними есть отступ. Давайте посмотрим в инструменты разработчика, как он задан.


Выделена область списка. Она вплотную граничит с кнопкой Показать еще

Мы видим, что отступа вообще нет. Но визуально он есть! Просто он создан вследствие того, что блок со списком товаров распёрли дочерние элементы. Если быть точным, это был элемент на третьем уровне вложенности.


В инструментах разработчика выделен дочерний элемент в списке с установленным отступом сверху и снизу

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


Честно я даже не знаю, как объяснить, что это плохо. Я никогда так не делал. Может у вас есть версия? Напишите, пожалуйста, в комментариях.


Но на этом не всё. Давайте ещё раз посмотрим на дочерний элемент.


В инструментах разработчика выделен дочерний элемент в списке с установленным отступом сверху и снизу

Он является последним элементом в родительском блоке. Но почему-то его нижний отступ не сброшен! А вот это точно плохо.


По моему мнению, у хороших фронтендеров есть одна общая черта. Они тестируют вёрстку, удаляя некоторые элементы. Вот этот список может быть отражён, как с кнопкой «Показать ещё», так и без. В последнем случае нижний отступ уже приведёт к тому, что вёрстка не будет соответствовать дизайну.


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


.uia-list__group:nth-of-type(n+2) {
  margin-top: 1.5rem;
} 

Также хочу сказать несколько слов по альтернативным методам. Можно сначала установить отступ, а потом его сбросить у крайних элементов. Или установить отступ с помощью псевдо-класса :not(). Все эти способы мне не нравятся. В первом случае нужно создавать два правила. Второй — это чисто мой загон.


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


▍ Единый стиль установки значений для свойств margin и padding — это способ борьбы с неопределённостью


В программировании есть правила хорошего тона, нацеленные на аккуратность кода. В вёрстке они тоже есть. Сегодня хочу рассказать про установку значений для свойств margin и padding.


Начнём мы с примера. Я нашёл раздел, содержащий несколько новостей. Мы рассмотрим, как у него установлен отступ.


В инструментах разработчика выделен элемент. У него установлен внешний отступ снизу

Запоминаем, что используется свойство margin-bottom. Идём дальше. В карточке новости есть элемент «Live». Посмотрим, как у него задан отступ.


В инструментах разработчика выделен элемент. У него установлен внешний отступ сверху

Здесь мы уже видим свойство margin-top. Ладно, тоже запомним. Посмотрим блок с кратким описанием новости.


В инструментах разработчика выделен элемент. У него установлен внутринний отступ сверху. Также у элемента установлено значение 0 для внутренниго отступа снизу

А тут сразу используется и padding-top, и padding-bottom. Полный комплект. Казалось бы, что нет ничего плохого в таком стиле работы с отступами. Просто любят разработчики разнообразие. А скорее всего этот код написало вообще несколько человек. Что не так?


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


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


Лично мне нравится устанавливать отступы слева и сверху. В моём коде вам очень сложно будет найти отступы справа и снизу. Исключением являются ситуации, когда требуется установить отступы сразу с двух сторон или со всех.


▍ Реализация отступов для дочерних элементов с учётом их количества


Создание компонентов, которые можно использовать в разных условиях, является одной из задач по моей душе. Нравится мне запариться. Могу очень много времени на это потратить. Я к чему?


Моя боль — это отступы. Сложно продумать все условия, при которых они будут адекватно себя вести. Вот взять пример вёрстки интерактивного элемента с иконкой.


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


Если мы будем для установки отступов между иконкой и текстом использовать свойство margin, то нам нужны дополнительные классы. Важным условием является то, что они не должны конфликтовать между собой.


В итоге получается такая разметка.


<body>
  <!-- состояние №1: только текст без иконки -->
  <button type="button" class="uia-button">
    <span class="uia-button__text">Перейти</span>
  </button>
</body>

<body>
  <!-- состояние №2: иконка находящийся перед текстом -->
  <button type="button" class="uia-button">
    <svg class="uia-button__icon uia-button__icon--pos-before" width="16" height="16" viewbox="0 0 24 24">
      <path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
    </svg>
    <span class="uia-button__text">Перейти</span>
  </button>
</body>

<body>
  <!-- состояние №3: иконка находящийся после текста -->
  <button type="button" class="uia-button">
    <span class="uia-button__text">Перейти</span>
    <svg class="uia-button__icon uia-button__icon--pos-after" width="16" height="16" viewbox="0 0 24 24">
      <path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
    </svg>
  </button>
</body>

<body>
  <!-- состояние №4: только иконка -->
  <button type="button" class="uia-button" aria-label="Перейти">
    <svg class="uia-button__icon" width="16" height="16" viewbox="0 0 24 24">
      <path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
    </svg>
  </button>
</body>

В CSS задаётся отступ с помощью свойств margin-right и margin-left.


.uia-button {
  display: inline-flex;
}

.uia-button__icon--pos-before {
  margin-right: 0.5rem;
}

.uia-button__icon--pos-after {
  margin-left: 0.5rem;
}

В этом решении мы сами продумываем ситуации, когда у нас появляется иконка рядом с текстом, и когда её не будет. Было бы здорово, если браузеры сами могли это предсказать. Если иконка есть, то отступ устанавливается. Если нет, то и отступа не надо. А знаете, так можно сделать. Есть же свойство gap.


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


Сначала уберу дополнительные классы uia-button__icon--pos-before и uia-button__icon--pos-after.


<body>
  <!-- состояние №1: только текст без иконки -->
  <button type="button" class="uia-button">
    <span class="uia-button__text">Перейти</span>
  </button>
</body>

<body>
  <!-- состояние №2: иконка находящийся перед текстом -->
  <button type="button" class="uia-button">
    <svg class="uia-button__icon" width="16" height="16" viewbox="0 0 24 24">
      <path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
    </svg>
    <span class="uia-button__text">Перейти</span>
  </button>
</body>

<body>
  <!-- состояние №3: иконка находящийся после текста -->
  <button type="button" class="uia-button">
    <span class="uia-button__text">Перейти</span>
    <svg class="uia-button__icon" width="16" height="16" viewbox="0 0 24 24">
      <path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
    </svg>
  </button>
</body>

<body>
  <!-- состояние №4: только иконка -->
  <button type="button" class="uia-button" aria-label="Перейти">
    <svg class="uia-button__icon" width="16" height="16" viewbox="0 0 24 24">
      <path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z"/>
    </svg>
  </button>
</body>

Далее добавим свойство gap для элемента с классом uia-button.


.uia-button {
  display: inline-flex;
  gap: 0.5rem;
}

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


Улучшу своё решение псевдо-классом :has.


.uia-button {
  display: inline-flex;
}

.uia-button:has(> :nth-child(2)) {
  gap: 0.5rem;
}

Теперь свойство gap будет добавлено, когда у элемента с классом uia-button будет больше одного прямого потомка. Другими словами, оно появится, когда будут добавлены элементы с текстом и иконкой.


▍ Заключение


Давайте подведём итог. В этой статье мы рассмотрели:

  • технику установки отступов для дочерних элементов без распирания их родителя;
  • почему нужно следить за отступами у элементов, граничащих с границами родителя:
  • преимущество единого стиля установки значения для свойств margin и padding делает;
  • альтернативный способ установки отступов на основе свойства gap;
  • способ установки свойства gap в зависимости от количества дочерних элементов.

Оставлю ссылки на все выпуски:

Спасибо за чтение!


P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.


© 2024 ООО «МТ ФИНАНС»

Telegram-канал со скидками, розыгрышами призов и новостями IT 💻
Теги:
Хабы:
Всего голосов 31: ↑30 и ↓1+44
Комментарии7

Публикации

Информация

Сайт
ruvds.com
Дата регистрации
Дата основания
Численность
11–30 человек
Местоположение
Россия
Представитель
ruvds