React Styled Components — More Complex Selectors and Selectively Passing Props
Tags: react, webdev, programming, javascript
Published: 2021-01-23 19:50:25

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps.

In this article, we’ll look at creating styled-components with pseudo selectors and creating styled wrappers for other components.

### Define Styled Components Outside of the Render Method

We can define styled-components outside of the render method with `styled-components` .

For instance, we can define a wrapper component as follows:

```
import React from "react";
import styled from "styled-components";

const StyledWrapper = styled.div`
  font-weight: bold;
`;

const Wrapper = ({ message }) => {
  return <StyledWrapper>{message}</StyledWrapper>;
};

export default function App() {
  return (
    <div className="App">
      <Wrapper message="foo" />
    </div>
  );
}
```

In the code above, we created the `StyledWrapper` component with its own styles. Then we created the `Wrapper` component which uses it. with the `message` prop passed inside. Then we can ass `message` as a prop to `Wrapper` used in `App` .

Therefore, we’ll see the word ‘foo’ bolded displayed on the screen.

### Pseudoelements, Pseudoselectors, and Nesting

`styled-components` supports SCSS-like syntax for defining styles for a styled component. The preprocessor that uses for transforming CSS is stylis.

For instance, we can write the following code to define styles with props and stylis code as follows:

```
import React from "react";
import styled from "styled-components";

const Thing = styled.div.attrs(() => ({ tabIndex: 0 }))`
  color: blue;
  &:hover {
    color: red;
  }
  & ~ & {
    background: tomato;
  }
  & + & {
    background: lime;
  }
  &.foo {
    background: orange;
  }
  .foo & {
    border: 1px solid ${props => (props.primary ? "red" : "green")};
  }
`;

export default function App() {
  return (
    <div className="App">
      <Thing>foo</Thing>
      <Thing className="foo" primary>
        <Thing>abc</Thing>
        <Thing primary>abc</Thing>
        bar
      </Thing>
      <Thing className="bar">baz</Thing>
      <Thing>baz</Thing>
    </div>
  );
}
```

In the code above, we have the `Thing` component, where we defined styles with pseudo selectors.

`&:hover` is the selector for when `Thing` is hovered.

`& ~ &` is the selector for the sibling of `Thing` but it may not be directly next to it.

`& + &` is the `Thing` next to a `Thing` .

`&.foo` is the `Thing` with a `foo` CSS class.

`.foo &` is the `Thing` inside something with the `foo` class. We also have a dynamic style with `${props => (props.primary ? “red” : “green”)}` where we check for the `primary` prop and then apply the color accordingly.

Then we get the following colored text:

![](https://cdn-images-1.medium.com/max/800/1*_iLnNUBtn56UGwbCIndtNg.png)

We can add the `&&` pseudoselector to increase the specificity of the rules on the component.

For instance, we can write:

```
import React from "react";
import styled from "styled-components";

const Thing = styled.div`
  && {
    color: blue;
  }
`;

export default function App() {
  return (
    <div className="App">
      <Thing>foo</Thing>
    </div>
  );
}
```

Then we only apply the specified style to `Thing` . Therefore, we avoid conflicts with styles in other components with `&&` .

![](https://cdn-images-1.medium.com/max/800/0*6EWIIYfNAKR-RWVf)Photo by [Pineapple Supply Co.](https://unsplash.com/@pineapple?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

### Attaching Additional Props

We can pass in a callback to the `attrs` method so that we can choose the props that the base element receives. For instance, if we have an input and we want it to only receive the `value` attribute and the `size` prop, we can write:

```
import React from "react";
import styled from "styled-components";

const Input = styled.input.attrs(({ value, size }) => ({
  size,
  value
}))`
  color: palevioletred;
  font-size: 1em;
  margin: ${props => props.size};
  padding: ${props => props.size};
`;

export default function App() {
  return (
    <div className="App">
      <Input value="foo" size="5px" />
    </div>
  );
}
```

In the code above, we took the `value` and`size` props and set them as attributes in the callback that we pass into the `attrs` method.

We also passed in the `size` prop into our styles dynamically in the string.

Then when we add the `Input` with the `value` set to `'foo'` and `size` set to `'5px'` , then we’ll see those reflected in our styled input.

### Conclusion

We can create styled components that are outside of the render method. Also, in addition to CSS selectors, we can use SCSS selectors for selecting elements.

The `&` selector is useful for selecting the current element. We can then use other selectors to select neighboring or child elements.

Also, we can use the `&&` selector to select one specific element.

Finally, we can use the `attrs` method to selectively pass props as attribute values of components.