How to Style Nested Elements in React with Styled-Components

How to style a nested functional component using styled components

I don't see a reason for three components, a pattern that works for me is using dot notation:

const StyledButton = styled.button``;
const Button = (props) => {
return (
<StyledButton className={props.className}>
{props.loading && <LoadingSpinner />}
{props.children}
</StyledButton>
);
};

Button.Styled = StyledButton;
export default Button;

In this way, you have a pattern where Component.Styled (if available) will always hold the runtime CSS-in-JS object which you can target.

Then in ButtonGroup implementation:

import { Button } from "@components";

// You can target the className
const ButtonGroup = styled.div`
${Button.Styled} { ... }
`;

// You can apply styles
styled(Button)

// You can use the component
<Button />

// Or extend style etc
<OtherButton as={Button.Styled} .../>

How do I style a component that has `styled-components` nested in it?

When you're using styled(YourComponent), assuming YourComponent is a normal Component and not already a styled-component, this will automatically provide the className property to the component. You simple need to put that somewhere.

export const Relative = styled.div`
position: relative;
`

export const Container = ({ children }) => {
return (
<Relative>
<AnotherComponent/>
{children}
</Relative>
)
}

export const MyComponent = ({ className, children }) => {
return (
<div className={className}>
<Container>
{children}
</Container>
</div>
)
}

export const CustomMyComponent = styled(MyComponent)`
// Styles inside here will be applied to the root element of MyComponent
`;

Styling nested components using styled components

EDIT:

Since you want the styles to apply to a custom component, you also need to manually assign the className generated by styled-components to the top-level element of that component. Something like:

const FieldWrapper = props => {
return (
<Div className={props.className}>
<Label>
<Input />
</Label>
</Div>
);
}

The problem is likely related to CSS Specicifity, meaning that the original css styles defined in FieldWrapper has higher "importance" than the ones in Form. If you inspect your element you can probably see that both styles are applied, but the former has precendence over the latter.

A way to solve that is to either use the !important rule to each of the input styles defined in your Form component. Another would be to add a class to <Input /> and define your styles as myClass.input. Basically anything that would increase the specicifity of the rules you want to apply.

See the above link for more info of how to do that. Also check out Cascade and inheritance:

Once you understand the fact that source order matters, at some point you will run into a situation where you know that a rule comes later in the stylesheet, but an earlier, conflicting, rule is applied. This is because that earlier rule has a higher specificity — it is more specific, and therefore is being chosen by the browser as the one that should style the element.

As we saw earlier in this lesson, a class selector has more weight than an element selector, so the properties defined on the class will override those applied directly to the element.

Something to note here is that although we are thinking about selectors, and the rules that are applied to the thing they select, it isn't the entire rule which is overwritten, only the properties which are the same.


The amount of specificity a selector has is measured using four different values (or components), which can be thought of as thousands, hundreds, tens and ones — four single digits in four columns:

  1. Thousands: Score one in this column if the declaration is inside a style attribute, aka inline styles. Such declarations don't have selectors, so their specificity is always simply 1000.
  2. Hundreds: Score one in this column for each ID selector contained inside the overall selector.
  3. Tens: Score one in this column for each class selector, attribute selector, or pseudo-class contained inside the overall selector.
  4. Ones: Score one in this column for each element selector or pseudo-element contained inside the overall selector.

Here is an example from MDN:

/* specificity: 0101 */
#outer a {
background-color: red;
}

/* specificity: 0201 */
#outer #inner a {
background-color: blue;
}

How to style nested elements in react with styled-components?

It looks like JSS syntax, not styled component.

Change this:

const styles = theme => ({
root: {
...theme.typography.button,
backgroundColor: theme.palette.common.white,
padding: theme.spacing.unit,
">span": {
background: "red"
}
}
});

With this:

const styles = theme => ({
root: {
...theme.typography.button,
backgroundColor: theme.palette.common.white,
padding: theme.spacing.unit,
"& span": {
background: "red"
}
}
});

or if you wouldn't that change all nested spans

const styles = theme => ({
root: {
...theme.typography.button,
backgroundColor: theme.palette.common.white,
padding: theme.spacing.unit,
"& > h1 > span": {
background: "red"
}
}
});

Try this codesandbox https://codesandbox.io/s/vm3qnmj75l

For reference:
http://cssinjs.org/jss-nested/

Is there any way I can style the nested component?

I see several issues here, but in the first place it seems like the problem is caused by the fact that you're not attaching the className prop to what's inside Menu.

See https://styled-components.com/docs/basics#styling-any-component and this Codesandbox: https://codesandbox.io/s/sweet-carlos-vt165s



Related Topics



Leave a reply



Submit