Стили и оформление
Оформление сайта складывается из трёх слоёв, подключаемых в <head> в таком порядке:
- Стили темы — базовая вёрстка и значения по умолчанию.
- Токены дизайна (
/site/design) — закрытый список именованных значений: цвета, радиус, типографика восьми уровней, ширины и отступы. Выводятся CSS-переменными поверх умолчаний темы. - Собственный CSS сайта (
/site/css) — произвольный лист, который подключается последним и перебивает всё остальное.
Разметку фреймов вы пишете сами, поэтому и стили к ней — ваши: классы фреймов оформляются в собственном CSS. Токены нужны, чтобы менять значения, которые использует тема и общие блоки, не переписывая их правила.
Токены дизайна
curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/design" \
| jq '{theme, total, changed, tokens: (.tokens | with_entries(select(.key | startswith("color."))) | map_values({value, default, source, css_var}))}'
Ответ перечисляет все токены с текущим значением, умолчанием темы, источником (default — стоит умолчание, site — задано сайтом), CSS-переменной и типом. Это же и ответ на вопрос «что вообще можно менять». Умолчания читаются из файла переменных активной темы (defaults_source); ?theme=<имя> показывает умолчания другой установленной темы.
| Токен | Тип | Переменная | Значение по умолчанию (тема onpress-v2) |
|---|---|---|---|
color.primary | цвет | --primary-color | #000000 |
color.secondary | цвет | --secondary-color | #ffd426 |
color.background | цвет | --bg-color | #ffffff |
color.background_alt | цвет | --bg-second-color | #f7f7f7 |
color.text | цвет | --font-main-color | rgba(0, 0, 0, 1) |
color.text_muted | цвет | --font-second-color | rgba(81, 81, 81, 1) |
color.link | цвет | --link-color | rgba(63, 140, 227, 1) |
color.line | цвет | --line-color | rgba(221, 221, 221, 1) |
color.accent | каналы RGB | --primary | от color.primary |
color.accent_light, color.accent_dark | каналы RGB | --primary-light, --primary-dark | от color.primary |
radius.default | px | --border-radius-default | 5px |
skin | lined или pure | — | lined |
layout.container_width | длина | --container-max-width | calc(910px + var(--padding, 2.5rem) * 2) |
layout.padding | длина | --padding | 2.5rem |
layout.padding_mobile | длина | --padding-container-mobile | 9px |
layout.header_height | длина | --header-height | calc(3.625rem - 1px) |
layout.border_width | длина | --border-width | 1px |
<уровень>.font | строка | --<уровень>-ff | "Inter", "Inter Fallback", sans-serif |
<уровень>.size | px, число | --<уровень>-fz | h1 — 48, абзац — 16 |
<уровень>.weight | целое 1–1000 | --<уровень>-fw | h1 — 700, абзац — 400 |
<уровень>.line_height | 0.5–4 | --<уровень>-lh | h1 — 1.2, абзац — 1.5 |
<уровень>.letter_spacing | em, −1…1 | --<уровень>-ls | h1 — −0.05, абзац — −0.02 |
<уровень>.color | цвет | --<уровень>-color | #000000 |
Уровни типографики: h1, h2, h3, h4, h5, h6, subtitle, paragraph. Всего 66 токенов.
Поменять
curl -s -X PATCH "$API/site/$SITE/design" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"tokens": {"color.primary": "#0055ff", "h2.size": 40, "layout.container_width": "1200px"}}' \
| jq '{applied, changed, css, cache: .cache.status}'
{
"applied": true,
"changed": [
{ "token": "color.primary", "value": "#0055ff", "css_var": "--primary-color", "store": "onpress-sidepanel-design" },
{ "token": "h2.size", "value": 40, "css_var": "--h2-fz", "store": "onpress-sidepanel-typography" },
{ "token": "layout.container_width", "value": "1200px", "css_var": "--container-max-width", "store": "onpress_design_tokens" },
{ "token": "color.accent", "value": "0 85 255", "css_var": "--primary", "store": "onpress_design_tokens", "derived": true }
],
"css": "html:root{--container-max-width:1200px;--primary:0 85 255;--primary-light:64 128 255;--primary-dark:0 64 191;}",
"cache": "flushed"
}
- Меняются только названные токены, остальные остаются как были.
- Значения проверяются: цвет —
#rrggbb,rgb()/rgba()или ключевое слово; длина — с единицей илиcalc(); размеры, насыщенность, интерлиньяж и трекинг — в своих диапазонах. Неверное значение —400 bad_token_value, неизвестное имя —400 unknown_token; в обоих случаях не пишется ничего. - Интерлиньяж пишется множителем (
1.2, не120%), трекинг — в em (-0.05, не-5%). - Токены типа px (
radius.default,<уровень>.size) принимают число:8, а не"8px"— строка с единицей даст400 bad_token_value. Длины (layout.*) — наоборот, с единицей:"1200px","2.5rem",calc(…). dry_run: true— отчёт в том же виде, без записи.flush_cache: false— не сбрасывать кэш страниц (по умолчанию сбрасывается весь кэш сайта: токены стоят в каждой странице).- Тема хранит типографику уровнем целиком, поэтому задать одно свойство уровня (
h1.size) значит закрепить весь уровень: остальные свойстваh1запишутся текущими умолчаниями, и уровень станетsite.
Акцент документации
Шаблон документации и доковые блоки красят акцентом через rgb(var(--primary)), поэтому --primary хранит не hex, а три канала через пробел: 22 110 63. Токен color.primary сам вычисляет color.accent и светлый и тёмный варианты (смешивание с 25% белого и чёрного) — пока вы не зададите их руками. На входе color.accent принимает hex, rgb() или готовые каналы и хранит каналы. Не конвертируйте значение ещё раз на своей стороне.
Где токены работают
На обычных страницах темы — все. На страницах шаблона документации типографика и ширины токенами не управляются: внутри тела документа шрифт, размеры, насыщенность и интерлиньяж наследуются от вёрстки документации, а ширины заданы её собственными правилами. Там работает акцент (color.primary или color.accent*). На страницах ваших фреймов токены работают ровно настолько, насколько ваша разметка и CSS используют эти переменные.
Сбросить
# отдельные токены
curl -s -X DELETE "$API/site/$SITE/design" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"tokens": ["color.primary", "h2.size"]}' | jq .
# всё — сайт возвращается к умолчаниям темы
curl -s -X DELETE "$API/site/$SITE/design" -H "Authorization: Bearer $OP_TOKEN" | jq .
Сброс color.accent (или color.primary, пока акцент вычисляется от него) снимает все три переменные акцента сразу. Уровень типографики, у которого не осталось своих значений, удаляется целиком.
Собственный CSS сайта
Произвольный CSS, который подключается после всех стилей темы и токенов на каждой странице сайта. Хранится в опциях сайта; тема выводит его в <style> в конце <head>, поэтому он выигрывает порядком — поднимать специфичность и писать !important не нужно.
Прочитать
# только сводка: размер, строки, дата, куски; без тела
curl -s -H "Authorization: Bearer $OP_TOKEN" \
"$API/site/$SITE/css?include_css=0&count=.site-header,.opfaq" | jq '{bytes, lines, meta, blocks, counts}'
# целиком
curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/css" | jq -r .css > site.css
{
"bytes": 109851,
"lines": 3130,
"meta": { "updated_at_gmt": "2026-09-24 08:21:04", "updated_by": 1, "bytes": 109851, "source": "task-34-accent-tokens", "stripped": [] },
"blocks": [
{ "name": "HEADER FRAME", "from": 92, "to": 1035, "lines": 942, "bytes": 20260 },
{ "name": "DOCS SIDEBAR", "from": 1893, "to": 2483, "lines": 589, "bytes": 18910 }
],
"counts": { ".site-header": 127, ".opfaq": 34 }
}
include_css=0 отдаёт всё, кроме самого листа (живой лист весит 100–150 КБ, а цифры нужны сразу), и ставит css_omitted вместо css, чтобы «лист пуст» и «тело не просили» различались. count — до 20 подстрок через запятую, ответ counts — сколько раз каждая встречается.
Блоки внутри листа
Лист удобно делить на именованные куски, у каждого — своя зона ответственности (шапка, подвал, документация). API распознаёт две формы маркеров и отдаёт опись в blocks:
/* ==== HEADER FRAME — START ==== */
.site-header{…}
/* ==== HEADER FRAME — END ==== */
:root{--header-frame:1}
.site-header{…}
:root{--header-frame-end:1}
Вторая форма переживает минификацию. blocks — закрытые куски с номерами строк маркеров, blocks_unclosed — открытые и не закрытые (всё, что после такого маркера, окажется внутри чужого куска), outside_bytes — непустые байты вне кусков. Правило работы с общим листом: правьте только свой кусок и заливайте лист целиком.
Записать
curl -s -X PUT "$API/site/$SITE/css" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d "$(jq -n --rawfile css site.css '{css: $css, source: "redesign-header"}')" \
| jq '{applied, bytes, stripped, warnings, cache: .cache.status}'
PUT (или POST — то же самое) заменяет лист целиком. Порядок работы: GET → правка своего куска → PUT всего листа. Поле source — метка записи, видна в meta.source.
Что вырезается. Контракт узкий: результат безопасен внутри <style>. Удаляются закрывающий </style>, теги <script>, адреса javascript: и vbscript:, expression( и управляющие символы; незакрытый комментарий /* закрывается автоматически. @import остаётся, но с предупреждением. Всё вырезанное перечислено в stripped (правило, сколько раз, почему, примеры) — ничего не пропадает молча. Проверить без записи — dry_run: true, ответ несёт очищенный css.
{
"stripped": [
{ "rule": "style_close_tag", "count": 1, "reason": "закрывающий тег </style> прекращает элемент стилей и пускает остаток как разметку", "samples": ["</style>"] },
{ "rule": "script_tag", "count": 2, "reason": "тег <script> в стилях не нужен", "samples": ["<script>", "</script>"] }
],
"css": "body{color:red}alert(1)"
}
Предел — 256 КБ (413 css_too_large). Пустая строка допустима и означает «ничего». После записи сбрасывается весь кэш страниц сайта (cache: flushed, empty, skipped при flush_cache: false, failed); неудачный сброс не отменяет запись.
Удалить
curl -s -X DELETE "$API/site/$SITE/css" -H "Authorization: Bearer $OP_TOKEN" | jq '{cleared, cache: .cache.status}'
Сайт возвращается к стилям темы и токенам.
Что оформлять своим CSS
Разметка платформенных вставок стабильна, на неё можно писать правила:
| Вставка | Корневой класс и элементы |
|---|---|
onpress/menu | ul.<class>, li.menu-item, .current-menu-item; свёрнутое — .<class>--dropdown, .<class>__summary |
onpress/lang-switcher | .<class>, .<class>__item, .is-current, .<class>__link, .<class>--dropdown, .<class>__menu |
onpress/footer-columns | .<class>__column, .<class>__title, .<class>__list |
onpress/faq | .opfaq, .opfaq__list, .opfaq__item, .opfaq__q, .opfaq__q-text, .opfaq__a |
onpress/callout | .op-callout, .standard-alert__alert--<вариант>, .standard-alert__title, .standard-alert__description |
onpress/featured-image | .op-featured-image, .op-featured-image__caption |
onpress/terms | .<class>, .<class>__list, .<class>__item, .<class>__link |
Картинки из текста выводятся как figure.wp-block-image с picture, таблицы — figure.wp-block-table, код — pre.wp-block-code > code.language-<язык>, заголовки — h2.wp-block-heading с id.