Focus on naming is very important.

Styled components as the name suggests are for styling the native DOM elements or custom components.

attrs is for mentioning the attributes of that very same DOM element in the attrs constructor without the need to even mention it in actual component call.

What above line means is you can do

 <Input placeholder="A small text input" />

with

const Input = styled.input.attrs(({ type }) => ({
  type:  type || "password"
}))`
  align-items: center;
  display: flex;
  margin: 1.5vh 0;
`

See that component usage <Input .../> doesn't have type prop anywhere. It came from your attribute constructor function(static)

You couldn't have done this otherwise in your style rules because these are just the string literal of your CSS properties.

It saved you from writing type='password' in every usage of

<Input type='password' ... />

Bonus:

Now, that's a specific input component with type attribute of password. What if you wish to have a general input (styled component) with any value of type attribute?

Tada!


const Input = styled.input.attrs(({ type }) => ({
  
  type:  type || "password",
  ...

Your type is now dynamic i.e. it will take whatever input type prop you specify from your usage of component and render the input as that type (text, password, file etc. ) or if you skip the type prop it will pick up default of password. You can use as much conditional logic as you want up there.

Example:

<Input .../> // renders type="password"
<Input type="text" .../>
<Input type="email" .../>

Hope that answers your question.

Answer from HalfWebDev on Stack Overflow
🌐
styled-components
styled-components.com › docs › api
styled-components
This is a chainable method that attaches some props to a styled component. The first and only argument is an object that will be merged into the rest of the component's props. The attrs object accepts the following values:
Top answer
1 of 6
32

Focus on naming is very important.

Styled components as the name suggests are for styling the native DOM elements or custom components.

attrs is for mentioning the attributes of that very same DOM element in the attrs constructor without the need to even mention it in actual component call.

What above line means is you can do

 <Input placeholder="A small text input" />

with

const Input = styled.input.attrs(({ type }) => ({
  type:  type || "password"
}))`
  align-items: center;
  display: flex;
  margin: 1.5vh 0;
`

See that component usage <Input .../> doesn't have type prop anywhere. It came from your attribute constructor function(static)

You couldn't have done this otherwise in your style rules because these are just the string literal of your CSS properties.

It saved you from writing type='password' in every usage of

<Input type='password' ... />

Bonus:

Now, that's a specific input component with type attribute of password. What if you wish to have a general input (styled component) with any value of type attribute?

Tada!


const Input = styled.input.attrs(({ type }) => ({
  
  type:  type || "password",
  ...

Your type is now dynamic i.e. it will take whatever input type prop you specify from your usage of component and render the input as that type (text, password, file etc. ) or if you skip the type prop it will pick up default of password. You can use as much conditional logic as you want up there.

Example:

<Input .../> // renders type="password"
<Input type="text" .../>
<Input type="email" .../>

Hope that answers your question.

2 of 6
6

The goal of .attrs is so it can be passed down from your props. So you can use props inside your styled, and you can create placeholders, or change colors depending of the props etc...

For example :

const InputText = styled.input.attrs({
  type: 'text',
  placeholder: props => props.placeholder || 'Please fill',
})`
  padding: 6px 12px; 
`;
🌐
Medium
medium.com › @magnus_junghard › efficient-styled-component-manipulations-e32ef338f93b
Efficient Styled-component manipulations with attrs | by Magnus Junghard | Mar, 2022 | Medium | Medium
March 9, 2022 - After a while we start getting this warning message from styled components. ... Attrs allows us to manipulate the attributes directly on the component we generate using styled components.
Top answer
1 of 1
20

(TL;DR at the end)

The problem is that you're reading about two separate use-cases, and assuming that they are explaining the same thing.

The Styled Components .attrs method is for passing props to a styled component. When the docs say that you should use .attrs "when you want every instance of a styled component to have that prop", they mean something like this:

const CheckboxInput = styled.input.attrs({ type: "checkbox" })`
   margin: 10px;
`;

This means that when you use <CheckboxInput />, it will be a checkbox by default, no need to define the prop type="checkbox" every time. This is the main purpose of the .attrs method.

So you understand that when you add style to that component's attrs, it's exactly the same as passing style as a prop to a regular, non-styled component. It just adds that style as an inline style, skipping any optimisation that styled-components might make. Inline styles aren't usually recommended because they will always be attached as an individual style to every version of that component. Example:

// items is some array with 100 elements
items.map(item => (
  <button style={{ background: 'blue' }} >{item.text}</button>
));

This would generate 100 buttons, and each button would have their own instance of the background: blue style.

With Styled Components, you would do this:

const button = styled.button`
   background: blue;
`;

This would generate the style only once, no matter how many buttons you have. Because it actually generates a CSS class.

Unfortunately, generating CSS classes isn't a lightweight operation, so if for instance you're doing animations or doing anything that changes a style frequently, it's recommended to go with inline styles instead.

TL;DR:

  • Use styled components for static styles and dynamic styles that don't change very often;
  • Use inline styles (through .attrs) for styles that change frequently, like for animations.
🌐
Scalablecss
scalablecss.com › styled-components-attrs
Quick Start Guide to Attrs in Styled Components - Scalable CSS
May 25, 2020 - This is much more efficient than adding a prop to every component if you find yourself turning to the same attribute over and over. ... The rule of thumb is to use attrs when you want every instance of a styled component to have that prop, and pass props directly when every instance needs a different one -Styled Components Docs
🌐
GitHub
github.com › styled-components › styled-components › issues › 4314
Setting prop via `.attrs()` is not making the prop on the final component optional · Issue #4314 · styled-components/styled-components
May 20, 2024 - @@ -210,7 +210,7 @@ interface MyStyle extends StyledObject<object> { textTransform?: StyledObject<object>['textTransform']; } -const DivWithRequiredProps = styled.div.attrs<{ foo?: number; bar: string }>({ +const DivWithRequiredProps = styled.div.attrs<{ foo: number; bar: string }>({ foo: 42, // Providing required prop foo, which makes it optional })``; @@ -221,7 +221,7 @@ const DivWithRequiredProps = styled.div.attrs<{ foo?: number; bar: string }>({ // @ts-expect-error and bar is still required <DivWithRequiredProps />; -const DivWithUnfulfilledRequiredProps = styled.div<{ foo?: number; bar: string }>``; +const DivWithUnfulfilledRequiredProps = styled.div<{ foo: number; bar: string }>``; // same test as above but with a wrapped, typed component const RequiredPropsProvidedAsAttrs = styled(DivWithUnfulfilledRequiredProps).attrs({
Published   May 20, 2024
Author   AntonNiklasson
🌐
CodeVertiser
codevertiser.com › styled-components-attrs-with-react-img-tag
How to use Styled-Components .attrs Method with Reactjs img Tag
In this tutorial, you will learn how to use locally downloaded images with styled-components. We will use the img tag with the .attrs method of styled-components.
🌐
GitHub
github.com › styled-components › styled-components › issues › 4183
styled-component does not inherit props passed through attrs method in react-native · Issue #4183 · styled-components/styled-components
September 29, 2023 - given the following component, typescript recognise source and resizeMode as valid props · const BlurImage = styled.Image.attrs({ source: blur, resizeMode: 'stretch' })' width: 100%; height: 100%; '; Typescript doesn't show any error · 👍React with 👍9Martinocom-Switcho, Martinocom, yildizberkay, JeyongOh-MAASASIA, mattia-sanfilippo and 4 more ·
Author   notOltioff
Find elsewhere
🌐
Medium
medium.com › @justiceotuya › how-to-add-classnames-to-styled-components-f1f88518ab51
How to add ClassNames to Styled Components | by Otuya Justice | Medium
February 19, 2020 - The .attrs object also takes functions, that receive the props that the component receives. The return value will be merged into the resulting props as well. ... We use the attrs constructor which exposes the className and then we can bind our className props to the attrs className. we can now style the dynamic classNames accordingly
🌐
freeCodeCamp
freecodecamp.org › news › styled-components-in-react
How to Use Styled Components in Your React Apps
October 16, 2024 - Styled-components is a library that allows you to write CSS in JS while building custom components in Reactjs. There are multiple options you can go with to style a React application.
🌐
Emotion
emotion.sh › docs › styled
Emotion – Styled Components
You can also use @emotion/is-prop-valid (which is used by emotion internally) to filter out props that are not valid as html attributes. ... You can create dynamic styles that are based on props and use them in styles. ... To use styles from a styled component but change the element that's rendered, you can use the as prop.
🌐
Josh W. Comeau
joshwcomeau.com › react › demystifying-styled-components
Demystifying styled-components • Josh W. Comeau
June 21, 2021 - For so many React devs, styled-components seems kinda magical. It isn't at all clear how it uses traditional CSS features under-the-hood, and that lack of clarity can cause real problems when things go awry. In this post, we'll learn exactly how styled-components works by building our own ...
Top answer
1 of 2
13

Answer 1: Warning about fill

You need to choose a different name, maybe full, but not fill for your styled component. As fill is a standard attribute of some HTML elements. Also, at w3schools

Experiment:

If you declare fill to be string and pass it a string value, you can see a fill attribute added to you to div in HTML DOM, example:

<div
  fill="test"
  style="background-image: url(&quot;/media/images/image_file.png&quot;);" class="sc-AxiKw jDjxaQ">
</div>

fill is a property in SVGAttributes interface:

from node_modules/@types/react/index.d.ts:

interface SVGAttributes<T> extends AriaAttributes, DOMAttributes<T> {
  // Attributes which also defined in HTMLAttributes
  className?: string;
  id?: string;
  ...
  // SVG Specific attributes
  accentHeight?: number | string;
  ...
  fill?: string;
  ...
}

That's the reason of this warning:

Warning: Received `true` for a non-boolean attribute `fill`.
If you want to write it to the DOM, pass a string instead: fill="true" or fill={value.toString()}.

Answer 2: Why interface is required 2 times?

Below is the excerpt from related interface:

attrs<
      U,
      NewA extends Partial<StyledComponentPropsWithRef<C> & U> & {
          [others: string]: any;
      } = {}
  >(
      attrs: Attrs<StyledComponentPropsWithRef<C> & U, NewA, T>
  ): ThemedStyledFunction<C, T, O & NewA, A | keyof NewA>;

U becomes : IBottleComponentProps which you pass C is HTML element or react component type

And the return type is ThemedStyledFunction<C, T, O & NewA, A | keyof NewA>:

export interface ThemedStyledFunction<
    C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
    T extends object,
    O extends object = {},
    A extends keyof any = never

where C, T were already provided. You are providing O by passing IBottleComponentProps the 2nd time.

If you don't provide it your BottleComponent will look like below one with {} for the props i.e. no props:

If you provide, it will look like below one, with the right props.

In short, you have to provide the interface 2 times for now. You can provide any if you don't have your interface defined.

2 of 2
1

Looks like second type variable information is losing information from the first type.

Here's the definition of attr

export interface ThemedStyledFunction<
    C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
    T extends object,
    O extends object = {},
    A extends keyof any = never
> extends ThemedStyledFunctionBase<C, T, O, A> {
    // Fun thing: 'attrs' can also provide a polymorphic 'as' prop
    // My head already hurts enough so maybe later...
    attrs<
        U,
        NewA extends Partial<StyledComponentPropsWithRef<C> & U> & {
            [others: string]: any;
        } = {}
    >(
        attrs: Attrs<StyledComponentPropsWithRef<C> & U, NewA, T>
    ): ThemedStyledFunction<C, T, O & NewA, A | keyof NewA>;

According to that NewA type variable should have necessary information from U type.

The result is however ThemedStyledFunction<"div", any, {}, never>

Ideally it would be similar to ThemedStyledFunction<"div", any, StyleProps & IBottleComponentProps, "style" | "fill">

type IBottleComponentProps = {
  fill?: boolean
}

type StyleProps = {
  style: {
    backgroundImage: string;
  }
}

const BottleComponent = styled.div.attrs<IBottleComponentProps, StyleProps & IBottleComponentProps>(({fill}) => ({
  style: {
    backgroundImage: `url("")`
  }
}))`
  width: 20px;
  height: 20px;
`;

🌐
GitHub
github.com › styled-components › styled-components › issues › 1959
How do you use `attrs` with TypeScript? · Issue #1959 · styled-components/styled-components
August 29, 2018 - Hi, it's unclear how attrs should be used with TypeScript, I'm not sure if there's just a bug in the types. Here's what we've got so far, this is the only way to make the component definition work as expected, but then the component usage fails with the error [ts] Type 'string' is not assignable to type 'never'.. import styled from '../utils/mural-styled-components'; interface AdditionalProps { readonly size: string; } interface ChangedProps { readonly type: string; readonly margin: string; readonly padding: string; } const WeirdComponent = styled.input.attrs<AdditionalProps, ChangedProps>({ /
Author   ryasmi
🌐
GitHub
github.com › styled-components › styled-components › issues › 4138
v6 .attrs() types are broken · Issue #4138 · styled-components/styled-components
August 22, 2023 - import type { FC } from "react"; import styled from "styled-components"; import { createRoot } from "react-dom/client"; type ContainerProps = { color: string; }; const Container: FC<ContainerProps> = ({ color }) => { return <div style={{ color }} />; }; const StyledContainer = styled(Container).attrs({ color: 'red' })``; function App() { return <StyledContainer />; // TS Error: "color" props is missing } const root = createRoot(document.getElementById("root")!); root.render(<App />); No TS error, just like in styled-components v5 ·
Author   laboskin
🌐
GitHub
github.com › DefinitelyTyped › DefinitelyTyped › issues › 28597
[@types/styled-components] How do you use `attrs`? · Issue #28597 · DefinitelyTyped/DefinitelyTyped
September 3, 2018 - import styled from '../utils/mural-styled-components'; interface AdditionalProps { readonly size: string; } interface ChangedProps { readonly type: string; readonly margin: string; readonly padding: string; } const WeirdComponent = styled.input.attrs<AdditionalProps, ChangedProps>({ // we can define static props type: 'password', // or we can define dynamic ones margin: (props) => props.size || '1em', padding: (props) => props.size || '1em', })` color: palevioletred; font-size: 1em; border: 2px solid palevioletred; border-radius: 3px; /* here we use the dynamically computed props */ margin: ${(props) => props.margin}; padding: ${(props) => props.padding}; `; import React from 'react'; export const X = () => ( <WeirdComponent size="massive"/> ); // [ts] Type 'string' is not assignable to type 'never'.
Author   ryasmi
🌐
egghead.io
egghead.io › lessons › react-use-the-attrs-method-to-add-html-attributes-in-styled-components
Use the `attrs` method to add HTML attributes in styled-components | egghead.io
[00:13] It's hard for us to remember this as developers sometimes. That's why I want to talk about attrs, which are a chainable method that exists in styled-components that allows you to push attributes into your actual HTML element.
🌐
Motoki-watanabe
tech.motoki-watanabe.net › entry › 2021 › 10 › 02 › 130740
styled-componentsですごい頻度でpropsを更新し続けていたらattrsメソッドを使えと怒られた - 青いやつの進捗日記。
October 2, 2021 - react_devtools_backend.js:2842 Over 200 classes were generated for component Seekbar__Preview with the id of "Seekbar__Preview-sc-16onun1-1". Consider using the attrs method, together with a style object for frequently changed styles.
🌐
Yockyard
yockyard.com › post › dynamic-styled-components
Highly Dynamic Styled-Components | Yockyard
February 15, 2022 - By digging through the GitHub of the styled-components project and looking for others with the same problem I was able to find this thead. You’re able to apply a “style” prop to the higher-order Component via the .attrs method.