good-css — 47 приёмов современного CSS, собранные в скилл для кодинг-агента
📂 Исходный код на GitHubСписок из 47 приёмов современного CSS, упакованный в скилл для кодинг-агентов: логические свойства вместо left и right, цвета в oklch(), размеры через clamp(), container queries, :has(), нативная прокрутка вместо карусели на скрипте. У каждого приёма есть CSS, объяснение, список правил, строка поддержки браузерами и автор, у которого приём взят. Лицензия MIT.
Репозиторий good-css собирает в один список приёмы современного CSS и упаковывает этот список в скилл для кодинг-агента. Установленный скилл меняет то, до чего агент тянется первым делом. Вместо лестницы брейкпоинтов он берёт одно свойство, которое само подстраивается под экран. Вместо скрипта — возможность, которая уже есть в CSS. Скрипт нужен только там, где он делает результат лучше, и только если результат работает и без него.
Что внутри репозитория
В репозитории три части, и у каждой своя роль.
Список для людей — файл PRACTICES.md. В нём 47 записей. У каждой записи одинаковая форма: когда применять приём, сам CSS, объяснение, почему он работает, список правил, строка поддержки браузерами и автор, у которого приём взят. Среди авторов: Кевин Пауэлл, Ахмад Шадид, Хейдон Пикеринг, Энди Белл, Джош Комо, Эмиль Ковальский, Ана Тюдор.
Список для агентов — папка skills/good-css, а входной файл в ней — SKILL.md. Это тот же список, но сокращённый до того, что нужно агенту во время работы. Записи разложены по восьми темам: основы, раскладка, отступы и формы, текст и картинки, взаимодействие, анимация, показ и скрытие элементов, прокрутка и экран.
Живые примеры — сайт good-css.com. Там каждая запись показана как работающий образец, а не как код в блоке.
Лицензия — MIT. Заодно список работает как указатель на первоисточники приёмов.
Правила, которые агент применяет всегда
Этот список агент держит в голове постоянно, без чтения файлов.
- Логические свойства вместо
left,right,topиbottom:padding-inline,margin-block-end,inset-block-start. На странице с направлением письма справа налево тот же код перевернётся сам. - Цвета в
oklch(). Для серого, белого и чёрного оттенок пишется какnone. Все производные цвета делаются черезcolor-mix(in oklch, …), а не новым значением вручную. - Размеры, которые растут вместе с экраном, живут в одном токене через
clamp(). - Каждое правило
:hoverпрячется внутрь@media (hover: hover) and (pointer: fine). Иначе на телефоне состояние наведения залипает после касания. - Фокус рисуется через
:focus-visibleиoutline. Правилоoutline: noneзапрещено. - У всего, на что можно нажать, есть состояние
:active. - Анимация, которая двигает или масштабирует, живёт внутри
@media (prefers-reduced-motion: no-preference). Свойства перечисляются по именам, а не словомall. - Лишнее обрезается через
overflow: clip. Значениеhiddenостаётся только там, где прокруткой управляет скрипт.
Несколько приёмов из списка
Сетка, которая сама решает, сколько в ней колонок. Одно правило заменяет подсчёт колонок для каждой ширины экрана.
.grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}
auto-fit создаёт столько колонок по 16rem, сколько помещается в контейнер. 1fr делит остаток. min(100%, 16rem) позволяет минимуму сжаться до ширины контейнера, без этого узкий контейнер переполняется. Значение auto-fill нужно там, где число карточек меняется, например в отфильтрованном списке: тогда карточки сохранят размер.
Отступы между секциями, которые зависят от соседей. Секция сама узнаёт, кто стоит рядом, и подстраивает свой край.
section { padding-block: 6rem; }
.logos:has(+ .features) { padding-block-end: 2rem; }
.features:has(+ .cta) { padding-block-end: 0; }
.hero + .logos { padding-block-start: 2rem; }
Селектор A:has(+ B) смотрит вперёд и меняет нижний край A. Селектор A + B смотрит назад и меняет верхний край B. Правила описывают пары, а не страницы. Как бы редактор ни переставил секции, каждая встречающаяся пара получит свои отступы, а остальное сохранит значение по умолчанию. Разделительный элемент для отступа при этом не нужен.
Слои друг на друге без position: absolute. Текст поверх картинки, бейдж на карточке, две иконки, которые меняются местами.
.stack { display: grid; }
.stack > * { grid-area: 1 / 1; }
.stack > .title { place-self: center; }
.stack > .badge { place-self: start end; }
Все дети попадают в одну ячейку и накладываются друг на друга. При этом слои остаются в потоке, и контейнер занимает размер самого большого из них. Элемент с position: absolute размеру контейнера не добавляет ничего.
Карточка целиком открывается по одной ссылке. Вместо ссылки вокруг всей карточки.
.card { position: relative; }
.card-link::after {
content: "";
position: absolute;
inset: 0;
}
Псевдоэлемент принадлежит ссылке и накрывает карточку, поэтому клик в любом месте срабатывает. Это настоящая ссылка, так что «открыть в новой вкладке» и адрес в строке состояния продолжают работать. Скринридер читает только текст ссылки, а не всю карточку. Кнопки внутри карточки поднимаются над накрытием через position: relative и z-index: 1.
Карусель на нативной прокрутке. Ряд карточек, который листается пальцем, трекпадом и клавиатурой без единой строки скрипта.
.carousel {
display: flex;
gap: 1rem;
overflow-x: auto;
scroll-snap-type: x mandatory;
overscroll-behavior-x: contain;
scrollbar-width: none;
}
.carousel > * {
flex: none;
scroll-snap-align: start;
}
Получается настоящий прокручиваемый контейнер, поэтому свайп, трекпад, клавиатура и инерция работают уже до загрузки скриптов. Привязка к карточкам делает остановку ровной. overscroll-behavior-x: contain не даёт свайпу у края списка вызвать жест «назад» в браузере. Скрипт нужен только для стрелок, и он двигает список на ширину одной карточки через scrollBy().
Поддержка браузерами
Скилл не задаёт минимальную версию браузера. У большинства записей в конце есть строка Support с версиями по браузерам. Агент должен сопоставить её с теми браузерами, которые нужны проекту, и сказать вслух, если что-то из использованного там не поддерживается. Какие браузеры считать поддерживаемыми, решает проект, а не список.
Как список поддерживается
PRACTICES.md — единственное место, где пишутся записи. Файлы в папке references генерируются из него скриптом и не содержат объяснений и авторов.
bun install
bun scripts/build-skill.js # write the reference files
bun scripts/build-skill.js --check # fail if they are out of date
bun dev # the preview site, on localhost:4310
Файл skills/good-css/SKILL.md написан вручную. Правила изменения репозитория лежат в AGENTS.md. Pull-запросы отправляют на исправления, а новые записи и смена мнения начинаются как issue. Что считается исправлением, описано в CONTRIBUTING.md.
Установка
Для любого агента, который понимает формат Agent Skills — Claude Code, Codex, Cursor:
npx skills@latest add vojtaholik/good-css
Установщик спросит, для каких агентов поставить. Флаг -g ставит скилл для всех проектов на машине.
Для Claude Code как плагин:
claude plugin marketplace add vojtaholik/good-css
claude plugin install good-css@good-css
Вручную достаточно скопировать папку skills/good-css в папку, из которой агент читает скиллы: .claude/skills/ для Claude Code и .agents/skills/ для Codex и Cursor, в проекте или в домашней папке. Выбирать надо один способ: две установки дадут агенту скилл дважды.
Сам скилл просит агента ставить себя только по просьбе пользователя. Если установить ничего нельзя, он читает SKILL.md из репозитория и объясняет пользователю, как поставить его вручную.
Зачем это
Проблема, которую решает репозиторий, знакомая любому, кто работает с агентами над вёрсткой. Модель по умолчанию пишет то, что чаще всего встречалось в обучающих данных: лестницу брейкпоинтов, обвязку из лишних div, обработчик click там, где хватает :hover. Такие решения работают, но они старше, чем возможности платформы.
good-css не добавляет новых приёмов — он отбирает существующие и записывает их в том виде, в котором агент сможет применить их сразу. Каждая запись короткая, с готовым CSS и правилами, которые нельзя нарушать. Список пополняют не новыми вкусами автора, а чужими решениями, у каждого есть имя.
Источник: https://github.com/vojtaholik/good-css