Эта страница переведена машинным способом и может содержать ошибки. Читать оригинал на английском

API

Справочник по Tailwind

Каждый элемент принимает классы Tailwind CSS в свойстве class (а условные классы, в classList). NSH разбирает их в Rust по стандартной теме Tailwind 4: JS передаёт только строку, каждая уникальная строка разбирается один раз и кэшируется, а варианты вроде dark: или active: пересчитываются нативно при смене оформления, размера окна или состояния нажатия, без запуска JS.

Каждая утилита задаёт ровно то, что для неё генерирует Tailwind CSS 4, с тем же смыслом, что и в браузере. На этой странице перечислено то, что поддерживается. Введение см. в разделе Tailwind; ключи стиля, которые задают утилиты, описаны в справочнике по стилям.

Компоненты Rust не принимают строки классов: они стилизуют элементы типизированными методами Styled (nsh_core::prelude), названными по этим утилитам и разрешающимися в те же значения, включая стандартные шкалы Tailwind (px-4 это .px_4(), rounded-2xl это .rounded_2xl(), shadow-md это .shadow_md(), bg-linear-to-br это .bg_linear_to_br()). Цвета являются значениями: цвета темы или палитра Tailwind в виде nsh_core::element::palette (ZINC.shade(800) это zinc-800). Варианты это методы, принимающие замыкание со стилями: .active(|s| …), .hover(…), .focus(…), .disabled_style(…), .dark(…), .group_active(…), а для остальных .style_when(condition, …). Справочник по стилям указывает метод для каждого ключа стиля.

use nsh_core::{element::palette::{RED, ZINC}, prelude::*};

view()
    .flex_row()
    .items_center()
    .gap_3()
    .rounded_2xl()
    .bg(white())
    .p_4()
    .shadow_md()
    .active(|s| s.scale(0.98))
    .transition()
    .dark(|s| s.bg(ZINC.shade(800)))
    .child(
        text("Inbox")
            .text_base()
            .font_weight(FontWeight::SEMIBOLD)
            .text_color(ZINC.shade(900))
            .dark(|s| s.text_color(white())),
    )
    .child(
        text(move || unread.get().to_string())
            .text_color(move || if unread.get() > 0 { RED.shade(500) } else { ZINC.shade(400) }),
    )

#Как комбинируются классы

  • Побеждает последний. Среди утилит одного уровня варианта побеждает та, что стоит в строке позже: "p-4 p-2" это p-2. Компонент может принять свойство class и добавить его к своим классам без tailwind-merge.
  • Варианты применяются после обычных утилит в порядке вариантов Tailwind: group-*: (по их состоянию, затем по имени группы), selection:, placeholder:, позиция (first: …), checked:, indeterminate:, selected:, focus-within:, hover:, focus:, focus-visible:, active:, enabled:, disabled:, aria-busy:, aria-checked:, aria-expanded:, aria-pressed:, aria-selected:, data-*: (по имени), движение, точки останова max-*: от самых широких, затем точки останова по возрастанию, ориентация, направление, dark:, затем платформа. Решает старший вариант класса, затем следующий по старшинству, а класс с ещё одним вариантом идёт позже (dark:hover: после dark:), так же как их сортирует Tailwind. Поэтому "active:bg-red-500 bg-blue-500" красный, пока элемент нажат.
  • style побеждает классы. Инлайновый style применяется поверх разрешённых классов. Ключ стиля это CSS-свойство с тем же именем, которое задают утилиты, поэтому он заменяет только это свойство и ничего больше: style={{ paddingLeft: 8 }} перекрывает pl-4 и сохраняет pr-4. Важная утилита (!p-4 или p-4!) побеждает и инлайновый стиль.
  • Стили текста наследуются. Текстовые утилиты на представлении (text-white, font-bold, text-center, …) передаются вложенным в него элементам <Text> и <Input>, как в CSS.
  • Display работает как в CSS. flex и inline-flex дают строку, если утилита направления не указывает иное, где бы она ни стояла в строке (flex-col flex это столбец). display: "flex" в стиле так же означает строку; представления, не задающие display, сохраняют столбец по умолчанию, принятый в NSH.

#Единицы измерения и тема

Длины измеряются в пунктах (1 = один пункт на iOS, один dp на Android). 1rem в Tailwind равен 16 пунктам, поэтому тема совпадает с веб-версией при той же плотности: один шаг отступа равен 4 пунктам (p-4 = 16 пунктов), text-base равен 16 пунктам.

#Значения отступов

Утилиты, принимающие значение отступа (padding, margin, gap, inset, ширина, высота, basis, translate, leading), допускают:

ЗначениеПримерРезультат
Шаги (допускаются четверти шага)p-4, gap-1.5, m-0.25шаг × 4 пункта
pxp-px, -mt-px1 пункт
0m-00
Дробь (inset, ширина, высота, basis, translate)w-1/2, left-1/3процент от родителя
full (то же самое)w-full, inset-full100%
auto (margin, inset, ширина, высота, basis)mx-auto, w-auto"auto"
Произвольноеp-[13px], w-[42%], mt-[1.5rem]заданная длина

Margin, inset, translate, rotate, skew, scale, z, hue-rotate, tracking, underline-offset, outline-offset, линии сетки и углы градиента принимают ведущий - для отрицательных значений: -mt-2, -translate-x-1/2, -rotate-6. У остальных (-p-4, -gap-2, -w-4) в Tailwind нет отрицательной формы, нет её и в NSH.

#Цвета

Полная палитра Tailwind 4 встроена: red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose, slate, gray, zinc, neutral, stone, mauve, olive, mist, taupe, каждый в оттенках 50, 100–900, 950; а также black, white и transparent. Собственные цвета берутся из nsh.json (см. Настройка темы).

Каждая цветовая утилита принимает:

ФормаПример
Цвет темыbg-sky-500, text-brand
Модификатор прозрачности (в процентах)bg-black/50, ring-black/5
Произвольная прозрачностьtext-black/[0.35]
Произвольный цветbg-[#0ea5e9], border-[rgb(0_0_0_/_0.1)], text-[oklch(70%_0.2_50)]
Произвольный цвет с модификаторомbg-[rgb(0_0_255)]/25

currentColor и inherit не являются значениями цвета. Как и в браузере, граница, outline или ring без цветового класса рисуется цветом текста элемента, собственным или унаследованным (<View class="text-white"><View class="border ring-2" /></View> рисует оба белым), и так же рисуется граница, толщину которой задаёт свойство style без цвета.

#Произвольные значения

Квадратные скобки передают значение, которого нет в теме: w-[37px], grid-cols-[200px_1fr], bg-[linear-gradient(45deg,red,blue)].

  • _ обозначает пробел (grid-cols-[1fr_2fr]); для буквального подчёркивания пишите \_.
  • Длины: просто число или px (пункты), pt (4/3 пункта, как в CSS), rem (16 пунктов) и % там, где уместны проценты.
  • Углы (rotate-[...], hue-rotate-[...], bg-linear-[...]): deg, rad, grad, turn.
  • Время (duration-[...], delay-[...]): ms или s; просто число означает миллисекунды.
  • Подсказки типа разрешают неоднозначные значения: text-[length:22px] это размер, text-[color:#333] цвет; border-[length:3px] аналогично.

Произвольные CSS-свойства ([mask-type:luminance]) не поддерживаются.

#Раскладка

КлассЗадаёт
flex, inline-flexdisplay: "flex", и строку, если не задана утилита направления
grid, inline-griddisplay: "grid"
block, flow-rootблочную раскладку или независимый контекст блочного форматирования
box-border, box-contentразмеры включают границы и отступы или только содержимое
w/h/size-min, w/h/size-max, w/h/size-fitвнутренние размеры Taffy: min-content, max-content, fit-content
inline, inline-blockdisplay: "block": то, что браузер вычисляет для них во flex- или grid-родителе
hiddendisplay: "none"
relative, absoluteposition
staticposition: "static": в потоке, его смещения игнорируются; абсолютные потомки используют ближайшего позиционированного предка
stickyposition: "sticky": в потоке, прилипает к top (left в горизонтальном scroll view) внутри окружающего scroll view, пока виден его родитель
fixedposition: "fixed": элемент, размещённый в рамке своего корневого представления (окна или его модального окна) поверх дочерних элементов этого корневого представления, остаётся на месте, пока окружающее содержимое прокручивается
inset-<n>, inset-x-<n>, inset-y-<n>top / right / bottom / left
top-<n>, right-<n>, bottom-<n>, left-<n>соответствующее смещение
start-<n>, end-<n>start / end (с учётом направления)
z-<n>, z-auto, z-[<n>]zIndex (z-auto равно 0)
visiblevisibility: "visible"
invisible, collapsevisibility: "hidden" (сохраняет своё место)
overflow-hidden, overflow-clip, overflow-x-hidden, overflow-y-hiddenoverflow: "hidden"
overflow-visibleoverflow: "visible"
aspect-square, aspect-video, aspect-<a>/<b>, aspect-[<a>/<b>], aspect-autoaspectRatio (1, 16/9, a/b, нет)

Прокрутка это элемент, а не класс: overflow-auto и overflow-scroll не поддерживаются; используйте scroll.

#Flexbox и grid

КлассЗадаёт
flex-row, flex-row-reverse, flex-col, flex-col-reverseflexDirection
flex-wrap, flex-wrap-reverse, flex-nowrapflexWrap
flex-1рост 1, сжатие 1, базис 0
flex-<n>рост n, сжатие 1, базис 0
flex-autoрост 1, сжатие 1, базис auto
flex-initialрост 0, сжатие 1, базис auto
flex-noneрост 0, сжатие 0, базис auto
flex-[<grow>], flex-[<grow>_<shrink>_<basis>]сокращённая запись CSS: flex-[2], flex-[3_0_50%]
grow, grow-<n>, grow-[<n>]flexGrow (без значения: 1)
shrink, shrink-<n>, shrink-[<n>]flexShrink (без значения: 1)
basis-<n>flexBasis (шаг отступа, дробь, full, auto, произвольное)
justify-start, justify-end, justify-center, justify-between, justify-around, justify-evenly, justify-stretch, justify-normaljustifyContent
items-start, items-end, items-center, items-baseline, items-stretchalignItems
self-auto, self-start, self-end, self-center, self-stretch, self-baselinealignSelf
content-start, content-end, content-center, content-between, content-around, content-evenly, content-stretch, content-normalalignContent
justify-items-start, -end, -center, -stretch, -normaljustifyItems
justify-self-auto, -start, -end, -center, -stretchjustifySelf
place-content-center, -start, -end, -between, -stretchalignContent и justifyContent
place-items-center, -start, -end, -stretchalignItems и justifyItems
place-self-auto, -center, -start, -end, -stretchalignSelf и justifySelf
gap-<n>, gap-x-<n>, gap-y-<n>gap, columnGap, rowGap
space-x-<n>, space-y-<n> (и отрицательные)margin у каждого дочернего элемента, кроме последнего: конечный margin (space-x) или нижний (space-y), под собственными margin дочернего элемента, как в Tailwind CSS; добавляется к gap
space-x-reverse, space-y-reverseвместо этого margin с начальной / верхней стороны (дочерние элементы в обратном порядке)
grid-cols-<n>gridTemplateColumns: "repeat(n, minmax(0, 1fr))"
grid-cols-[<tracks>], grid-cols-nonegridTemplateColumns (grid-cols-[200px_1fr])
grid-rows-<n>, grid-rows-[<tracks>], grid-rows-nonegridTemplateRows
col-span-<n>, col-span-full, col-auto, col-<n>, col-[<value>]gridColumn
col-start-<n>, col-end-<n> (и -auto)gridColumnStart, gridColumnEnd
row-span-<n>, row-span-full, row-auto, row-<n>, row-[<value>]gridRow
row-start-<n>, row-end-<n> (и -auto)gridRowStart, gridRowEnd
grid-flow-row, grid-flow-col, grid-flow-dense, grid-flow-row-dense, grid-flow-col-densegridAutoFlow
auto-cols-auto, -min, -max, -fr, auto-cols-[<track>]gridAutoColumns
auto-rows-auto, -min, -max, -fr, auto-rows-[<track>]gridAutoRows

#Отступы

КлассЗадаёт
p-<n>, px-<n>, py-<n>padding, paddingHorizontal, paddingVertical
pt-<n>, pr-<n>, pb-<n>, pl-<n>paddingTop / Right / Bottom / Left
ps-<n>, pe-<n>paddingStart, paddingEnd (с учётом направления)
m-<n>, mx-<n>, my-<n>margin, marginHorizontal, marginVertical
mt-<n>, mr-<n>, mb-<n>, ml-<n>marginTop / Right / Bottom / Left
ms-<n>, me-<n>marginStart, marginEnd (с учётом направления)

#Размеры

КлассЗадаёт
w-<n>, h-<n>width, height (шаг отступа, дробь, full, auto, произвольное)
size-<n>width и height
min-w-<n>, max-w-<n>, min-h-<n>, max-h-<n>соответствующее ограничение
w-screen, w-dvw, w-svw, w-lvwширина окна (также для min-w- / max-w-)
h-screen, h-dvh, h-svh, h-lvhвысота окна (также для min-h- / max-h-)
w-auto, h-autoauto (размер определяется содержимым)
max-w-none, max-h-noneбез ограничения
w-<container>, min-w-<container>, max-w-<container>ширина контейнера (см. ниже)

Ширина контейнеров (в пунктах): 3xs 256, 2xs 288, xs 320, sm 384, md 448, lg 512, xl 576, 2xl 672, 3xl 768, 4xl 896, 5xl 1024, 6xl 1152, 7xl 1280; prose равно 65 ширинам 0 шрифта элемента (65ch в CSS), как в Tailwind CSS.

#Типографика

#Шрифт

КлассЗадаёт
font-sansсистемный шрифт
font-serif, font-monofontFamily: "serif" / "monospace"
font-thin (100), font-extralight (200), font-light (300), font-normal (400), font-medium (500), font-semibold (600), font-bold (700), font-extrabold (800), font-black (900)fontWeight
font-[<weight>], font-[<family>]числовое значение задаёт насыщенность, иначе семейство шрифта: font-[650], font-[Inter]
italic, not-italicfontStyle
normal-nums, small-caps, oldstyle-nums, lining-nums, tabular-nums, proportional-numsfontVariant (они комбинируются; normal-nums сбрасывает формы чисел)

#Размер, цвет и высота строки

text-<size> задаёт размер шрифта и соответствующую высоту строки из Tailwind; её заменяет класс leading-*, где бы он ни стоял в строке и каков бы ни был его вариант (leading-tight md:text-lg сохраняет плотный межстрочный интервал):

КлассРазмерВысота строки
text-xs1216
text-sm1420
text-base1624
text-lg1828
text-xl2028
text-2xl2432
text-3xl3036
text-4xl3640
text-5xl481×
text-6xl601×
text-7xl721×
text-8xl961×
text-9xl1281×
КлассЗадаёт
text-<size>/<leading>размер и высоту строки: text-sm/6 (24 пункта), text-lg/tight
text-[<length>]fontSize: text-[22px], text-[length:22px]
text-<color>color
leading-none (1), leading-tight (1.25), leading-snug (1.375), leading-normal (1.5), leading-relaxed (1.625), leading-loose (2)lineHeight как кратное размера шрифта
leading-<n>, leading-[<length>]lineHeight в пунктах (leading-6 = 24)
leading-[<number>]lineHeight как кратное размера шрифта (leading-[1.5]), наследуется как этот множитель; em и % вычисляют длину при размере шрифта элемента до наследования
tracking-tighter (-0.05em), tracking-tight (-0.025em), tracking-normal (0), tracking-wide (0.025em), tracking-wider (0.05em), tracking-widest (0.1em)letterSpacing относительно размера шрифта
tracking-[<value>]letterSpacing: tracking-[0.2em], tracking-[1px]

#Выравнивание, регистр и перенос

КлассЗадаёт
text-left, text-center, text-right, text-justifytextAlign
text-start, text-endtextAlign: "start" / "end": начало или конец строки в направлении раскладки
align-baseline, align-text-top, align-text-bottom, align-middleverticalAlign (представления и изображения внутри текста)
uppercase, lowercase, capitalize, normal-casetextTransform
truncateодна строка, многоточие в конце, без переноса, overflow: hidden (у представления: его тексты не переносятся)
line-clamp-<n>, line-clamp-nonenumberOfLines (none показывает все строки)
text-ellipsis, text-cliptextOverflow: "ellipsis" / "clip"
whitespace-nowrap, text-nowrapстроки никогда не переносятся; у представления это строки находящихся в нём текстов (наследуется, как white-space в CSS)
whitespace-normal, text-wrap, text-balance, text-prettyстроки переносятся (балансировка не выполняется)
select-text, select-noneuserSelect: "text" / "none"; у представления для находящихся в нём текстов, у которых оно не задано
select-autouserSelect: "auto": решает окружающее представление, как user-select: auto в CSS (select-none md:select-auto)

#Оформление и тень

КлассЗадаёт
underline, line-through, no-underlinetextDecorationLine
decoration-solid, decoration-double, decoration-dotted, decoration-dashed, decoration-wavytextDecorationStyle
decoration-<n>, decoration-[<length>]textDecorationThickness
decoration-auto, decoration-from-fonttextDecorationThickness: "auto"
decoration-<color>textDecorationColor
underline-offset-<n>, underline-offset-[<length>], underline-offset-autotextUnderlineOffset
text-shadow-2xs, -xs, -sm, -md, -lg; /<alpha>текстовая тень из темы (один слой: самый широкий из слоёв темы); модификатор задаёт альфа-канал слоёв: text-shadow-md/20
text-shadow-<color>, text-shadow-currentеё цвет с альфа-каналом размера
text-shadow-noneубирает её

У текстовых теней Tailwind несколько слоёв; нативно рисуется одна тень — самый широкий слой.

#Поля ввода

КлассЗадаёт
placeholder:text-<color>placeholderColor
selection:bg-<color>selectionColor (подсветка выделения в поле ввода или в выделяемом тексте, в том числе внутри элемента)
caret-<color>цвет курсора

#Фоны

КлассЗадаёт
bg-<color>backgroundColor
bg-[<gradient>]backgroundImage: bg-[linear-gradient(45deg,red,blue)], bg-[radial-gradient(...)]
bg-linear-to-t, -tr, -r, -br, -b, -bl, -l, -tlлинейный градиент в сторону или к углу (bg-gradient-to-* — название из v3)
bg-linear-<angle>, bg-linear-[<angle>]линейный градиент под углом: bg-linear-45, -bg-linear-12, bg-linear-[0.25turn]
bg-radialрадиальный градиент от центра
bg-conic, bg-conic-<angle>конический градиент, при необходимости с начальным углом
from-<color>, via-<color>, to-<color>опорные цвета градиента (по умолчанию на концах прозрачные)
from-<p>%, via-<p>%, to-<p>%позиции опорных цветов: via-40%, from-[15%]
bg-noneубирает градиент

Утилиты градиентов смешивают цвета в Oklab, как их записывает Tailwind CSS (in oklab); при произвольной позиции (bg-linear-[25deg], bg-conic-[0.25turn]) они следуют значению CSS по умолчанию: Oklab для цветов палитры и sRGB, когда каждый опорный цвет — hex, rgb(), hsl() или именованный цвет.

view()
    .h_32()
    .rounded_2xl()
    .bg_linear_to_br()
    .gradient_from(INDIGO.shade(500))
    .gradient_via(PURPLE.shade(500))
    .gradient_via_position(percentage(0.4))
    .gradient_to(PINK.shade(500))

#Границы

КлассЗадаёт
border, border-<n>, border-[<length>]borderWidth (без значения: 1)
border-x, border-y, border-t, border-r, border-b, border-l, border-s, border-e (с -<n> или без значения)ширина соответствующих сторон
border-<color>, border-t-<color>, …borderColor и цвета отдельных сторон
border-solid, border-dashed, border-dottedborderStyle
border-none, border-hiddenborderStyle: "none" / "hidden": границы нет независимо от классов ширины, в любом порядке (md:border-solid показывает её снова)
rounded, rounded-<size>, rounded-none, rounded-full, rounded-[<length>]borderRadius (без значения: sm)
rounded-t-, -r-, -b-, -l-, -tl-, -tr-, -br-, -bl-соответствующие углы
rounded-s-, -e-, -ss-, -se-, -es-, -ee-начальные / конечные углы (с учётом направления): borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius
outline, outline-<n>, outline-[<length>]outlineWidth (без значения: 1), сплошная, если в строке нет класса стиля (outline-dashed outline-2 — пунктир, outline-none outline-2 ничего не рисует)
outline-<color>outlineColor
outline-solid, outline-dashed, outline-dotted, outline-none, outline-hiddenoutlineStyle; один стиль даёт среднюю ширину CSS, 3 пункта
outline-offset-<n>, outline-offset-[<length>]outlineOffset

Размеры радиуса (в пунктах): xs 2, sm 4, md 6, lg 8, xl 12, 2xl 16, 3xl 24, 4xl 32, full 9999.

#Кольца

Кольца — это тени блока с растяжением (spread); они рисуются снаружи границы и не занимают места.

КлассЗадаёт
ring, ring-<n>, ring-[<length>]кольцо такой ширины (без значения: 1)
ring-<color>цвет кольца (по умолчанию цвет текста элемента)
ring-insetрисует кольцо внутри
ring-offset-<n>, ring-offset-<color>зазор между элементом и кольцом (по умолчанию белый)
inset-ring, inset-ring-<n>, inset-ring-<color>внутреннее кольцо

#Эффекты

КлассЗадаёт
shadow-2xs, shadow-xs, shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl; /<alpha>boxShadow из темы; модификатор задаёт альфа-канал слоёв: shadow-xl/20
shadow-[<box-shadow>]произвольная тень: shadow-[0_8px_24px_rgb(0_0_0_/_0.12)]
shadow-<color>, shadow-currentперекрашивает слои тени с альфа-каналом размера: shadow-indigo-500/40
shadow-noneнет тени
inset-shadow-2xs, -xs, -sm, inset-shadow, inset-shadow-[...], inset-shadow-<color>, inset-shadow-noneвнутренняя тень
opacity-<n>, opacity-[<value>]opacity: opacity-50 = 0.5
mix-blend-<mode>mixBlendMode: normal, multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color, luminosity, plus-darker, plus-lighter

Тени, кольца и внутренние тени объединяются в один список boxShadow, как в CSS. Цвет тени заменяет цвет каждого слоя, включая альфа-канал, как --tw-shadow-color в Tailwind: shadow-md shadow-red-500 — непрозрачная красная тень, shadow-md/20 shadow-red-500 — тень с альфа-каналом 20%.

#Фильтры

КлассЗадаёт
blur, blur-xs (4), -sm (8), -md (12), -lg (16), -xl (24), -2xl (40), -3xl (64), blur-none, blur-[<length>]blur()
brightness-<n>, contrast-<n>, saturate-<n>коэффициенты в процентах: brightness-125 = 1.25
grayscale, grayscale-<n>, invert, invert-<n>, sepia, sepia-<n>без значения: 100%
hue-rotate-<deg>, -hue-rotate-<deg>hue-rotate()
drop-shadow, drop-shadow-xs, -sm, -md, -lg, -xl, -2xl, drop-shadow-[...], drop-shadow-none; drop-shadow-<color>, drop-shadow-current; /<alpha> у любого из нихdrop-shadow() на каждый слой, после остальных фильтров; цвет заменяет цвета слоёв, с альфа-каналом размера; Web, Linux, Windows и GPUI рисуют каждый слой, iOS, macOS и Android — самый широкий
drop-shadow-noneубирает его
filter-noneубирает все фильтры
backdrop-blur, backdrop-blur-<size>, backdrop-blur-[<length>]размывает то, что находится позади представления
backdrop-brightness-<n>, backdrop-contrast-<n>, backdrop-grayscale, backdrop-hue-rotate-<deg>, backdrop-invert, backdrop-opacity-<n>, backdrop-saturate-<n>, backdrop-sepiaфильтры backdrop
backdrop-filter-noneубирает их

#Трансформации

КлассЗадаёт
translate-x-<n>, translate-y-<n>, translate-<n>translate (отступы, full, доли собственного размера элемента: -translate-x-1/2, произвольные значения)
rotate-<deg>, rotate-[<angle>]rotate
rotate-x-<deg>, rotate-y-<deg>, rotate-z-<deg>3D-поворот (в transform, после сдвига, поворота и масштаба)
scale-<pct>, scale-x-<pct>, scale-y-<pct>, scale-[<factor>]scale: scale-95 = 0.95, -scale-x-100 отражает
skew-<deg>, skew-x-<deg>, skew-y-<deg>наклон, в transform (не на Android)
perspective-dramatic (100), -near (300), -normal (500), -midrange (800), -distant (1200), perspective-[<length>], perspective-noneглубина для 3D-поворотов дочерних элементов, если смотреть из его центра (perspective в CSS: <View class="perspective-near"><View class="rotate-y-45" /></View>)
origin-center, -top, -top-right, -right, -bottom-right, -bottom, -bottom-left, -left, -top-left, origin-[<value>]transformOrigin
backface-hidden, backface-visiblebackfaceVisibility
transform-noneсбрасывает 3D-повороты и наклоны (transform: none в CSS)
translate-none, rotate-none, scale-noneсбрасывает сдвиг, поворот, масштаб

Утилиты трансформаций компонуются как в CSS: translate-*, rotate-* и scale-* задают свойства translate, rotate и scale и комбинируются независимо от порядка, затем применяется transform (rotate-x-*, skew-*). Ключи пропа style с теми же именами заменяют только своё свойство: style={{ scale: 1.1 }} заменяет scale-95 и сохраняет rotate-3. transform, transform-gpu, transform-cpu и transform-flat принимаются и ничего не делают: NSH компонует все трансформации одинаково, плоско. Сдвиги на долю размера вычисляются относительно frame элемента и следуют за ним при изменении размера.

#Переходы и анимация

КлассЗадаёт
transitionцвета, прозрачность, тень и трансформацию; 150 мс, cubic-bezier(0.4, 0, 0.2, 1)
transition-all, transition-colors, transition-opacity, transition-shadow, transition-transformанимируемые свойства
transition-noneнет перехода
duration-<ms>, duration-[<time>]transitionDuration: duration-300, duration-[0.4s]
delay-<ms>, delay-[<time>]transitionDelay
ease-linear, ease-in, ease-out, ease-in-out, ease-initial, ease-[cubic-bezier(...)]transitionTimingFunction
animate-spin, animate-ping, animate-pulse, animate-bounceнативная покадровая анимация, повторяющаяся бесконечно
animate-noneостанавливает её

Переходы выполняются в UI-потоке при изменении значения, в том числе когда вариант начинает или перестаёт совпадать, поэтому transition active:scale-95 анимирует нажатие без JS. Оборачивайте анимации в motion-safe:, чтобы учитывать настройку уменьшения движения.

#Интерактивность

КлассЗадаёт
pointer-events-none, pointer-events-autopointerEvents: "none" / "auto": является ли представление целью для касаний и указателя; наследуется как в CSS: внутри представления pointer-events-none представление pointer-events-auto снова становится целью
cursor-<name>, cursor-[<name>]cursor: cursor-pointer, cursor-grab, cursor-not-allowed, … (любое ключевое слово курсора CSS)
select-none, select-text, select-autoвыделение текста (см. «Типографика»)

#SVG

КлассЗадаёт
fill-<color>, fill-none, fill-current, fill-inheritfill (fill-current — это currentColor)
stroke-<color>, stroke-none, stroke-current, stroke-inheritstroke
stroke-<number>, stroke-[<length>]strokeWidth

#Изображения

КлассЗадаёт
object-cover, object-contain, object-fill, object-none, object-scale-downobjectFit (fill растягивает, none сохраняет естественный размер и размещает в objectPosition, scale-down — то же самое, но уменьшает, если изображение больше); изображения и видео
object-top, object-bottom, object-left, object-right, object-center, object-top-left, object-top-right, object-bottom-left, object-bottom-right, object-[<position>]objectPosition (object-left-top, … — то же, что object-top-left, …)
tint-<color>tintColor (перекрашивает template-изображения)

#Принимаются без эффекта

Эти утилиты — подсказки для рендеринга или то, чем уже является любое нативное представление; они разбираются без предупреждения и ничего не меняют: antialiased, subpixel-antialiased, isolation-auto, box-border, appearance-none, appearance-auto, will-change-auto, will-change-scroll, will-change-contents, will-change-transform, will-change-[<value>], transform, transform-gpu, transform-cpu, transform-flat. Прокрутка, привязка (snapping) и overscroll — это пропы scroll.

#Не поддерживается

Варианты peer-*, псевдоэлементы (before:, after:), произвольные свойства ([prop:value]), overflow-auto / overflow-scroll, divide-*, columns-*, float-*, container, контейнерные запросы, order-*, transform-3d, select-all, border-double / outline-double, внутренние (intrinsic) ограничения min/max (например, max-w-max), snap-*, scroll-*, overscroll-*, touch-* и isolate — неизвестные классы. nsh build и nsh dev предупреждают о неизвестных классах, найденных в вашем исходном коде (file:line:col: unknown class '...'), а рантайм логирует каждый неизвестный класс один раз.

#Варианты

Варианты делают утилиту условной: dark:bg-zinc-900, md:flex-row, active:opacity-70. Они комбинируются (dark:active:bg-zinc-700) и вычисляются нативно при каждом изменении того, от чего зависят.

#Оформление и окружение

ВариантПрименяется, когдаRust
dark:включено тёмное оформление.dark(|s| …)
ios:приложение запущено на iOS или Mac Catalyst.when(os() == Os::Ios, …)
android:приложение запущено на Android.when(os() == Os::Android, …)
portrait:, landscape:окно выше, чем шире / шире, чем выше.style_when(move || window().height > window().width, …)
ltr:, rtl:направление раскладки.style_when(rtl, …)
motion-safe:, motion-reduce:пользователь не запрашивал / запросил уменьшение движения.style_when(reduce_motion, …)

#Брейкпоинты

Брейкпоинты сравниваются с шириной окна в пунктах.

ВариантМин. ширина
sm:640
md:768
lg:1024
xl:1280
2xl:1536
ФормаПримерПрименяется, когда
<bp>:md:p-8ширина ≥ брейкпоинта
max-<bp>:max-md:p-1ширина < брейкпоинта
min-[<length>]:min-[600px]:grid-cols-3ширина ≥ указанной длины
max-[<length>]:max-[400px]:text-smширина < указанной длины

Телефон в портретной ориентации (шириной 390 пунктов) не соответствует ни одному из брейкпоинтов по умолчанию; планшет или телефон в альбомной ориентации соответствует нескольким. В Rust брейкпоинт — это условие на окно: .style_when(move || window().width >= px(768.0), |s| s.p_8()) — это md:p-8.

#Состояния взаимодействия

Платформа отслеживает состояния только для элементов, в классах которых они используются, а изменения применяются нативно, без обращения к JS.

ВариантПрименяется, когдаRust
active:элемент нажат.active(|s| …)
hover:над ним находится указатель (указатель iPad, Mac Catalyst, мышь на Android).hover(|s| …)
focus:, focus-visible:поле ввода находится в фокусе.focus(|s| …)
focus-within:фокус у элемента или его потомка (содержимое Overlay является потомком элемента, в котором оно находится).focus_within(…)
disabled:у элемента есть проп disabled.disabled_style(|s| …)
enabled:у элемента нет пропа disabled
selected:элемент выбран: selected у Button или accessibilityState.selected
checked:элемент отмечен: accessibilityState.checked равно true ("mixed" не отмечен)
indeterminate:элемент в неопределённом состоянии: accessibilityState.checked равно "mixed"
aria-expanded:элемент раскрыт: accessibilityState.expanded равно true (триггер Popover или Menu, пока открыто его всплывающее окно)
aria-pressed:элемент — включённая кнопка-переключатель: accessibilityState.pressed равно true ("mixed" не нажат; это не active:, то есть не нажатие в процессе).aria_pressed(|s| …)
aria-busy:элемент занят: accessibilityState.busy равно true
aria-checked:элемент отмечен: accessibilityState.checked равно true, как checked:
aria-selected:элемент выбран: accessibilityState.selected равно true, как selected:
data-<name>:у элемента есть булев атрибут data-* name (&[data-<name>] в Tailwind; имена из строчных букв, цифр и -): то, что часть компонента показывает помимо своих состояний, например день календаря в начале диапазона data-range-startInteractive::project_data(name, …) задаёт такой атрибут

Те же состояния в виде объектов стиля — это пропы activeStyle, hoverStyle, focusStyle, disabledStyle, checkedStyle, indeterminateStyle, expandedStyle и pressedStyle каждого элемента (и selectedStyle у Button); они накладываются поверх стиля и классов элемента.

disabled работает на любом элементе: он применяет disabled: и убирает обработчики нажатий элемента, поэтому обратной связи при нажатии тоже нет.

view()
    .on_press(save)
    .disabled(saving)
    .rounded_lg()
    .bg(BLUE.shade(600))
    .px_4()
    .py_2()
    .transition()
    .active(|s| s.scale(0.95).bg(BLUE.shade(700)))
    .disabled_style(|s| s.opacity(0.4))
    .child(text("Save").font_weight(FontWeight::MEDIUM).text_color(white()))

#Группы

Пометьте предка с помощью group и стилизуйте потомков по его состоянию с помощью group-<state>:. Назовите группы, чтобы вкладывать их друг в друга: group/card и group-hover/card:.

ВариантПрименяется, когда группаRust
group-active:нажата.group_active(…), .group_active_named(name, …)
group-hover:под курсором.group_hover(…), .group_hover_named(name, …)
group-focus:, group-focus-visible:в фокусе
group-focus-within:в фокусе или содержит фокус.group_focus_within(…), .group_focus_within_named(name, …)
group-disabled:отключена
group-selected:выбрана
group-checked:отмечена
group-indeterminate:в неопределённом состоянии
group-aria-expanded:развёрнута
group-aria-pressed:переключатель включён
group-aria-busy:, group-aria-checked:, group-aria-selected:занята, отмечена, выбрана
group-data-<name>:показывает атрибут data-* name
view()
    .on_press(open)
    .group_named("row")
    .flex_row()
    .items_center()
    .gap_3()
    .p_3()
    .active(|s| s.bg(ZINC.shade(100)))
    .child(
        text("Settings")
            .flex_1()
            .text_color(ZINC.shade(900))
            .group_active_named("row", |s| s.text_color(BLUE.shade(600))),
    )
    .child(
        text("›")
            .text_color(ZINC.shade(400))
            .group_active_named("row", |s| s.translate_x(px(4.0)))
            .transition_transform(),
    )

#Позиция среди соседних элементов

ВариантПрименяется к
first:первому дочернему элементу
last:последнему дочернему элементу
only:единственному дочернему элементу
odd:1-му, 3-му, … дочернему элементу
even:2-му, 4-му, … дочернему элементу
each(items, |item: &Item| item.id, move |item, index| {
    text(move || item.with(|i| i.name.clone()))
        .border_b(px(1.0))
        .border_color(ZINC.shade(200))
        .py_3()
        .style_when(move || index.get() + 1 == items.with(Vec::len), |s| s.border_b(px(0.0)))
})

#Плейсхолдер и выделение

placeholder: применяется к плейсхолдеру элемента <Input> и принимает только цвет текста: placeholder:text-zinc-400 (ключ стиля placeholderColor). selection: применяется к выделению элемента <Input> или выделяемого элемента <Text>, а на любом элементе — к выделению внутри него (& *::selection в Tailwind; побеждает ближайший элемент), и принимает фон — подсветку: selection:bg-violet-200 (ключ стиля selectionColor, который также окрашивает каретку поля ввода там, где платформа рисует её одним цветом).

#Важно

! до или после утилиты (!p-4, p-4!) делает её приоритетнее всех остальных классов и встроенного style.

#Настройка темы

Расширьте тему в объекте "tailwind" файла nsh.json вашего приложения. Записи с новым именем добавляются; записи с существующим именем заменяют значения по умолчанию. Длины задаются в пунктах. Тема проверяется при сборке приложения: неизвестный ключ или недопустимое значение приводят к ошибке сборки.

{
  "name": "My App",
  "id": "com.example.myapp",
  "tailwind": {
    "colors": {
      "brand": { "50": "#f5f3ff", "500": "#7c3aed", "600": "#6d28d9", "DEFAULT": "#7c3aed" },
      "accent": "#f59e0b"
    },
    "spacing": 4,
    "breakpoints": { "tablet": 600 },
    "fontFamily": { "display": "Inter" },
    "fontSize": { "huge": [48, 1.1] },
    "fontWeight": { "heavy": 850 },
    "radius": { "card": 14 },
    "shadow": { "card": "0 2px 8px rgb(0 0 0 / 0.12)" },
    "insetShadow": { "well": "inset 0 2px 6px rgb(0 0 0 / 0.1)" },
    "dropShadow": { "icon": "0 2px 4px rgb(0 0 0 / 0.2)" },
    "tracking": { "label": 0.08 },
    "leading": { "dense": 1.15 },
    "blur": { "glass": 20 },
    "perspective": { "card": 700 },
    "aspect": { "photo": 1.5 },
    "ease": { "snappy": [0.2, 0, 0, 1] },
    "container": { "content": 680 }
  }
}

С такой темой работают bg-brand-500, bg-brand (оттенок DEFAULT), text-accent, tablet:flex-row, font-display, text-huge, font-heavy, rounded-card, shadow-card, inset-shadow-well, drop-shadow-icon, tracking-label, leading-dense, blur-glass, perspective-card, aspect-photo, ease-snappy и max-w-content.

КлючЗначениеИспользуется в
colors{ name: color } или { name: { shade: color } }; DEFAULT задаёт имя базового цвета. Любой синтаксис цвета CSS.всех утилитах цвета
spacingпунктов на шаг (по умолчанию 4)p-*, m-*, gap-*, w-*, …
remпунктов на rem (по умолчанию 16)
breakpoints{ name: width }вариантах точек останова (сортируются по ширине)
container{ name: width }w-*, min-w-*, max-w-*
fontFamily{ name: family } (системное семейство или имя встроенного шрифта)font-*
fontSize{ name: size } или { name: [size, lineHeightMultiple] }text-*
fontWeight{ name: 1–1000 }font-*
tracking{ name: em }tracking-*
leading{ name: multiple }leading-*
radius{ name: points }rounded-*
shadow, insetShadow, dropShadow{ name: "CSS box-shadow" }shadow-*, inset-shadow-*, drop-shadow-*
blur{ name: points }blur-*, backdrop-blur-*
perspective{ name: points }perspective-*
aspect{ name: ratio }aspect-*
ease{ name: [x1, y1, x2, y2] }ease-*

#См. также