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
It passes it on to the HTML node if it's a valid attribute, otherwise it only passes it into interpolated functions. (see Tagged Template Literal) You can pass an arbitrary classname to a styled component without problem and it will be applied next to the styles defined by the styled call.
🌐
styled-components
styled-components.com › docs › basics
Styled Components Basic
This way you can for example attach static props to an element or pass a third-party prop like data-testid to a component. Furthermore, you can also attach more dynamic props to a component. The .attrs object also takes functions, that receive the props that the component receives.
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; 
`;
🌐
DEV Community
dev.to › elijahtrillionz › complete-guide-on-how-to-use-styled-components-in-react-360c
Complete Guide On How To Use Styled-components In React - DEV Community
February 19, 2022 - You must pass in the className prop in the parent element of the component to be styled because with it styled component can apply the given styles to the component. Apart from custom components, you can also style components that you did not ...
🌐
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 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
🌐
N's Blog
naura.hashnode.dev › how-to-pass-classname-to-styled-components-in-react
How to Pass className to Styled-Components in React
September 16, 2022 - So now we can write regular CSS with classNames inside our <Badge /> component; export const Badge = styled.div.attrs((props) => ({ className: props.className }))` /* ...existing styles */ &.react { background-color: #f2fbdc; color: #a7c957; } &.styled-components { background-color: #f9f5ff; color: #6941c6; } &.web-dev { background-color: #fdf2fa; color: #c11574; } `;
🌐
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 - To solve this we could put the variables inside the attrs method and let the static styles live in the string-interpolation. If we now inspect the head-element in the console we can see that this component does not create thousands of classes, instead it uses the same since it doesn’t need to render a new class for each new x and y that we use.
Find elsewhere
🌐
Softchris
softchris.github.io › pages › react-styled-components.html
Styled components, the styling library for your React apps you don’t want to be without
There are a ton of ways to style components in React. This is probably my favorite way of doing it and it differs somewhat conceptually from other ways of styling. ... When you start out styling your React components you may opt for defining CSS classes and assigning them to each element, like so: <div className=”card”> <div className=”card-header”> <h3>{card.header}</h3> </div> <div className=”content”>{card.content}</div> </div>
🌐
GitHub
github.com › styled-components › styled-components › issues › 2270
attrs() are no longer merged in v4 · Issue #2270 · styled-components/styled-components
December 4, 2018 - const Tooltip = styled.div.attrs({ className: 'tooltip' })``; const LightTooltip = styled(Tooltip).attrs({ className: 'tooltip--light' })``; In v4 it doesn't seem that this type of attrs() merging is possible. Doesn't seem to be possible even with a .attrs(props => ({})) callback. Is this expected? It seems some attributes are shallow merged (like styles in #1877). Should this have the same treatment if it's a common pattern? CodeSandbox default create-react-app environment. ... Create another styled-component that wraps the original component styled(InnerComponent) which also provides a className via the attrs() method
Author   austingreendev
🌐
Tabnine
tabnine.com › home page › code › javascript › themedstyledfunction
styled-components.ThemedStyledFunction.attrs JavaScript and Node.js code examples | Tabnine
styled.button.attrs(props => ({ className: classNames({ 'plain-button': true, flex: true, 'flex--v-center': true, [font('hnm', 5)]: true, }), }))
🌐
Gitter
gitter.im › styled-components › styled-components
styled-components/styled-components - Gitter
const Btn = styled.button.attrs({ className: 'btn' })` common shared button css code ` export default Btn ... So instead of passing props, i switch component ...
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.
🌐
Jser
jser.dev › 2023-10-09-styled-components
The Internals of Styled Components
: 'className' ] = classString; propsForElement.ref = forwardedRef; return createElement(elementToBeCreated, propsForElement); -------------------------------------------------- } function useStyledComponentImpl<Props extends object>( forwardedComponent: IStyledComponent<'web', Props>, props: ExecutionProps & Props, forwardedRef: Ref<Element> ) { const { attrs: componentAttrs, componentStyle, defaultProps, foldedComponentIds, styledComponentId, target, } = forwardedComponent; const contextTheme = React.useContext(ThemeContext); const ssc = useStyleSheetContext(); const shouldForwardProp = forwardedComponent.shouldForwardProp || ssc.shouldForwardProp; // NOTE: the non-hooks version only subscribes to this when !componentStyle.isStatic, // but that'd be against the rules-of-hooks.
🌐
GitHub
github.com › styled-components › styled-components › issues › 728
Components with secondary classnames · Issue #728 · styled-components/styled-components
April 21, 2017 - Hi, I'm wondering if there is a solution to using styled-components with existing libraries. Lots of libraries adopt customization to css via multiple className props. For example, react-select uses className and optionClassName in a component.
🌐
Medium
medium.com › styled-components › how-styled-components-works-618a69970421
How styled-components works: A deep dive under the hood | by Eugene Gluhotorenko | 💅 styled-components | Medium
August 15, 2018 - For our Button instance the generated className is jsZVzX. Then this class name is stored in the component state as generatedClassName. 3. CSS Preprocessing: Here is where the super fast stylis CSS preprocessor comes to the rescue and helps to obtain valid CSS string: ... 4. Injecting CSS string into the page: Now the CSS should be injected into the <style> element in the head of the page right after the component’s comment marker:
🌐
GitHub
github.com › styled-components › styled-components › issues › 1250
It's impossible to extend styled components with attrs · Issue #1250 · styled-components/styled-components
November 17, 2017 - const Param = styled.div` order: ${props => props.order}; ` and then we will try to extend our component with attributes · const Label = Param.attrs({ className: 'someclass', })` overflow: hidden; text-overflow: ellipsis; ` Seems that it should be possible to add attrs to styled primitve component ·
Author   kajas90
🌐
LogRocket
blog.logrocket.com › home › 8 awesome features of styled-components
8 awesome features of styled-components - LogRocket Blog
June 4, 2024 - To tell styled-components the type of input element you want, use the attrs method.