Releases: styled-components/styled-components
Release list
styled-components@7.0.0-prerelease-20260808041113
No new changes since the previous release.
Full Changelog: styled-components@7.0.0-prerelease-20260807223715...styled-components@7.0.0-prerelease-20260808041113
styled-components@6.5.1
Patch Changes
- a0a92cd: Fix a styled component silently dropping props declared as a union whose members have no prop in common, which left every one of those props rejected. The same applied when
aspointed at a component with such props. Where every member's props are optional the union is still flattened, so declare the combined optional shape instead. - a0a92cd: Styled components now report the same debug value to React DevTools on every render. Previously the value was only reported on renders that recomputed styles, so it disappeared from the DevTools panel whenever a component re-rendered with unchanged style props.
- a0a92cd: Fix wrapping a component whose props are a union. Since 6.5.0 the wrapped version accepted only the props common to every member of the union, so a prop belonging to just one member was rejected even though the unwrapped component accepted it.
styled-components@7.0.0-prerelease-20260807223715
Minor Changes
-
createGlobalStylerules land before any consumer layout effect. (global-styles-before-layout-effects.md)Global styles now write from an insertion effect, which React runs for the whole tree before any layout effect. A component measuring itself in
useLayoutEffectreads the styled measurement, where before it could read the unstyled one depending on where the global style component sat in the tree.If you were compensating for that ordering, for example by measuring in a passive effect or on a later tick, that workaround can come out.
-
styled-components does no work in a passive or layout effect on its render path. (no-passive-or-layout-effects.md)
This is a correctness and predictability guarantee rather than a speed one. Where the library needs a lifecycle hook it uses the narrowest thing that fits: a ref callback for teardown that needs a committed host,
useSyncExternalStorefor external mutable state, anduseInsertionEffectfor stylesheet writes.On React Native several teardowns now run before paint instead of after, so a sibling reading a scroll-snap or anchor registry never paints a frame against a stale entry. The render-count effect is small and was measured rather than assumed:
position: stickyelements render once per layout change instead of twice. Scrolling itself is unchanged, and no timing benchmark was run.On React Native,
anchor-nameandscroll-snap-alignnow require the styled target to forward itsref, because the library registers and deregisters through a ref callback.styled.Viewand every other host target already do.styled(YourComponent)needsYourComponentto passrefdown to the host element it renders; if it does not, the declaration is inert and says so in development rather than stranding an entry nothing can remove.Three carve-outs remain, each documented at its site, so this is a guarantee about the library's own render path rather than an absolute: the
position: stickyoverlay publish and its paired deregistration, the reanimated@starting-styletwo-pass flip, and the default Animated adapter's unmount teardown, which is on the path of every animated native component.
Patch Changes
-
Renaming
anchor-nameon React Native releases the old anchor. (anchor-name-rename-releases-old-rect.md)The old name's rect stayed in the registry until the element unmounted, so
anchor()andanchor-size()consumers resolving it kept reading a position nothing updated. The rect is now released when the name changes, as documented. -
A React Native scroller only snaps if it declared
scroll-snap-typeitself. (scroll-snap-needs-a-declared-type.md)scroll-snap-alignon a child used to make any styledScrollViewsnap, even one that never opted in. Two scrollers sharing a card component meant the one meant to drift freely snapped along with the one that asked to. This matches css-scroll-snap-1, where the initialscroll-snap-type: nonemakes an element a non-snapping container and a descendant'sscroll-snap-alignhas no effect there.
Full Changelog: styled-components@7.0.0-prerelease-20260806233720...styled-components@7.0.0-prerelease-20260807223715
styled-components@7.0.0-prerelease-20260806233720
Minor Changes
-
Cut the TypeScript cost of using styled components in an app. A render target's props are resolved once per target instead of once per JSX call site, which is where most of the work was going. Against a fixture of 100 styled components the type count drops to roughly a sixth and peak memory to roughly a quarter, putting v7 slightly under v6 on both. (consumer-type-check-cost.md)
-
A declared
styletype now constrains the fields it names and leaves the rest of CSS accepted, instead of replacing the target'sstyleoutright. Wrap the declaration in the newCustomStyleexport to forbid everything it omits rather than writingneverfor every property by hand. The constraint holds throughasandforwardedAs. (declared-style-merges.md)Under
exactOptionalPropertyTypesa component with a declaredstylerejects an explicitstyle={undefined}; declarestyle?: X | undefinedto allow it. Omitting the prop is unaffected. -
React Native
styleprops are checked against React Native's own style types. The CSS-custom-property widening the web entry applies was reaching the native entry too, so web-only CSS and custom properties were accepted on native components that cannot render them. (native-style-typing.md)
Patch Changes
- Fix a styled component silently dropping props declared as a union whose members have no prop in common, which left every one of those props rejected. Where every member's props are optional the union is still flattened, so declare the combined optional shape instead. (disjoint-union-props.md)
- Fix wrapping a component whose props are a union. The wrapped version accepted only the props common to every member, so a prop belonging to just one member was rejected even though the unwrapped component accepts it. The same applied when
aspointed at such a component. (union-props-survive-styled.md) - Fix wrapping a component whose props cannot be inspected statically, such as the polymorphic factory components Mantine ships. Every prop was rejected,
childrenincluded. Declaring props of your own on the wrapper no longer switches the behavior back off either. (untyped-target-props.md)
Full Changelog: styled-components@7.0.0-prerelease-20260731041038...styled-components@7.0.0-prerelease-20260806233720
styled-components@6.5.1-prerelease-20260806232123
Patch Changes
- a0a92cd: Fix a styled component silently dropping props declared as a union whose members have no prop in common, which left every one of those props rejected. The same applied when
aspointed at a component with such props. Where every member's props are optional the union is still flattened, so declare the combined optional shape instead. - a0a92cd: Styled components now report the same debug value to React DevTools on every render. Previously the value was only reported on renders that recomputed styles, so it disappeared from the DevTools panel whenever a component re-rendered with unchanged style props.
- a0a92cd: Fix wrapping a component whose props are a union. Since 6.5.0 the wrapped version accepted only the props common to every member of the union, so a prop belonging to just one member was rejected even though the unwrapped component accepted it.
Full Changelog: styled-components@6.5.0...styled-components@6.5.1-prerelease-20260806232123
styled-components@6.5.0
Minor Changes
-
dfe4baf: React Native components now check
styleagainst React Native's own style types. Web-only CSS such asfloat, and CSS custom properties such as--brand, were previously accepted even though React Native has never done anything with them at runtime. They now surface as a type error where you write them instead of silently doing nothing.const Card = styled.View``; <Card style={{ padding: 16 }} />; // unchanged <Card style={{ float: 'left' }} />; // now a type error
Web components are unaffected and still accept custom properties.
-
dfe4baf: Declaring your own
styleprop type now constrains the fields you name while leaving the rest of CSS alone. Previously a declaration likestyled.div<{ style?: { width: number } }>was quietly ignored, because the built-in style type was applied after your props, so any CSS value was still accepted. Nowwidthhas to be a number, whilecolor, custom properties, and everything else you did not mention keep working as before.To remove a field rather than constrain it, declare it as
never. To make your type the only thing accepted, wrap it in the newCustomStylehelper, which removes every field you did not list:const Box = styled.div<{ style?: CustomStyle<{ width: number }> }>``;
The constraint holds when the component is rendered through
asorforwardedAs, so it cannot be sidestepped by rendering the same component as a different tag. Note thatCustomStyleremoves CSS custom properties too, since they are among the fields you did not list.One thing to know if you use
exactOptionalPropertyTypes: on a component that declares its ownstyle, passingstyle={undefined}explicitly is now rejected. Leaving the prop off is unaffected. Writestyle?: { width: number } | undefinedin your declaration if you need to pass it explicitly.Relatedly, reading the style type back off a component (for example with
React.ComponentProps) now reports that CSS custom properties are accepted, which matches what was already allowed when rendering. -
2949923: Large TypeScript projects type-check dramatically faster. On a 500-component app,
tsccheck time drops to under a quarter of what 6.4.4 takes and peak memory to under a third, which resolves the out-of-memory failures some projects hit after upgrading past 6.4.2. Both are now better than 6.4.2 was, so there is no longer a reason to pin to it. Editor responsiveness improves by the same margin, and autocomplete onastargets is unchanged.
Patch Changes
-
dfe4baf: Fixed
refbeing rejected on React Native components created with the shorthand syntax, such asstyled.TextInput. Passing a ref, or a ref callback whose parameter you have not annotated, now works the same way it does withstyled(TextInput).Also fixed a type error when a component's
attrscallback is given an explicit parameter type, as instyled.div.attrs<MyProps>(props => props). -
dfe4baf: Fixed components built on targets whose props cannot be inspected, such as Mantine's polymorphic components, rejecting
childrenand the target's own props once you added a prop of your own:const Styled = styled(MantineButton)<{ $variant: 'a' | 'b' }>``; <Styled $variant="a" variant="filled"> this now works </Styled>;
Wrapping such a target without adding props already worked; adding one turned the permissiveness off. Your own declared props stay strictly typed either way.
styled-components@6.5.0-prerelease-20260804151232
Minor Changes
-
dfe4baf: React Native components now check
styleagainst React Native's own style types. Web-only CSS such asfloat, and CSS custom properties such as--brand, were previously accepted even though React Native has never done anything with them at runtime. They now surface as a type error where you write them instead of silently doing nothing.const Card = styled.View``; <Card style={{ padding: 16 }} />; // unchanged <Card style={{ float: 'left' }} />; // now a type error
Web components are unaffected and still accept custom properties.
-
dfe4baf: Declaring your own
styleprop type now constrains the fields you name while leaving the rest of CSS alone. Previously a declaration likestyled.div<{ style?: { width: number } }>was quietly ignored, because the built-in style type was applied after your props, so any CSS value was still accepted. Nowwidthhas to be a number, whilecolor, custom properties, and everything else you did not mention keep working as before.To remove a field rather than constrain it, declare it as
never. To make your type the only thing accepted, wrap it in the newCustomStylehelper, which removes every field you did not list:const Box = styled.div<{ style?: CustomStyle<{ width: number }> }>``;
The constraint holds when the component is rendered through
asorforwardedAs, so it cannot be sidestepped by rendering the same component as a different tag. Note thatCustomStyleremoves CSS custom properties too, since they are among the fields you did not list.One thing to know if you use
exactOptionalPropertyTypes: on a component that declares its ownstyle, passingstyle={undefined}explicitly is now rejected. Leaving the prop off is unaffected. Writestyle?: { width: number } | undefinedin your declaration if you need to pass it explicitly.Relatedly, reading the style type back off a component (for example with
React.ComponentProps) now reports that CSS custom properties are accepted, which matches what was already allowed when rendering. -
dfe4baf: Large TypeScript projects type-check dramatically faster. On a 500-component app,
tsccheck time drops to under a quarter of what 6.4.4 takes and peak memory to under a third, which resolves the out-of-memory failures some projects hit after upgrading past 6.4.2. Both are now better than 6.4.2 was, so there is no longer a reason to pin to it. Editor responsiveness improves by the same margin, and autocomplete onastargets is unchanged.
Patch Changes
-
dfe4baf: Fixed
refbeing rejected on React Native components created with the shorthand syntax, such asstyled.TextInput. Passing a ref, or a ref callback whose parameter you have not annotated, now works the same way it does withstyled(TextInput).Also fixed a type error when a component's
attrscallback is given an explicit parameter type, as instyled.div.attrs<MyProps>(props => props). -
dfe4baf: Fixed components built on targets whose props cannot be inspected, such as Mantine's polymorphic components, rejecting
childrenand the target's own props once you added a prop of your own:const Styled = styled(MantineButton)<{ $variant: 'a' | 'b' }>``; <Styled $variant="a" variant="filled"> this now works </Styled>;
Wrapping such a target without adding props already worked; adding one turned the permissiveness off. Your own declared props stay strictly typed either way.
Full Changelog: styled-components@6.4.4...styled-components@6.5.0-prerelease-20260804151232
styled-components@7.0.0-prerelease-20260731041038
No new changes since the previous release.
Full Changelog: styled-components@7.0.0-prerelease-20260731035917...styled-components@7.0.0-prerelease-20260731041038
styled-components@7.0.0-prerelease-20260731035917
Minor Changes
-
Client styles inject through
useInsertionEffect. (buffered-injection-default.md)Class names are still resolved during render so elements get the right
classon the first paint, but the stylesheet write runs in the insertion effect after React commits. Discarded concurrent renders no longer leave rules in the document, and a committed update still gets its rules even when an earlier concurrent attempt for the same styles was discarded. Blocking updates (concurrent features off) behave the same: styles apply on commit, not mid-render.ServerStyleSheetSSR and React Server Components still flush during render, where insertion effects do not run. -
Smaller bundles:
styled.divand every other element shorthand is built the first time it is read, so an app ships no table of element names and pays only for the tags it uses. (lazy-element-shorthands.md)styled.div,styled.feBlendand the rest behave exactly as before, including returning the same component factory on repeated reads, and'div' in styledstill answerstrue. Two things differ if you inspectstyleditself:Object.keys(styled)no longer lists every tag, and reading a lowercase name that is not a standard element (styled.blink) now hands back a working factory rather thanundefined, matching whatstyled('blink')has always done. CamelCase probes such astoJSONstay undefined.Published bundles are also emitted as ES2020 rather than ES2015. Every supported peer (React 19, React Native 0.85, Node 16) runs that syntax natively.
Full Changelog: styled-components@7.0.0-prerelease-20260731032118...styled-components@7.0.0-prerelease-20260731035917
styled-components@7.0.0-prerelease-20260731032118
No new changes since the previous release.
Full Changelog: styled-components@7.0.0-prerelease-20260731031704...styled-components@7.0.0-prerelease-20260731032118