Изоляция CSS
Андрей Ситник, Злые Марсиане
Злые марсиане
Работаем над
Наш опенсорс
Глава 1 Проблема
Зачем нам ИТ?
Рост сложности
3 объекта
6 объектов
3 связи
15 связей
Решение роста
Компоненты сети
Компоненты ОС
Компоненты JavaScript
import Logo from '../logo';
export const Header = () => (
<div class="header">
<Logo></Logo>
</div>
);
Компоненты дизайна
Глобальный CSS :-(
* {
box-sizing: border-box;
}
.title {
font-size: 30px;
}
Глава 2 Четыре всадника CSS
Всадник 1 Конфликт селекторов
/* logo.css */
.name {
color: gray;
}
/* header.css */
.name {
color: red;
}
БЭМ
window.prefixA = …;
window.prefixB = …;
Всадник 2 Глобальный сброс
* {
box-sizing: border-box;
}
Всадник 3 Наследуемые свойства
body
.header
.logo
line-height: 1.4
line-height: 1.4
line-height: 1.4
Агрессивные селекторы
.article p {
margin-bottom: 1em;
}
Всадник 4 Медиа-выражения страницы
.logo:container( width <= 100px ) {
.name {
display: none;
}
}
Четыре всадника
Конфликт селекторов
Глобальный сброс
Наследуемые свойства
Медиа-выражения страницы
Глава 3 Революция
PostCSS
CSS
карта кода
Генератор
Парсер
Плагин
Плагин
Новый CSS
новая карта
Задачи
Sass
PostCSS
Код
return gulp.src('src/*.scss')
.pipe( sass() )
.pipe( postcss(plugins) )
.pipe( gulp.desc('build/') );
Глава 4 Побеждаем глобальный CSS
Шаг 1 Чистая комната
gulp.task('css:new', () => {
return gulp.src('src/new/')
.pipe( postcss([
// other plugins
require('autoprefixer')
]) )
.pipe( gulp.dist('build/') )
});
Шаг 2 Нарежьте дизайн на блоки
Шаг 3 Папка для компонента
logo/ logo.js logo.css company.svg header/ header.js header.css
js/ logo.js header.js css/ logo.css header.css images/ company.svg
postcss([,
require('postcss-modules'),
require('autoprefixer')
])
Пишите любые селекторы
.name {
color: red;
}
.Logo_name_jbds3 {
color: red;
}
Шаблон
var style = require('./logo.css.json');
export const Logo = () => (
<div className={ style.name }>
</div>
);
Работает с PHP и Rails
- style = load_json('logo.css.json');
%div{ class: style.name }
CSS Modules против БЭМ
Первая победа
Конфликт селекторов
Глобальный сброс
Наследуемые свойства
Медиа-выражения страницы
Локальный сброс
h1, h2, …, div {
/* сброс */
}
.header {
/* стили */
}
.logo {
/* стили */
}
.header, .logo {
/* сброс */
}
.header {
/* стили */
}
.logo {
/* стили */
}
Локальный сброс
body
.header
.logo
line-height: 1.4
line-height: 1
line-height: 1
Плюсы локального сброса
Сброс по W3C
.logo {
all: initial;
}
Шаг 5 postcss-autoreset
require('postcss-autoreset')({
reset: {
all: 'initial',
font: 'inherit',
boxSizing: 'border-box'
}
})
Шаг 6 postcss-cssnext
postcss([
require('postcss-modules'),
require('postcss-autoreset'),
require('postcss-cssnext'),
require('autoprefixer')
])
Полифил будущего CSS
.logo {
all: initial;
}
.logo {
display: block;
border: none;
padding: 0;
margin: 0;
…
}
Ещё две победы
Конфликт селекторов
Глобальный сброс
Наследуемые свойства
Медиа-выражения страницы
Шаг 7 cq-prolyfill
<script src="cq-prolyfill.min.js" async>
</script>
postcss([
…,
require('cq-prolyfill/postcss-plugin'),
…
])
Медиа-выражения контейнера
.logo:container( width >= 100px ) {
…
}
.logo:container( text-align = right ) {
…
}
.logo:container( background-color lightness > 20% ) {
…
}
Полная изоляция
Конфликт селекторов
Глобальный сброс
Наследуемые свойства
Медиа-выражения страницы
Глава 5 Плюсы
Без вопросов
Проще тестировать
Проще обновлять технологии
old/ logo/ new/ header/
Авто. оптимизации
.Logo_name_jb4 {
color: black;
}
.Header_top_e63 {
color: black;
}
.Logo_name_jb4,
.Header_top_e63 {
color: black;
}
Глава 6 Советы
Главное зло
.logo {
&.is-in-header {
width: 100px;
height: 100px;
padding: 10px 0;
}
&.is-in-footer {
…
}
}
Совет 1 Пишите размеры в обёртках
<div className={ style.place }>
<Logo>
</div>
.place {
width: 100px;
height: 100px;
padding: 10px 0;
position: relative;
}
.logo {
width: 100%;
height: 100%;
}
Совет 2 Вкладывайте друг в друга
<Button icon="remove" />
<Button>
<RemoveIcon>
</Button>
Финал
Полная изоляция
postcss([
// Изоляция селекторов
require('postcss-modules'),
// Локальный сброс
require('postcss-autoreset'),
require('postcss-cssnext'),
// Контейнерные выражения
require('cq-prolyfill/postcss-plugin'),
require('autoprefixer')
])
@evilmartians
evl.ms/chronicles