# Как писать CSS
Чтобы сделать хороший CSS, нужно выполнить несколько условий.
## Модульность
Мы хотим писать стили в разных файлах, а браузер должен скачивать только один, склеенный. В JS это называется “бандл” (bundle), в CSS тоже.
Любой CSS-препроцессор умеет это делать, о них ниже.
## Обфускация, оптимизация, сжатие
Чтобы уменьшить размер файла, который будет качать браузер.
Чтобы из такого:
```css
h1::before {
margin: 10px 20px 10px 20px;
color: red;
font-weight: 400;
background-position: bottom right;
quotes: '«' "»";
background: linear-gradient(to bottom, #ffe500 0%, #ffe500 50%, #121 50%, #121 100%);
min-width: initial;
}
@charset "utf-8";
```
Получилось такое:
`
@charset "utf-8";h1:before{margin:10px 20px;color:red;font-weight:400;background-position:100% 100%;quotes:"«" "»";background:linear-gradient(180deg,#ffe500,#ffe500 50%,#121 0,#121);min-width:0}
`
С этим лучше всего справляется [CSSNano](https://cssnano.co/).
Вот бенчмарки: [goalsmashers.github.io/css-minification-benchmark](https://goalsmashers.github.io/css-minification-benchmark/).
## Autoprefixer должен расставить вендорные префиксы
А не ты.
Некоторые свойства до сих пор нужно повторять через префиксы типа `-webkit-backdrop-filter`
Вот [статья про них по состоянию на 2021 год](https://css-tricks.com/is-vendor-prefixing-dead/).
## Тебе должно быть удобно
Если любишь синтаксический сахар — не стоит себе в нём отказывать.
Если любишь писать сложный, громоздкий код, управлять каждой мелочью, выносить всё в переменные и функции — инструментарий должен это позволять сделать.
Если ты решаешь какую-то специфичкскую и сложную задачу — инструментарий должен тебе в этом помогать.
# На чём писать
Сами по себе языки, на которых можно писать стили, называются препроцессорами, потому что они буквально преобразуют один текст в другой.
Например, вот такой код:
```sass
.link
background-color: hsl(217, 91%, 60%)
&:hover
background-color: hsl(217, 91%, 80%)
```
С помощью Sass превращается вот в такой:
```css
.link {
background-color: hsl(217, 91%, 60%);
}
.link:hover {
background-color: hsl(217, 91%, 80%);
}
```
Спешу напомнить, как всё называется:
```css
селектор {
свойство: значение;
}
```
## Препроцессоры: Sass, Less, Stylus
У разных CSS-препроцессоров немного разный синтаксис, но всё склоняется к довольно простым возможностям.
Сейчас есть три основных препроцессора, вот они слева направо:
#### Sass
Самый известный, имеет два синтаксиса: `.scss` в стиле CSS и “сахарный” `.sass` на табах. Можно импортировать между ними.
#### Less
У него довольно интересная идеология в стиле “сделаем очень похоже на CSS”, из-за этого там не очень с циклами и вообще синтаксис довольно странный. Но зато он работает прямо в браузере.
#### Stylus
Самый панковый препроцессор. Можно писать в стиле CSS, можно в стиле `.sass` на табах, можно даже двоеточие не писать между свойством и значением. Можно даже скопировать откуда-нибудь сломанный CSS и он его схавает.
### 1. Склеивать несколько файлов стилей в один
`@import components/style` — Sass
`@import 'components/style'` — SCSS
`@import 'components/style.less'` — Less
`@require 'components/style'` — Stylus
Там, где ты это напишешь, в CSS будет содержимое упомянутого файла.
### 2. Статические переменные
Когда все эти инструменты создавались, в CSS ещё не было возможности написать `color: var(--my-color)`, чтобы установить цвет, записанный как `--my-color: lightblue`. Поэтому препроцессоры сделали это сами:
`$my-color: lightblue` — Sass / SCSS
`@my-color: lightblue` — Less
`my-color = lightblue` — Stylus
### 3. Переиспользуемый код: миксины и примеси
Иногда код хочется использовать несколько раз в разных местах, немного поменяв его в паре мест. В препроцессорах есть функции и миксины (“mixin”, некоторые называют это “примесь”).
#### Миксины
Нужны для того, чтобы переиспользовать одно или несколько свойств сразу.
Sass:
```sass
=setColor($color, $bg)
color: $color
background-color: $bg
.card
+setColor(darkgray, lightblue)
```
SCSS:
```sсss
@mixin setColor($color, $bg) {
color: $color;
background-color: $bg;
}
.card {
@include setColor(darkgray, lightblue)
}
```
Less:
```less
.setColor(@color, @bg) {
color: @color;
background-color: @bg;
}
.card {
.setColor(darkgray, lightblue)
}
```
Stylus:
```styl
setColor(color, bg)
color color
background-color bg
.card
setColor(darkgray, lightblue)
```
Все примеры кода выведут один и тот же CSS:
```css
.card {
color: darkgray;
background-color: lightblue;
}
```
### Функции
Нужны, когда надо переиспользовать только значение свойства.
Sass:
```sass
@function gradient($from, $to)
@return linear-gradient(to bottom, $from 10%, $to 90%)
.red-to-white
background-image: gradient(red, white)
.green-to-black
background-image: gradient(green, black)
```
SCSS:
```scss
@function gradient($from, $to) {
@return linear-gradient(to bottom, $from 10%, $to 90%);
}
.red-to-white {
background-image: gradient(red, white);
}
.green-to-black {
background-image: gradient(green, black);
}
```
Less:
```scss
.gradient(@from, @to) {
@result linear-gradient(to bottom, @from 10%, @to 90%);
}
.red-to-white {
background-image: .gradient(red, white)[@result];
}
.green-to-black {
background-image: .gradient(green, black)[@result];
}
```
Stylus:
```styl
gradient(from, to)
linear-gradient(to bottom, from 10%, to 90%)
.red-to-white
background-image gradient(red, white)
.green-to-black
background-image gradient(green, black)
```
Все примеры выше выведут одинаковый CSS:
```css
.red-to-white {
background-image: linear-gradient(to bottom, red 10%, white 90%);
}
.green-to-black {
background-image: linear-gradient(to bottom, green 10%, black 90%)
}
```
## Пост-процессоры: PostCSS и иже с ним
А есть ещё понятие “пост-процессоры”. Оно родилось, чтобы отличать их от препроцессоров, но довольно быстро PostCSS оброс такими инструментами, что разница сильно размылась: появились переменные, примеси, функции, циклы и так далее.
Вообще, самое первое, зачем нужны пост-процессоры — это Autoprefixer. Он расставляет за вас вендорные префиксы, о которых говорилось ранее.
Но есть и другие весьма интересные инструменты, например:
- [`postcss-momentum-scrolling`](https://github.com/solversgroup/postcss-momentum-scrolling) исправляет проблему, когда на iOS ломается плавная прокрутка на элементах с `overflow: scroll` / `auto`.
- [`postcss-image-set-polyfill`](https://github.com/SuperOl3g/postcss-image-set-polyfill) позволяет использовать `image-set`
- [`postcss-easing-gradients`](https://github.com/larsenwork/postcss-easing-gradients) делает градиенты мягче и симпатичнее
Но есть и крупные инструменты на PostCSS, с помощью которых можно вообще отказаться от Sass / Less / Stylus в пользу, например, [CSSNext](https://cssnext.github.io/) — это набор PostCSS-плагинов, собранный для того, чтобы составить конкуренцию менее гибким препроцессорам, и писать CSS, соответвующий ранним черновикам спецификации, а на выходе получать рабочий в нынешних браузерах.