Как не надо делать
HTML для наших кнопок будет неизменным в течение всей статьи:
<ul class="about_butt_list">
<li class="about_butt_item"><a href="#" class="about_butt blue_mod">Инфраструктура</a></li>
<li class="about_butt_item"><a href="#" class="about_butt red_mod">Квартиры</a></li>
<li class="about_butt_item"><a href="#" class="about_butt yellow_mod">Галерея</a></li>
</ul>
Первое что может прийти в голову верстальщику — записать стили для кнопок сразу в классы наших элементов.
SCSS:
.about_butt {
display: block;
height:50px;
line-height: 50px;
text-align: center;
font-family: 'intro';
font-size: 12px;
}
Мы написали стили для нашего основного класса, теперь сделаем его модификации по цвету(для цвета использованы переменные для удобства):
.about_butt {
display: block;
height: 50px;
line-height: 50px;
text-align: center;
font-family: 'intro';
font-size: 12px;
&.blue_mod {
background: $blue_1;
color: $white;
transition: background .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: lighten($blue_1, 5%);
}
}
&.red_mod {
background: $red_1;
color: $white;
transition: background .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: lighten($red_2, 5%);
}
}
&.yellow_mod {
background: $yellow_1;
color: $white;
transition: background .3s ease;
&:hover, &:focus {
text-decoration: none;
}
}
}
Пока все просто и понятно.Но на следующей странице появляется вот такая кнопка:
Эта кнопка имеет те же размеры, что и предыдущие, но другое оформление. Давайте нарушим принцип DRY и скопируем стили для нее от наших предыдущих кнопок:
.news_more_butt {
display: block;
height:50px;
line-height: 50px;
text-align: center;
font-family: 'intro';
font-size: 12px;
}
С размерами определились, давайте добавим оформление:
.news_more_butt {
color:$black_2;
background: transparent;
box-shadow:inset 0 0 0 2rem $gray_4;
transition:all .3s ease;
&:hover,&:focus {
text-decoration: none;
}
&:hover {
background: $gray_4;
color:$white;
}
}
Ну и немного стилей для размещения нашей кнопки:
.news_more_butt {
width: 186px;
margin: 20px auto;
}
Идем дальше и на другой странице встречаем следующую кнопку:
Оформление осталось прежним, а вот размеры кнопки и шрифта изменились. И тут перед нами два пути:
- Продолжать копировать стили для разных кнопок и давать им уникальные классы
- Сделать специальные классы для оформления и добавлять его в наши теги
Минусы каждого из этих подходов очевидны. В первом мы копируем слишком много кода, и когда нужно что-либо изменить — менять нужно в нескольких местах. Во втором мы добавляем презентационные классы, и это тоже не очень хорошо(любители Bootstrap бы возразили).
Но есть и третий путь — использование sass @extend(хотя это можно реализовать в любом препроцессоре).
Третий путь
У меня примеси лежат в отдельном scss файле — buttons.scss, это крайне удобно.Мы будем разделять их на размеры(+типографика) и цветовые схемы.Напишем классы для размеров:
%butt_size_1 {
display: block;
height:50px;
line-height: 50px;
text-align: center;
font-family: 'intro';
font-size: 12px;
}
%butt_size_2 {
display: block;
height:70px;
line-height: 70px;
text-align: center;
font-family: 'intro';
font-size: 16px;
}
Отлично, а теперь цветовые схемы:
%butt_gray_1 {
color: $black_2;
background: transparent;
box-shadow: inset 0 0 0 2rem $gray_4;
transition: all .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: $gray_4;
color: $white;
}
}
%butt_blue_1 {
background: $blue_1;
color: $white;
transition: all .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: lighten($blue_1, 5%);
}
}
%butt_red_1 {
background: $red_2;
color: $white;
transition: all .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: lighten($red_2, 5%);
}
}
%butt_yellow_1 {
background: $yellow_1;
color: $white;
transition: all .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: lighten($yellow_1, 5%);
}
}
%butt_green_1 {
background: $green_1;
color: $white;
transition: all .3s ease;
&:hover, &:focus {
text-decoration: none;
}
&:hover {
background: lighten($green_1, 5%);
}
}
Вот мы и получили гибкую систему для организации наших кнопок.Теперь наш scss будет выглядеть следующим образом:
.about_butt {
@extend %butt_size_1;
&.blue_mod {
@extend %butt_blue_1;
}
&.red_mod {
@extend %butt_red_1;
}
&.yellow_mod {
@extend %butt_yellow_1;
}
}
.news_more_butt {
@extend %butt_size_1;
@extend %butt_gray_1;
width: 186px;
margin: 20px auto;
}
.show_news_butt {
@extend %butt_size_2;
@extend %butt_gray_1;
display: inline-block;
}
Если появляется новая цветовая схема — мы просто делаем для нее @extend и используем, если изменяется текущая —
Ключевые моменты
- Используем тихие классы, а не миксины(меньше результирующего CSS)
- Если у вас одно-страничный сайт с небольшим количеством кнопок — данная система будет излишней
- В тихих классах объявляется display:block, потом это можно переписать в правиле селектора
P.S.: Данную систему разработал Андрей Бойко, за что ему огромное спасибо!
Комментарии (33)
asci
20.11.2015 11:40вы же знаете что `butt` по-английски значит, правда?)
А вообще спасибо, сам над чем-то похожим думаем в проекте. Но пока решили сделать несколько базовых миксинов и просто передавать в них цвета
Metaller
20.11.2015 11:50Хорошо бы вам подучиться нормальному стилю кода или хотя бы использовать IDE с автоформатированием. В свойствах после двоеточего пробел то есть, то нет, вместо табуляции используйте 4 пробела, оступы огромные. несколько extend можно объединять в одной строке
@extend .foo, .bar
.
Откуда такие размеры и зачем тут rem если везде pxwidth: 186rem; margin: 20rem auto;
? По умолчанию 1rem = 16px.
Эти же классы нельзя будет применить на<button>
, будут дефолтные бордеры.
Маленький лайфхакtransition:all .3s ease;
можно заменить наtransition: .3s ease;
, но если вы меняете только одно свойство, то лучше указать его явноtransition: background-color .3s ease;
чтобы избежать ненужных анимаций.
Ну и последнее в этом занудном комментарии — сокращать имя классаbutton
доbutt
странно, коллеги не поймут (butt — анг. задница), общепринятоbtn
.Metaller
20.11.2015 13:21А еще у вас в классах смесь теплого и мягкого. Если это класс size, зачем там же переопределяется font-size, font-family, text-align, display. Если это цвет, зачем там переопределяется transition. Вынесите все общие для кнопок свойства в общие, и расширяйте для каждой кнопки.
gatilin222
20.11.2015 13:31Мне и моим коллегами удобнее делать 2 тихих класса)
Ag47
20.11.2015 13:43Сейчас у вас в тихих классах размеров и тем, куча копипасты про шрифт, танзишен и т.д., если понадобиться менять, вы предлагаете менять те же настройки транзишена в пяти местах, а если цветов еще больше, то в еще большем количестве. Зачем код так жестоко дублировать то?
Если он везде пристуствует его можно вынести в отдельный тихий класс %btn-default и extend делать либо в нужных классах кнопок, либо в сами тихие классы им расширить. Хотя, конечно, стоило просто завести класс btn c свойствами по-умолчанию, не стоит слишком увлекаться extend'ами.gatilin222
20.11.2015 13:59Вы правы, нужно все загонять в переменные, но для этой статьи я решил немного упростить)
А так все зависит от конкретного проекта, здесь описаны основные моментыAg47
20.11.2015 14:02Тогда лучше было выкинуть совсем не относящиеся к делу стили=)
gatilin222
20.11.2015 14:04Наверное так и надо было сделать, не бейте сильно — это первый опыт написания чего-то осмысленного)
Glivera
20.11.2015 19:58В данном примере описана система которая обычно используется на больших проектах. Размер кнопки подразумевает подкласс объекта который включает в себя общие свойства для нескольких кнопок. По сути каждый «класс size» это дефолтное состояние для набора кнопок с определенной высотой. Вся система построена на том что бы иметь только один класс в HTML для привязки всех стилей и не завязываться на модификаторы.
faiwer
20.11.2015 13:27вместо табуляции используйте 4 пробела, оступы огромные
О_о, очередной tabs-vs-spaces?Metaller
20.11.2015 13:30Выше наглядный пример, далеко ходить не надо, по моему мнению тут все очевидно.
faiwer
20.11.2015 13:31Наглядный пример чего? Пример default-го tabSize-а в браузере? Вы серьёзно?
Metaller
20.11.2015 13:33Как один из кейсов. Дефолтный tabSize в браузере у 99% пользователей. Код выше с такими отступами выглядит неаккуратно. Давайте не будем начинать?
PS И кстати при чем тут tabSize браузера, стили для кода — это CSS хабра.faiwer
20.11.2015 13:38Дык, какое отношение имеет дефолтный tabSize в браузере к написанию CSS-кода? Вы выше даёте советы использовать вместо табов пробелы… Я могу точно также рекомендовать всем использовать пробелы, вместо табов. НО!
Зачем вы (не конкретно вы, а апологеты пробелов) из раза в раз тащите всю эту вкусовщину на хабр? Вам этого мало?
gatilin222
20.11.2015 13:46Соглашусь с вами, код действительно выглядит не очень аккуратно в моей статье, но мне лень переводить табы в пробелы)
gatilin222
20.11.2015 13:30Вы правы, в оформлении кода есть косяки, которые образовались во время переноса из редактора в статью).
Надо бы поменять rem на px(где-то изменил, а где-то нет).
transition обычно определяю в тихом классе, для статьи переписал.У меня на проектах 1rem = 10px.
Видимо коллеги находятся на моем уровне грамотности и понимают, что butt — это кнопка, хотя и вправду получается смешно)
sashabeep
20.11.2015 13:09Прям новшество лабораторий гарнье :)
Написал один сайт на компасе + кучка своих примесей — разучился писать css
еще бы кто предложил компилятор компаса, чтобы на шареде бегало, а то при любых изменениях пересобирать и закидывать — пока что не самая интересная процедура. Не надо, пожалуйста, рассказывать про всякие там VPS, серверы, облака и колокейшены — цель должна оправдывать средства
Pilat
20.11.2015 13:49Я как не-верстальщик понял только одно: надо пользоваться стандартными кнопками Bootstrap и ничего не трогать :)
gatilin222
20.11.2015 14:02Если это работает на ваших проектах, совершенно верно! Просто на моих проектах css-фреймворки не едут)
firya
20.11.2015 15:00Следующим шагом предлагаю посмотреть в сторону БЭМ и не бояться написать для кнопки лишний класс.
Можно сократить итоговый css раза в полтора использовав для кнопки классы размера, и миксины просто станут не нужны.gatilin222
20.11.2015 17:38У кнопки делаю один основной класс — мне так удобно, не люблю много презентационных классов)
firya
20.11.2015 18:00Вы итак используется модификационные классы для цвета, чем вам помешает еще один класс для размера?
Из плюсов:
- почти в 3 раза меньше стилей
- такой код легче сопровождать и поддерживать
и выглядеть это будет примерно так:
Код (656 символов стилей)Код на вскидку, не проверял идентичность
<a href="#" class="btn btn-blue">Инфраструктура</a> <a href="#" class="btn btn-red">Квартиры</a> <a href="#" class="btn btn-yellow">Галерея</a> <a href="#" class="btn btn-transparent">Архив новостей</a> <a href="#" class="btn btn-transparent btn-xl">Показать все новости</a>
.btn { display: block; height: 50px; line-height: 50px; text-align: center; font-family: 'intro'; font-size: 12px; text-decoration: none; background: transparent; transition: background .3s ease; &.btn-blue { background-color: #80B1D3; &:hover { background: #80B1D3; color: #fff; } } &.btn-red { background-color: #D46C6B; &:hover { background: #D46C6B; color: #fff; } } &.btn-yellow { background-color: #F3B562; &:hover { background: #D46C6B; color: #fff; } } &.btn-transparent { box-shadow: inset 0 0 0 2rem $gray_4; } &.btn-xl { height: 70px; line-height: 70px; font-size: 16px; } }
PeoneEr
20.11.2015 17:22А зачем Вы каждой кнопке говорите
&:hover, &:focus {
text-decoration: none;
}
?
Задайте это свойство основному классу, а если вдруг потребуется — лучше его изменить для одного стиля, чем тащить везде.gatilin222
20.11.2015 17:37один раз написал его в екстенде — и не парюсь, зачем мне его постоянно писать? А переопределить всегда смогу у основного класса
kvaps
Что-то шрифт кнопок на картинке плывет, сначала попробовал глаза протереть, нет, правда плывет…
kvaps
Статья кстати классная, спасибо. Не знал что такое на css можно.
DeXPeriX
Это же не CSS, а один из препроцессоров — SASS. После компиляции из SASS получается CSS.
Смысл лично мне не очень понятен. В SASS есть примеси, переменные. Их надо использовать. Что ещё можно вынести из статьи?
gatilin222
Когда я начинал верстать, сам бы не додумался до такой системы, и мне кажется статья полезна для таких как я)
Мне бы было интересно посмотреть ваши наработки в sass, если есть возможность поделитесь.