Box.extend() registers a prop that is indistinguishable from a built-in one afterwards: it nests in themes, breakpoints, container queries and every state on this site's /variants page, shares a class with every other element that used the same value, and reaches getStyles() on a server. So the rows below are not a list of things you cannot do — they are the list of props not worth typing for everybody, yet. And for the one-off nobody will type twice, css={{ mixBlendMode: 'multiply' }} is the same style object compiled to a class rather than an inline style — the /escape-hatch page is what governs it.const { extendedProps } = Box.extend({}, {}, {
mixBlendMode: [{ styleName: 'mix-blend-mode', values: ['multiply', 'screen', 'overlay'] as const }],
});
// <Box mixBlendMode="multiply" theme={{ dark: { mixBlendMode: 'screen' } }} />bg-blu-500 is a silent no-op. JSX forbids a duplicate prop, so the conflict-resolution ecosystem Tailwind needs — tailwind-merge, clsx, cva, 120M downloads a week between them — has nothing to resolve here. And Box.components() is the component-and-variant layer those libraries exist to bolt on.| Tailwind | Box props | Status |
|---|---|---|
| aspect-ratio | aspectRatio | yes |
| box-sizing | boxSizing | yes |
| display | displayinline | yes inline is the shorthand for the inline- pair |
| object-fit | objectFit | yes |
| overflow | overflowoverflowXoverflowY | yes |
| position | position | yes |
| top / right / bottom / left / inset / start / end | toprightbottomleftinsetinsetXinsetYinsetStartinsetEnd | yes insetX/insetY are the logical inset-inline/inset-block, insetStart/insetEnd their two sides |
| visibility | visibility | yes |
| z-index | zIndex | yes |
| @container | containercontainerNamecontainerType | yes |
| clip-path | clipPath | yes takes url(#id) and var(--name), so a shape is a value |
| content-visibility | contentVisibility | yes no Tailwind utility |
| interpolate-size | interpolateSize | yes no Tailwind utility |
| object-position | — | no the fit, without the position |
| float / clear | — | no grid and flex replace both |
| isolation | — | no no demand yet |
| overscroll-behavior | — | no no demand yet |
| columns / break-* / box-decoration-break | — | no multi-column and print breaks |
| Tailwind | Box props | Status |
|---|---|---|
| flex-direction | d | yes |
| flex-wrap | flexWrap | yes |
| flex | flex1 | partly flex1 is flex: 1; auto, initial and none are not values |
| flex-grow / flex-shrink | flexGrowflexShrink | yes |
| order | order | yes |
| grid-template-columns / -rows | gridTemplateColumnsgridTemplateRows | yes |
| grid-column / grid-row | gridColumngridColumnStartgridColumnEndgridRowgridRowStartgridRowEnd | yes |
| gap | gaprowGapcolumnGap | yes |
| justify-content / align-items | jcai | yes the two short names this library keeps |
| the rest of box alignment | justifyItemsjustifySelfalignContentalignSelfplaceContentplaceItems | yes all eight take the overflow-safe values ('safe center') |
| place-self | — | no alignSelf and justifySelf together |
| flex-basis | — | no width, on a flex child |
| grid-auto-flow / -columns / -rows | — | no no demand yet |
| Tailwind | Box props | Status |
|---|---|---|
| padding | ppxpyptprpbplpspe | yes divider 4 — p={4} is 1rem; ps/pe are the logical pair, and px is already padding-inline |
| margin | mmxmymtmrmbmlmsme | yes ms/me are the logical pair |
| width | widthminWidthmaxWidth | yes 'fit' is 100%, '1/2' is 50% |
| height | heightminHeightmaxHeight | yes |
| size | — | no width and height, written twice |
| space-x / space-y | — | no gap — which Tailwind now recommends over both |
| Tailwind | Box props | Status |
|---|---|---|
| font-size | fontSize | yes divider 16 — fontSize={14} is 14px |
| font-style / font-weight | fontStylefontWeight | yes |
| letter-spacing / line-height | letterSpacinglineHeight | yes lineHeight is direct px |
| text-align | textAlign | yes takes 'start'/'end', which follow the text direction |
| color | color | yes twenty-six OKLCH families, and an opacity modifier on any of them |
| text-transform | textTransform | yes |
| text-overflow / text-wrap / white-space | textOverflowtextWrapwhiteSpace | yes |
| text-shadow | textShadowtextShadowColor | yes |
| content | content | yes text is quoted for you; attr()/counter()/var() are written as CSS |
| text-decoration-line | textDecoration | partly the line only — colour, style and thickness are not props |
| list-style-type | listStyle | partly square and none, plus the two positions |
| font-family | — | no a project-wide decision: one vars entry, or the base stylesheet |
| line-clamp | — | no no demand yet |
| font-variant-numeric / font-stretch / font-smoothing | — | no no demand yet |
| text-indent / vertical-align / word-break / hyphens | — | no no demand yet |
| Tailwind | Box props | Status |
|---|---|---|
| background-color | bgColor | yes |
| background-image | bgImagebgGradient | yes a gradient is a record whose stops are palette values, so it is themed and shares a class |
| background-clip | bgClip | yes needs color="transparent" beside it to show |
| border-width | bbxbybtbrbbblbsbe | yes direct px — b={1} is 1px; bs/be are the logical pair |
| border-color / border-style | borderColorborderStyle | yes |
| border-radius | borderRadiusborderRadiusTopborderRadiusRightborderRadiusBottomborderRadiusLeftborderRadiusTopLeftborderRadiusTopRightborderRadiusBottomRightborderRadiusBottomLeftborderRadiusStartborderRadiusEndborderRadiusStartStartborderRadiusStartEndborderRadiusEndEndborderRadiusEndStart | yes divider 4, the spacing scale |
| outline | outlineoutlineStyleoutlineOffsetoutlineColor | yes |
| ring | ringinsetRingringColorinsetRingColor | yes a width in px that follows borderRadius and costs no layout |
| background-position / -repeat / -size / -attachment / -origin | — | no the gradient and mask records cover what most pages want from them |
| divide-* | — | no a border on the child, with nth to drop the last one |
| Tailwind | Box props | Status |
|---|---|---|
| box-shadow | shadowinsetShadowshadowColorinsetShadowColor | yes four layers of one property, so they stack instead of overwriting |
| opacity | opacity | yes |
| filter | blurbrightnesscontrastgrayscalehueRotateinvertsaturatesepiadropShadowdropShadowColor | yes nine functions, each its own layer of one composed filter |
| backdrop-filter | backdropBlurbackdropBrightnessbackdropContrastbackdropGrayscalebackdropHueRotatebackdropInvertbackdropOpacitybackdropSaturatebackdropSepiabackdropFilter | yes |
| mask-image | maskImage | partly the image — it takes the gradient record; mask-size/position/repeat/composite are not props |
| mix-blend-mode / background-blend-mode | — | no no demand yet |
| forced-color-adjust | — | no the forcedColors block is the way in, with the system colours as values |
| Tailwind | Box props | Status |
|---|---|---|
| transition-property / -duration / -timing-function / -delay / -behavior | transitiontransitionDurationtransitionTimingFunctiontransitionDelaytransitionBehavior | yes times are milliseconds; a spring name goes on the curve *and* the duration |
| animation | animationanimationNameanimationDurationanimationDelayanimationDirectionanimationFillModeanimationIterationCountanimationPlayStateanimationTimingFunction | yes four presets that stop under reduced motion on their own, and Box.keyframes() for the rest |
| rotate / scale / translate | rotatescalefliptranslateXtranslateY | yes CSS longhands, so they compose instead of overwriting one transform |
| will-change | willChange | yes |
| skew / transform-origin | — | no no demand yet |
| perspective / transform-style / backface-visibility | — | no 3D transforms |
| Tailwind | Box props | Status |
|---|---|---|
| accent-color / caret-color | accentColorcaretColor | yes the parts of a native control the page does not draw |
| appearance | appearance | yes |
| color-scheme | colorScheme | yes |
| cursor | cursor | yes |
| field-sizing | fieldSizing | yes |
| pointer-events | pointerEvents | yes |
| resize | resize | yes |
| user-select | userSelect | partly contain is deliberately absent: Chrome computes it to auto |
| scrollbar | scrollbarWidthscrollbarColorscrollbarGutter | yes no Tailwind utility |
| scroll-behavior / scroll-margin / scroll-padding / scroll-snap-* | — | no no demand yet |
| touch-action | — | no no demand yet |
| Tailwind | Box props | Status |
|---|---|---|
| fill | fillfillOpacityfillRule | yes takes url(#id) and var(--name), so a gradient is a value |
| stroke / stroke-width | strokestrokeOpacitystrokeWidth | yes |
| the rest of stroke | strokeLinecapstrokeLinejoinstrokeMiterlimitstrokeDasharraystrokeDashoffset | yes no Tailwind utility — and a dash length that transitions is what animates a chart |
| paint and text rendering | paintOrdervectorEffectshapeRenderingtextAnchordominantBaseline | yes no Tailwind utility |
| geometry | cxcyrrxryxy | yes no Tailwind utility: real CSS, so unlike the attributes they transition |
| Tailwind | Box props | Status |
|---|---|---|
| border-collapse / border-spacing / table-layout / caption-side | — | no the four table properties — this site's own tables still reach for a style attribute |
| Tailwind | Box props | Status |
|---|---|---|
| --custom-property | vars | yes the answer for markup this library does not render — a chart, a third-party widget |
| arbitrary properties ([mask-type:luminance]) | css | yes the typed escape hatch: a style object compiled to a class, never an inline style — the 5% every other row is not |
| Tailwind | Box props | Status |
|---|---|---|
| hover / focus / focus-visible / focus-within / active | hoverfocusfocusVisibleactive | yes focus is :focus-within, which is what a wrapper wants |
| disabled / checked / indeterminate / required / valid / invalid / optional | disabledcheckedindeterminaterequiredvalidinvalidoptionalselected | yes valid/invalid are :user-valid — the state after the user has had a turn |
| visited / target / open / placeholder-shown / autofill / in-range / out-of-range / inert | visitedtargetopenplaceholderShownautofillinRangeoutOfRangeinert | yes |
| has-* | hashasFocushasCheckedhasValidhasInvalidhasRequiredhasDisabled | yes the general key, plus the six worth a name of their own |
| not-* | not | yes keyed by state name, so it stays typed |
| data-* / aria-* | dataAttrariaAttr | yes a bare aria key means ="true" |
| first / last / only / odd / even / nth-* | nth | yes one key: 'first', '2n+1', 'last 2' |
| group-* / peer-* | grouppeer | yes a state on the default class or a named one — 'card/hover', 'row/data-state=open' |
| read-only / default / empty | — | no no demand yet |
| first-of-type / last-of-type / nth-of-type | — | no nth counts children, not types |
| Tailwind | Box props | Status |
|---|---|---|
| before / after | beforeafter | yes both come with content: '' — a generated element with none renders nothing |
| placeholder / selection / marker / first-line / first-letter / backdrop / file | placeholderselectionmarkerfirstLinefirstLetterbackdropfileButton | yes marker and selection reach descendants, as Tailwind's do |
| Tailwind | Box props | Status |
|---|---|---|
| sm … 2xl | smmdlgxlxxl | yes |
| @sm … @2xl (container) | cq | yes six sizes, each with a complement — maxMd is not (min-width) |
| dark | theme | yes any number of themes, not just two |
| motion-reduce / contrast-more / forced-colors | motionReducecontrastMoreforcedColors | yes reduced motion is the default: the base transition rides a variable it zeroes |
| pointer-coarse / pointer-fine | pointerCoarsepointerFine | yes |
| starting | startingStyle | yes every starting rule is emitted !important, or specificity kills the entrance |
| max-sm … max-2xl | — | no the container sizes have complements; the breakpoints do not |
| rtl / ltr | rtlltr | yes :dir(), not [dir="rtl"] & — the direction belongs to this element, so a <bdi> or dir="auto" is seen |
| print / motion-safe / supports-* | — | no no demand yet |
| arbitrary variants ([&>*]:) | — | no a selector this library did not compile is the one thing it will not emit |