О фронтенде

Помогаю создавать хорошие сайты

Простой лейбл с инпутом

Если вы пишите лейбл с инпутом только так, статья для вас.

<label for="my-input">Лейбл для инпута</label>
<input id="my-input" type="text" />

Предлагаю заверстать форму, где инпутов много.

Фильтр компьютеров в юлмарте
Фильтр компьютеров в юлмарте

Готов поспорить, что вы устанете придумывать айди шестидесяти семи инпутам. Еще придется следить, чтобы айди не повторялись, иначе будет ошибка:

Делайте проще

<label>
  <span>Лейбл для инпута</span>
  <input type="text" />
</label>

Айди придумывать не надо. А чтобы добавить новый инпут, достаточно просто скопировать код.

Подход удобен, чтобы стилизовать радиобаттоны или чекбоксы.

Чтобы написать конструкцию с помощью эммета, напишите label{Текст}>input. Строка развернется так:

<label for="">Текст<input type="text" /></label>

Но при нажатии на текст инпут не сработает. Это потому, что у лейбла стоит атрибут for. Даже если for пустой, он будет искать инпут с таким же айди. Чтобы сработало, удалите for.

See the Pen Лейбл с ошибкой by Dmirty (@shalfey41) on CodePen.

label>input хороший прием, но смотрите по ситуации. Например, если делаете слайдер на CSS, смело отделяйте.

Хорошая сетка

Студенты Академии верстают каталог:

Учебный проект «Техномарт» в HTMLAcademy
Учебный проект «Техномарт» Академии

Заверстаем сетку для списка перфораторов. Добавляю карточкам отступ справа 20 пикселей, а у каждой третьей убираю:

.grid__item {
  margin-right: 20px;
}

.grid__item:nth-child(3n) {
  margin-right: 0;
}
Сетка на марджинах

Получилось хорошо. Но при таком подходе придется следить за размером экрана и дописывать стили.

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

Поменяли размер экрана

Сетка должна быть резиновой. Я нашел решение в коде бутстрапа. Давайте повторим.

Чтобы все получилось, я создал контейнеры для списка, элементов и контента. Пусть будет 3 карточки:

<div class="grid__list">
  <div class="grid__item">
    <div class="grid__content"></div>
  </div>

  <div class="grid__item">
    <div class="grid__content"></div>
  </div>

  <div class="grid__item">
    <div class="grid__content"></div>
  </div>
</div>

Проставим отступы. Представьте 2 карточки рядом. У первой карточки отступ справа 10 пикселей, а у второй — такой же отступ слева. В сумме 20 пикселей:

.grid__item {
  padding-left: 10px;
  padding-right: 10px;
}

Теперь между карточками расстояние 20 пикселей. Почти готово, но у самой первой карточки ненужный отступ слева 10 пикселей, а у последней — справа. Чтобы исправить, добавлю отрицательный отступ для всего списка:

.grid__list {
  margin-left: -10px;
  margin-right: -10px;
}

Вот и все. Хорошая сетка сохранит время и количество кода. Особенно, если сайт адаптивный.

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

Но как же justify-content: space-between?

Некоторые делают сетку проще:

.grid__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.grid__item {
  width: 200px;
}

Но что, если в каталоге будет не 9 товаров, а 5?

Карточки разъехались. Я уже не говорю о разных размерах экрана.

Это не значит, что justify-content: space-between нельзя использовать — если вы знаете, что в макете будет два элемента, которые прижаты по бокам, то space-between справится лучше всех.

Старайтесь предугадывать, как может измениться ваша верстка: «Что, если будет 5 карточек? А что, если сайт будет адаптивным?» — вам же над сайтом и работать. А если и не вам, то не стоит заставлять другого разработчика переписывать ваш код. Думайте наперед.

Итоговая сетка.

Как писать меньше стилей и не бояться правок

Продолжаю разбирать работы студентов базового интенсива Академии. Вот фрагмент макета:

Фрагмент макета «Девайс» от HTML Academy

Студент пишет разметку блока «о нас»:

<section class="about">
  <h2 class="about__title">О нас</h2>
  <p class="about__text">Огромный выбор гаджетов не оставит равнодушным гика, который есть в каждом из нас</p>
  ...
  <a class="about__btn" href="about.html">Подробнее о нас</a>
</section>

Рядом блок «контакты»:

<section class="contacts">
  <h2 class="contacts__title">Контакты</h2>
  ...
  <a class="contacts__btn" href="contact-form.html">Напишите нам</a>
</section>

Теперь CSS-файл. «О нас»:

.about__title {
  font-size: 44px;
  position: relative;
  padding-top: 45px;
  margin-bottom: 50px;
}

.about__title:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 80px;
  height: 7px;
  background-color: black;
}
...
.about__btn {
  position: relative;
  max-width: 300px;
  padding: 0 18px;
  font-size: 18px;
  font-weight: bold;
  color: black;
  text-align: center;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
}

.about__btn:before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  height: 8px;
  background-color: #f0c52e;
  z-index: -1;
}

«Контакты»:

.contacts__title {
  font-size: 44px;
  position: relative;
  padding-top: 45px;
  margin-bottom: 50px;
}

.contacts__title:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 80px;
  height: 7px;
  background-color: black;
}
...
.contacts__btn {
  position: relative;
  max-width: 300px;
  padding: 0 18px;
  font-size: 18px;
  font-weight: bold;
  color: black;
  text-align: center;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
}

.contacts__btn:before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  height: 8px;
  background-color: #f0c52e;
  z-index: -1;
}

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

Я заметил, что размер заголовка по макету равен 47 пикселей, а студент поставил 44:
— Тут с размером заголовка косяк. Поправь, пожалуйста.
— Окей.

.promo__title {
  font-size: 47px;
}
...
.about__title {
  font-size: 47px;
}
...
.contacts__title {
  font-size: 47px;
}
...
.form__title {
  font-size: 47px;
}
...
.goods__title {
  font-size: 47px;
}

— Кстати, с межбуквенным расстоянием кнопок не досмотрел.
— Блин...

.promo__btn {
  letter-spacing: 0.1em;
}
...
.about__btn {
  letter-spacing: 0.1em;
}
...
.contacts__btn {
  letter-spacing: 0.1em;
}
...
.form__btn {
  letter-spacing: 0.1em;
}
...
.goods__btn {
  letter-spacing: 0.1em;
}

Лютый копипаст увеличивает размер кода и раздражение разработчика при очередных правках.

Как правильно

Найдите в макете повторяющиеся элементы. Чаще всего это:

  • заголовки,
  • основной текст,
  • кнопки,
  • списки.

Чтобы элементы были на виду, создайте новый документ в фотошопе и перенесите их.

Создайте классы, куда сложите общие элементы:

.theme__title {
  font-size: 44px;
  position: relative;
  padding-top: 45px;
}

.theme__btn {
  position: relative;
  max-width: 300px;
  padding: 0 18px;
  font-size: 18px;
  font-weight: bold;
  color: black;
  text-align: center;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
}

Осталось добавить тему к разметке:

<section class="contacts">
  <h2 class="theme__title contacts__title">Контакты</h2>
  ...
  <a class="theme__btn contacts__btn" href="contact-form.html">Напишите нам</a>
</section>

А теперь представьте, что к вам пришел менеджер:
— Привет. Заголовки крупноваты, давай уменьшим. 25 пикселей будет ок.
— Через 10 секунд подойди.

9 секунд, чтобы открыть файл и найти класс, 1 секунда, чтобы внести изменения:

.theme__title {
  font-size: 25px;
}

Любитель переменных скажет: «Зачем мне дополнительные классы? Я создам переменные.»:

// style.less
@h2: 47px;

.about__title {
  font-size: @h2;
}
...
.contacts__title {
  font-size: @h2;
}
...
.form__title {
  font-size: @h2;
}

Окей, пусть переменные. А что, если на мониторах увеличить заголовок до 60 пикселей?

// style.less
@media (min-width: 1600px) {
  @h2: 60px;
}

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

// style.less
@media (min-width: 500px) {
  @h2: 30px;

  .about__title {
    font-size: @h2;
  }
  ...
  .contacts__title {
    font-size: @h2;
  }
  ...
  .form__title {
    font-size: @h2;
  }
}

Иными словами, мы вернулись к проблеме. Решение с классом:

// style.less
@media (min-width: 1600px) {
  .theme__title {
    font-size: 60px;
  }
}

Не пишите лишнего

В блоке «о нас» и в «контактах» у заголовка одинаковый отступ снизу. Хочется поддаться искушению и добавить отступ в общий класс:

.theme__title {
  ...
  margin-bottom: 45px;  
}

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

// Общий стиль, который только описывает заголовок
.theme__title {
  font-size: 44px;
  position: relative;
  padding-top: 45px;
}

// В блоке «контакты» и «о нас» отступ 45 пикселей
.about__title,
.contacts__title {
  margin-bottom: 45px;
}

// А здесь 60 пикселей
.form__title {
  margin-bottom: 60px;
}

Пример кода на кодпене

Ищите общие элементы в макетах. Не стесняйтесь упрощать себе работу.