good-css — 47 приёмов современного CSS, собранные в скилл для кодинг-агента

· 6 мин чтения
css skills frontend best-practices
📂 Исходный код на GitHub

Список из 47 приёмов современного CSS, упакованный в скилл для кодинг-агентов: логические свойства вместо left и right, цвета в oklch(), размеры через clamp(), container queries, :has(), нативная прокрутка вместо карусели на скрипте. У каждого приёма есть CSS, объяснение, список правил, строка поддержки браузерами и автор, у которого приём взят. Лицензия MIT.

good-css — 47 приёмов современного CSS, собранные в скилл для кодинг-агента

Репозиторий 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