Skip to content

Releases: styled-components/styled-components

styled-components@6.4.3

Choose a tag to compare

@quantizor quantizor released this 24 Jun 17:54

Patch Changes

  • f692ec2: Fix a TypeScript error when wrapping a component whose props can't be statically read, such as Mantine v7's polymorphic-factory components (Button, Card, Menu.Item, and similar). These styled components no longer reject every prop, including children; arbitrary props are accepted again at the JSX call site and via .attrs(), while components with readable prop types stay fully type-checked.
  • f692ec2: Keep TypeScript attribute autocomplete working while you type props on a polymorphic styled component. When a component renders a different element through as (for example as="video"), beginning to type a new prop name could make the whole suggestion list vanish; the rendered element's props now keep autocompleting as you go.

styled-components@7.0.0-prerelease-20260611043336

Choose a tag to compare

Major Changes

  • React Native: isolation: isolate is supported on iOS, Android, and the web. Blended descendants (mix-blend-mode) composite against the isolated element's own group, matching across all three targets. Separately, when a filter on iOS uses effects the platform only renders at the experimental release level, development builds warn that the effect is invisible and that it suspends descendant mix-blend-mode compositing while mounted. (isolation-isolate-android-layer.md)
  • react-native-web: CSS the browser implements natively reaches it untouched. This covers math functions with units (calc(), min(), max(), clamp(), round() and friends), viewport units (dvh / svh / lvh stay distinct), standalone translate / rotate / scale (3D values keep their Z component on the web), transform-style, transform-box, perspective, light-dark(), CSS system color keywords, wide-gamut color functions with theme values, hyphens, text-wrap, caret-color, accent-color, overscroll-behavior, scrollbar-width, field-sizing, interactivity, and direction. Native-only prop mappings and their platform-limitation warnings are scoped to the native targets and do not appear on the web. (rn-web-browser-native-passthrough.md)
  • React Native: @supports conditions are evaluated as real feature queries. A condition like @supports (display: grid) answers based on what the current platform can actually render, not / and / or combinations follow the CSS grammar (invalid mixes are ignored as the spec requires), unknown future syntax such as selector(...) evaluates to false, and on the web the browser answers directly. Probing for an unsupported feature inside @supports is silent: the query is the supported way to ask, so it does not emit the development warning for that feature. (supports-real-feature-queries.md)
  • React Native: z-index: auto resolves to the platform default stacking (the behavior CSS defines for auto) on iOS and Android, and passes through to the browser on the web. (z-index-auto-native.md)

Minor Changes

  • Added CSS anchor positioning on React Native (core subset). Declare anchor-name: --save on any styled element and position absolutely-placed siblings against it in pure CSS: top: anchor(--save bottom); left: anchor(--save left); width: anchor-size(--save width);. Anchored elements track the anchor as it moves or resizes, fallback values apply when the anchor is missing, position-anchor supplies an implicit target, and the functions compose inside calc(). Supported subset: physical side keywords in top/left insets, with the anchor and positioned element sharing a parent; unsupported forms fall back with a development warning. On the web the browser handles the same declarations natively. (native-anchor-positioning.md)

  • React Native: the CSS attr() function is supported. Styles can read the component's own props as typed CSS values: width: attr(data-size px, 48px) sizes from a data-size prop and uses the fallback when the prop is missing or invalid. Supported types include unit names (px, %, deg, ...), number, raw-string, and type() forms for lengths, numbers, percentages, and colors. attr() composes inside calc(), and fallbacks can themselves be dynamic values like light-dark(). (native-attr-function.md)

  • React Native: the corner-shape property is supported. round renders iOS's circular corner curve and squircle (along with nearby superellipse() values) renders the Apple-smooth continuous curve. Contours React Native can't draw (bevel, notch, scoop, square, far-out superellipse values, and corners that mix shapes) drop with a development warning suggesting round or squircle. Android renders circular corners and warns that the curve only takes effect on iOS. On the web the value passes through to browsers that support it. (native-corner-shape.md)

    const Card = styled.View`
      border-radius: 16px;
      corner-shape: squircle;
    `;
  • React Native: a display: grid layout subset is supported. A grid container written as display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; lays its direct styled children into equal columns, sizing each child to its share of the measured container width. Use grid-column: span 2 to make a child span multiple columns. (native-grid-subset.md)

    const Grid = styled.View`
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
    `;
    const Wide = styled.View`
      grid-column: span 2;
    `;

    The supported subset is equal 1fr columns (repeat(N, 1fr) or a 1fr 1fr 1fr track list) plus gap / row-gap / column-gap and grid-column: span N on direct children. Anything outside it, including fixed-pixel tracks, minmax(), auto-fill / auto-fit, unequal fractions, and line-number or named-line placement, is ignored with a development warning that names a supported alternative, and the container falls back to a wrapping row. On the web the browser lays out the full grid as written.

    A grid container that also declares container-type is a container-query container at the same time: descendants can use @container rules and cq* units against its measured box.

  • React Native: position: sticky is supported. Direct styled children of a styled ScrollView stick to the top edge and hold position exactly through flings and fast scrolling, with literal declarations and function interpolations alike. On the web the browser handles it. The current support matrix lives at https://styled-components.com/docs/compatibility. (native-position-sticky.md)

  • React Native: the @property rule is supported. Custom properties can be registered with a typed syntax, an initial value, and an inheritance switch: an unset registered property resolves var() references to its typed initial value, and inherits: false registrations stop ancestor values from leaking into descendants. Invalid rules (missing descriptors, initial values that don't match the declared syntax) are ignored with a development warning, matching the spec. On the web, registrations forward to the browser's own CSS.registerProperty(). (native-property-rule.md)

  • React Native: relative color syntax is supported for the rgb(), hsl(), hwb(), and color() forms, alongside oklch() / oklab() / lch() / lab(). A value like color: rgb(from ${theme.brand} r g b) resolves to a color React Native can display on iOS, Android, and react-native-web, whether the base is a literal color, another color function, or a resolved theme value. (native-relative-color-completion.md)

  • React Native: CSS scroll-driven animations are supported. animation-timeline: scroll() binds any @keyframes animation's progress to the scroll position of the nearest styled ScrollView, enabling parallax, scroll progress bars, and reveal-on-scroll in plain CSS. Scrollers can declare named timelines with scroll-timeline: --name for descendants to reference, and animation-range limits an animation to a slice of the scroll distance (animation-range: entry 25% 75%, lengths and calc() included). Iteration counts and all four direction modes apply across the scroll range. The same declarations are supported on the web. (native-scroll-driven-animations.md)

  • React Native: CSS scroll snap is supported on styled.ScrollView. Declare scroll-snap-type on the scroller and scroll-snap-align: start | center | end on its children, exactly like the web: the children become real snap positions (mixed sizes welcome), and scroll-snap-stop: always on a child keeps a fast fling from skipping past it. A settle guarantee makes mandatory literal on Android, where the platform engine can otherwise leave a caught scroller resting between snap points. (native-scroll-snap.md)

    Without aligned children, mandatory approximates with full-scrollport paging and a development warning; for manual control pass snapToInterval or snapToOffsets on the ScrollView and your props win. proximity applies fast deceleration only. On the web the browser handles all of these properties directly.

  • React Native: styled scrollers (styled.ScrollView, styled.FlatList, and friends) nest like the web. A vertical scroller inside another vertical scrollable receives gestures on Android without passing nestedScrollEnabled yourself; iOS and the web behave this way too. Passing the prop explicitly still wins. ([native-scroller-ergonomics.md](https://github.com/st...

Read more

styled-components@7.0.0-prerelease-20260610071139

Choose a tag to compare

@github-actions github-actions released this 10 Jun 07:14
ac6b11c

Patch Changes

  • Fixed a rules-of-hooks violation that could crash components triggering an immediate re-render with unchanged style props. (hooks-cache-hit-debug-value.md)

Full Changelog: styled-components@7.0.0-prerelease-20260530064039...styled-components@7.0.0-prerelease-20260610071139

styled-components@6.4.3-prerelease-20260602021501

Choose a tag to compare

@github-actions github-actions released this 02 Jun 02:16
f692ec2

Patch Changes

  • f692ec2: Fix a TypeScript error when wrapping a component whose props can't be statically read, such as Mantine v7's polymorphic-factory components (Button, Card, Menu.Item, and similar). These styled components no longer reject every prop, including children; arbitrary props are accepted again at the JSX call site and via .attrs(), while components with readable prop types stay fully type-checked.
  • f692ec2: Keep TypeScript attribute autocomplete working while you type props on a polymorphic styled component. When a component renders a different element through as (for example as="video"), beginning to type a new prop name could make the whole suggestion list vanish; the rendered element's props now keep autocompleting as you go.

Full Changelog: styled-components@6.4.2...styled-components@6.4.3-prerelease-20260602021501

styled-components@7.0.0-prerelease-20260530064039

Choose a tag to compare

@github-actions github-actions released this 30 May 06:43
051c829

Patch Changes

  • In React Native apps (both native and react-native-web), animating a multi-argument transform shorthand (translate(x, y), translate3d(x, y, z), or scale(x, y)) inside @keyframes or a transition no longer throws "Transform with key of translate must have an array as the value". These forms now animate correctly per axis. Single-axis forms and uniform scale(n) were already fine. (native-animated-translate-shorthand.md)

Full Changelog: styled-components@7.0.0-prerelease-20260526020504...styled-components@7.0.0-prerelease-20260530064039

styled-components@7.0.0-prerelease-20260526020504

Choose a tag to compare

@github-actions github-actions released this 26 May 02:07
6d1630d

Patch Changes

  • On React Native (Expo and other Metro projects), importing from styled-components/native could pull React Native Web into your iOS and Android bundles, bloating them and breaking styling on device. The correct build is now selected automatically for each platform, so React Native Web stays out of native bundles and no custom Metro resolver workaround is needed. (native-metro-platform-resolution.md)

Full Changelog: styled-components@7.0.0-prerelease-20260524213421...styled-components@7.0.0-prerelease-20260526020504

styled-components@7.0.0-prerelease-20260524213421

Choose a tag to compare

@github-actions github-actions released this 24 May 21:36
fadbfac

Patch Changes

  • Fix native Node.js ESM default imports so import styled from 'styled-components' exposes the styled factory directly. (fresh-node-default-import.md)

Full Changelog: styled-components@7.0.0-prerelease-20260519035351...styled-components@7.0.0-prerelease-20260524213421

styled-components@6.4.2

Choose a tag to compare

@quantizor quantizor released this 19 May 12:58

Patch Changes

  • 9945904: Restore TypeScript prop autocomplete inside the JSX of a styled component once the first attribute is typed.
  • 9945904: Apply all chain levels' styles when an extended styled component renders with the as prop under Preact's react-compat.
  • 9945904: Respect a custom toString on plain value objects (e.g. design tokens) when interpolated into a styled component, rather than walking the object's keys as CSS declarations.
  • 9945904: Fix a TypeScript error when wrapping a component whose props include an as prop with a non-string type (such as Next.js Link's as?: Url). The styled component now accepts either the styled-components polymorphism value or the wrapped component's own as type, so spreading the wrapped component's props onto the styled component is assignable again.
  • 9945904: Restore reliable styling in production browser bundles built without a runtime process global.

styled-components@7.0.0-prerelease-20260519035351

Choose a tag to compare

Minor Changes

  • CSS accent-color now works on every target. Applied to a styled.Switch, it tints the on-state surface so the control picks up the value (the closest analog to the on-web behavior of tinting a checked checkbox). Both <color> values and accent-color: auto are accepted; auto resolves to the platform's accent color. (native-accent-color.md)

    The same color forms work here as in every other color slot in styled-components: HTML named colors, CSS Color 4 system keywords, hex, modern color functions, and theme tokens.

    For wrapping a third-party component (Slider, Checkbox, ProgressBar, etc.) whose tint prop isn't <Switch>.trackColor, use the function form of .attrs(...) with the AST bridge to forward the resolved value:

    const ThemedSlider = styled(Slider).attrs<{ thumbTintColor?: string }>((_props, ast) => ({
      thumbTintColor: ast.pop('accentColor'),
    }))`
      accent-color: red;
    `;

    ast.pop('accentColor') returns the resolved value and removes it from the style bag so it doesn't reach the wrapped component as an unrecognized style key. Cascade-style inheritance from an ancestor accent-color declaration down to a descendant <Switch> is not implemented in this release; declare accent-color on the Switch itself (or use the attrs recipe above when wrapping).

  • React Native now supports CSS custom properties through the component cascade. (native-css-var-warn.md)

    Declare a property on any styled component (--brand: tomato;) and descendants can read it back through the standard var() syntax (color: var(--brand);). The substitution honors the full CSS Variables Module Level 1 contract — fallbacks (var(--maybe, default)), nested resolution (var(--a, var(--b, default))), nested resolution in the name argument (var(var(--name-of-name))), cycle detection, and case-sensitive names. Substituted values flow through the same value pipeline as authored CSS, so shorthand expansion (margin: var(--spacing); with --spacing: 4px 8px;) still expands to the individual longhands.

    Spec compliance touches:

    • --foo: initial correctly resets a custom property to the guaranteed-invalid value, so a downstream var(--foo, fallback) substitutes the fallback.
    • Trailing !important is stripped from custom property values before they reach the cascade.
    • A literal var(--name) inside a quoted CSS string (e.g. content: "var(--brand)") is preserved verbatim instead of being mistakenly substituted.
    • Bare -- declarations are dropped (reserved for future use per the spec) and never leak as a style key.

    The rn-web bundle leaves both the declarations and var() references in place so the browser's own cascade handles them. Development builds warn on a var() reference only when no ancestor declared the property and no fallback was provided.

  • CSS font-size keywords now produce identical pixel sizes on iOS, Android, and the web build. Absolute-size keywords (xx-small, x-small, small, medium, large, x-large, xx-large, xxx-large) resolve to 9, 10, 13, 16, 18, 24, 32, 48 (the reference table modern browsers use at the default medium of 16px). Relative-size keywords (smaller, larger) resolve at render time against the inherited cascade font-size, stepping to the next entry on the absolute-size ramp when the inherited size matches a keyword and otherwise multiplying by 1.2. (native-font-keyword-parity.md)

    Other CSS Fonts shorthand keyword classes that React Native cannot replicate exactly drop with a development warning that names the offending keyword and suggests a concrete alternative:

    • Font-width / font-stretch keywords (condensed, expanded, etc.) drop because React Native does not control glyph width.
    • System font names (caption, icon, menu, message-box, small-caption, status-bar) drop because the per-platform meaning has no cross-platform mapping; pick a font-family explicitly.
  • Expanded the React Native CSS surface with four polyfills that previously dropped silently or warned: (native-font-line-height-caret-line-width.md)

    • font-size now accepts the full CSS length grammar: absolute-size keywords (xx-small through xxx-large), relative-size keywords (larger / smaller), absolute lengths (pt, pc, in, cm, mm, Q), font-relative units (em, rem, lh, rlh plus the font-metric forms ex, cap, ch, ic and their r-variants), viewport units (vh, vw, dvh, svh, lvh and width counterparts), container-query units (cqh, cqw, cqi, cqb, cqmin, cqmax), and percentages. Keyword sizes resolve to a fixed pixel ramp on every platform; everything else folds against the current environment at render time.
    • line-height now accepts the same expanded set: absolute lengths, font-relative units (including font-metric forms), viewport units, container-query units, and percentages all resolve against the cascade instead of being dropped with a development warning.
    • caret-color on iOS now applies the authored color to the text input's caret. iOS exposes a single surface for the caret and selection highlight, so the selection picks up the same color as a side-effect (a one-time development note names the deviation). Android and rn-web behavior is unchanged.
    • round(line-width, A) now snaps A to the device pixel grid at render time using the platform's pixel ratio, matching the CSS Values 4 "snap a length as a line width" algorithm. Useful for hairline borders that should align to physical pixels regardless of screen scale.

    translate: x y z no longer drops the Z value on React Native; the three-argument translate(x, y, z) form passes through unchanged on iOS and Android.

    The transform-style: preserve-3d development warning is more accurate: animated 3D transforms are already isolated automatically by the animation adapter, and the warn no longer suggests a manual collapsable={false} workaround for static decls (it has no effect on iOS without a perspective surface).

  • React Native now respects CSS !important. (native-important-support.md)

    Authoring color: red !important; inside a styled component on native now behaves like the web:

    • The !important marker is stripped from the rendered value (previously the literal string 'red !important' leaked onto the host element and the color silently failed).
    • Important declarations beat any normal declaration on the same property, regardless of source order, including overrides from matched @media, @container, @supports, attribute selectors, pseudo states (:hover, :focus, :active, :disabled), :has(), :nth-child(), and combinator selectors.
    • A shorthand marked !important propagates to every longhand (padding: 4px 8px !important becomes important across padding-top / -right / -bottom / -left).
    • Importance flows through var() substitution and through render-time resolvers (light-dark(), env(), viewport units, theme tokens).
    • Spec-aligned with the web: a styled component's !important beats a runtime style={{ ... }} prop. Normal declarations are still overridden by the runtime style prop as before.
    • Case-insensitive on the marker (!IMPORTANT) and tolerant of whitespace between ! and important.

    !important inside @keyframes is ignored, matching the CSS Animations spec.

    Cross-component cascade of !important for inherited properties (a parent's !important font-size defeating a child's normal one) is not yet supported. Today's coverage is within-component only.

  • :nth-child(an+b of S) and :nth-last-child(an+b of S) now work on React Native. The formula counts position within the filter, so :nth-child(2n+1 of [data-active]) selects every odd active sibling regardless of inactive siblings between them. The of S inner accepts a styled-component reference or a single attribute selector (the same simple-selector forms :has() accepts on native). Complex inner selectors with combinators or descendant chains warn and fall through. (native-nth-child-of-selector.md)

    const Row = styled.View`
      background: white;
      &:nth-child(2n + 1 of [data-active]) {
        background: silver;
      }
    `;
  • CSS overscroll-behavior and scrollbar-width now work on React Native. Apply them to a styled.ScrollView, styled.FlatList, styled.SectionList, or styled.VirtualizedList: (native-scroll-surfaces.md)

    • overscroll-behavior: contain | none disables both bounce on iOS and the over-scroll glow on Android. overscroll-behavior: auto (the initial value) restores the platform defaults.
    • scrollbar-width: none hides both scroll indicators; auto and thin keep the platform default (React Native does not expose a thin-scrollbar surface). thin is equivalent to auto on native per the spec note that user agents may disregard thin.

    Web builds continue to forward the declaration so the browser handles it natively.

  • CSS text-overflow: ellipsis | clip now works on every target. Pair it with line-clamp or text-wrap: nowrap so the content can actually overflow. ([native-text-overflow...

Read more

styled-components@6.4.2-prerelease-20260516150535

Choose a tag to compare

d20b88e Fix a TypeScript error when wrapping a component whose props include an as prop with a non-string type (such as Next.js Link's as?: Url). The styled component now accepts either the styled-components polymorphism value or the wrapped component's own as type, so spreading the wrapped component's props onto the styled component is assignable again.

Full Changelog: styled-components@6.4.2-prerelease-20260514185513...styled-components@6.4.2-prerelease-20260516150535