Creating React Styled Components with Dynamic Tags and Props

John Au-Yeung - Jan 23 '21 - - Dev Community

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 how to create React styled-components with varying tags with the styled-components package fo React.

Changing the Tags When Rendering Styled Components

We can pass in the as prop to render a styled component with different tags than we originally defined them as. For instance, we can write the following code to do that:

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

const Title = styled.h1`
  color: palevioletred;
  font-size: 1.5em;
  margin: 1em;
`;

const GreenTitle = styled(Title)`
  color: green;
`;

const BlueTitle = styled(Title)`
  color: blue;
`;

export default function App() {
  return (
    <div className="App">
      <Title>hello</Title>
      <GreenTitle as="p">hello</GreenTitle>
      <BlueTitle as="span">hello</BlueTitle>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have multiple styled-components with several variations. Then in App , we added the as prop we want to render the component so that we can render the way we want to them do.

Now when we inspect the components, we’ll see that the rendered element has the same tag as we specified in the as prop.

The as prop also works with custom components. For instance, we can write the following code to change the tag that’s rendered in a component that’s defined without using styled-component :

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

const H1 = styled.h1`
  color: green;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  display: block;
`;

const Title = ({ children, ...props }) => <H1 {...props}>{children}</H1>;

export default function App() {
  return (
    <div className="App">
      <Title as="p">hello</Title>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the Title component, which returns the H1 component. We pass all the props to the H1 component, and the children in between the H1 tags.

Then we can use the as prop on the H1 . There’s no difference if we pass in the as directly or passing the as prop through another component. As long we the as prop ends up in a component that’s created with styled-components , the as prop can be applied.

Therefore, we should get the p element displayed instead of H1 as we originally created it.

Styling Any Component

The styled method works on any component, as long we attached the passed className prop a DOM element.

For instance, we can use it as follows:

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

const Title = ({ className, children }) => (
  <h1 className={className}>{children}</h1>
);

const StyledTitle = styled(Title)`
  color: green;
  font-weight: bold;
`;

export default function App() {
  return (
    <div className="App">
      <Title>hello</Title>
      <StyledTitle>hello</StyledTitle>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The className is passed from the props in Title so that we can apply the class name generated by the styled-components package to apply the styles.

To create the StyledTitle component, we called the styled function with the Title component passed in. Then we can applied the styles with the template as we did with component built into styled-components.

When we render both components in App , we see that the top title has no styling and the second one has styling.

Photo by Shyam Sundar Hemamalini on Unsplash

Passed Props

Props that are passed into styled-components are passed in as attributes of HTML elements. If the component being modified is a React component, then the props are passed through as props.

For instance, we can pass in the value attribute to our styled input element as follows:

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

const Input = styled.input`
  padding: 0.5em;
  margin: 0.5em;
  color: ${props => props.inputColor || "palevioletred"};
  border-radius: 3px;
`;

export default function App() {
  return (
    <div className="App">
      <Input value="foo" inputColor="red" />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

As we can see, we just pass them in as we did with any HTML element., Then the input will be displayed since we passed in 'foo' for value .

Therefore, we should see 'foo' displayed as the value of the input.

For React components, we can pass props to them as follows:

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

const Foo = ({ text, ...style }) => <p style={style}>{text}</p>;

const StyledFoo = styled(Foo)`
  padding: 0.5em;
  margin: 0.5em;
  color: ${props => props.color || "palevioletred"};
  border-radius: 3px;
`;

export default function App() {
  return (
    <div className="App">
      <StyledFoo color="red" text="foo" />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we passed in the text and color props. The text prop ends up between the p tags of Foo . The styles are in the style prop and are passed into the style prop of p.

Conclusion

We can style any HTML element as if we pass in the className prop generated by styled-components to the component that we want to style.

Also, we can change the tag that the styled component is rendered as with the as prop.

Finally, we can pass props into styled elements as we do with any other HTML element.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .