Only Styled-component Classes Can Be Targeted in This Fashion

  • 12 min read
  • CSS, React, CSS-in-JS, JavaScript, Tools

Quick summary ↬ While the component-driven arroyo has ushered in a new borderland in the way we build web applications, it isn't without its imperfections — 1 being its usability and scalability with CSS. This has given birth to a new way to construct and manage our styles in a component-specific manner, otherwise knows as CSS-in-JS.

Styled components are a CSS-in-JS tool that bridges the gap between components and styling, offering numerous features to get you upward and running in styling components in a functional and reusable way. In this article, you'll learn the basics of styled components and how to properly use them to your React applications. You should have worked on React previously before going through this tutorial. If you're looking for diverse options in styling React components, you can check out our previous postal service on the subject.

At the cadre of CSS is the capability to target any HTML element — globally — no matter its position in the DOM tree. This can be a hindrance when used with components, because components need, to a reasonable extent, colocation (i.e. keeping assets such as states and styling) closer to where they're used (known as localization).

In React's ain words, styled components are "visual primitives for components", and their goal is to give united states of america a flexible way to style components. The outcome is a tight coupling betwixt components and their styles.

Note: Styled components are bachelor both for React and React Native, and while you should definitely check out the React Native guide, our focus here will be on styled components for React.

More than after jump! Continue reading below ↓

Why Styled Components?

Autonomously from helping y'all to scope styles, styled components include the post-obit features:

  • Automatic vendor prefixing
    Yous tin use standard CSS properties, and styled components volition add together vendor prefixes should they be needed.
  • Unique grade names
    Styled components are independent of each other, and you do not accept to worry nigh their names because the library handles that for yous.
  • Emptying of dead styles
    Styled components remove unused styles, even if they're declared in your lawmaking.
  • and many more than.

Installation

Installing styled components is easy. You can practise it through a CDN or with a parcel manager such as Yarn…

          yarn add styled-components        

… or npm:

          npm i styled-components        

Our demo uses create-react-app.

Starting Out

Mayhap the first affair you'll notice about styled components is their syntax, which tin can be daunting if you don't understand the magic behind styled components. To put it briefly, styled components utilise JavaScript'due south template literals to bridge the gap between components and styles. And then, when you create a styled component, what you're actually creating is a React component with styles. Information technology looks like this:

          import styled from "styled-components";  // Styled component named StyledButton const StyledButton = styled.button`   background-color: black;   font-size: 32px;   color: white; `;  function Component() {   // Use it like any other component.   render <StyledButton> Login </StyledButton>; }        

Here, StyledButton is the styled component, and information technology will be rendered as an HTML button with the independent styles. styled is an internal utility method that transforms the styling from JavaScript into actual CSS.

In raw HTML and CSS, we would have this:

          push button {   background-color: black;   font-size: 32px;   color: white; }  <button> Login </button>        

If styled components are React components, can we use props? Yes, we can.

Adapting Based on Props

Styled components are functional, and then nosotros can easily style elements dynamically. Let's presume nosotros take ii types of buttons on our page, one with a black groundwork, and the other bluish. Nosotros do not have to create two styled components for them; we can arrange their styling based on their props.

            import styled from "styled-components";  const StyledButton = styled.button`   min-width: 200px;   edge: none;   font-size: 18px;   padding: 7px 10px;   /* The resulting groundwork color will be based on the bg props. */   background-colour: ${props => props.bg === "black" ? "black" : "blueish"; `;  part Contour() {   return (     <div>       <StyledButton bg="black">Button A</StyledButton>       <StyledButton bg="blue">Button B</StyledButton>     </div>   ) }          

Because StyledButton is a React component that accepts props, we can assign a unlike background color based on the existence or value of the bg prop.

You'll discover, though, that we oasis't given our button a type. Let'south do that:

            function Contour() {   return (     <>       <StyledButton bg="black" type="button">         Button A       </StyledButton>       <StyledButton bg="blue" blazon="submit" onClick={() => alarm("clicked")}>         Button B       </StyledButton>     </>   ); }          

Styled components tin can differentiate between the types of props they receive. They know that blazon is an HTML aspect, so they actually return <button type="button">Push A</push button>, while using the bg prop in their ain processing. Detect how nosotros attached an event handler, too?

Speaking of attributes, an extended syntax lets usa manage props using the attrs constructor. Check this out:

          const StyledContainer = styled.section.attrs((props) => ({   width: props.width || "100%",   hasPadding: props.hasPadding || false, }))`   --container-padding: 20px;   width: ${(props) => props.width}; // Falls back to 100%   padding: ${(props) =>     (props.hasPadding && "var(--container-padding)") || "none"}; `;        

Notice how nosotros don't need a ternary when setting the width? That'southward because we've already gear up a default for it with width: props.width || "100%",. Also, nosotros used CSS custom backdrop considering we tin!

Note: If styled components are React components, and nosotros can pass props, so can we likewise use states? The library'southward GitHub account has an issue addressing this very matter.

Extending Styles

Let's say you're working on a landing page, and you've set your container to a certain max-width to keep things centered. Yous accept a StyledContainer for that:

          const StyledContainer = styled.department`   max-width: 1024px;   padding: 0 20px;   margin: 0 auto; `;        

So, you discover that you need a smaller container, with padding of 10 pixels on both sides, instead of 20 pixels. Your first thought might be to create another styled component, and yous'd exist right, but it wouldn't take any time before you realize that yous are duplicating styles.

          const StyledContainer = styled.section`   max-width: 1024px;   padding: 0 20px;   margin: 0 auto; `;  const StyledSmallContainer = styled.section`   max-width: 1024px;   padding: 0 10px;   margin: 0 auto; `;        

Before you lot get ahead and create StyledSmallContainer, like in the snippet to a higher place, permit's acquire the way to reuse and inherit styles. Information technology's more than or less like how the spread operator works:

          const StyledContainer = styled.section`   max-width: 1024px;   padding: 0 20px;   margin: 0 auto; `;  // Inherit StyledContainer in StyledSmallConatiner const StyledSmallContainer = styled(StyledContainer)`   padding: 0 10px; `;  part Dwelling() {   return (     <StyledContainer>       <h1>The surreptitious is to be happy</h1>     </StyledContainer>   ); }  role Contact() {   render (     <StyledSmallContainer>       <h1>The road goes on and on</h1>     </StyledSmallContainer>   ); }        

In your StyledSmallContainer, you'll get all of the styles from StyledContainer, but the padding volition be overridden. Keep in mind that, unremarkably, you'll get a section chemical element rendered for StyledSmallContainer, because that's what StyledContainer renders. But that doesn't mean it's carved in rock or unchangeable.

The "every bit" Polymorphic Prop

With the as polymorphic prop, you lot can bandy the terminate chemical element that gets rendered. 1 apply example is when you lot inherit styles (every bit in the last instance). If, for example, you'd prefer a div to a section for StyledSmallContainer, you lot can pass the as prop to your styled component with the value of your preferred element, similar then:

          function Home() {   render (     <StyledContainer>       <h1>It'southward concern, non personal</h1>     </StyledContainer>   ); }  part Contact() {   return (     <StyledSmallContainer as="div">       <h1>Never dribble when you lot tin can pass</h1>     </StyledSmallContainer>   ); }        

Now, StyledSmallContainer volition be rendered as a div. You could even have a custom component as your value:

          function Abode() {   return (     <StyledContainer>       <h1>It's business organisation, non personal</h1>     </StyledContainer>   ); }  function Contact() {   return (     <StyledSmallContainer as={StyledContainer}>       <h1>Never dribble when you can pass</h1>     </StyledSmallContainer>   ); }        

Don't accept information technology for granted.

SCSS-Like Syntax

The CSS preprocessor Stylis enables styled components to support SCSS-like syntax, such as nesting:

          const StyledProfileCard = styled.div`   border: 1px solid black;    > .username {     font-size: 20px;     color: blackness;     transition: 0.2s;      &:hover {       color: red;     }      + .dob {       color: grey;     }   } `;  function ProfileCard() {   render (     <StyledProfileCard>       <h1 className="username">John Doe</h1>       <p className="dob">         Date: <span>12th October, 2013</span>       </p>       <p className="gender">Male</p>     </StyledProfileCard>   ); }        

Blitheness

Styled components have a keyframes helper that assists with constructing (reusable) animation keyframes. The advantage here is that the keyframes will be detached from the styled components and can be exported and reused wherever needed.

          import styled, {keyframes} from "styled-components";  const slideIn = keyframes`   from {     opacity: 0;   }    to {     opacity: one;   } `;  const Toast = styled.div`   animation: ${slideIn} 0.5s cubic-bezier(0.4, 0, 0.two, 1) both;   border-radius: 5px;   padding: 20px;   position: fixed; `;        

Global Styling

While the original goal of CSS-in-JS and, by extension, styled components is scoping of styles, nosotros can likewise leverage styled components' global styling. Because nosotros're more often than not working with scoped styles, yous might remember that's an invariable factory setting, but you lot'd be wrong. Think about it: What actually is scoping? It's technically possible for us — in the proper noun of global styling — to exercise something similar to this:

          ReactDOM.return(   <StyledApp>     <App />   </StyledApp>,   document.getElementById("root") );        

Only we already have a helper function — createGlobalStyle — whose sole reason for existence is global styling. Then, why deny it its responsibility?

One thing we tin can use createGlobalStyle for is to normalize the CSS:

          import {createGlobalStyle} from "styled-components";  const GlobalStyle = createGlobalStyle`     /* Your css reset here */ `;  // Use your GlobalStyle function App() {   return (     <div>       <GlobalStyle />       <Routes />     </div>   ); }        

Note: Styles created with createGlobalStyle do not accept whatever children. Learn more in the documentation.

At this point, you might be wondering why we should bother using createGlobalStlye at all. Here are a few reasons:

  • Nosotros can't target anything outside of the root render without it (for example, html, torso, etc.).
  • createGlobalStyle injects styles but does not render any bodily elements. If you await at the last instance closely, you'll notice we didn't specify any HTML chemical element to render. This is cool because we might not actually need the element. After all, we're concerned with global styles. We are targeting selectors at large, not specific elements.
  • createGlobalStyle is not scoped and can be rendered anywhere in our app and volition be applicable as long as it'southward in the DOM. Recall about the concept, non the construction.
          import {createGlobalStyle} from "styled-components";  const GlobalStyle = createGlobalStyle`   /* Your css reset hither */    .app-title {     font-size: 40px;   } `;  const StyledNav = styled.nav`     /* Your styles hither */ `;  office Nav({children}) {   render (     <StyledNav>       <GlobalStyle />       {children}     </StyledNav>   ); }  office App() {   return (     <div>       <Nav>         <h1 className="app-championship">STYLED COMPONENTS</h1>       </Nav>       <Main />       <Footer />     </div>   ); }        

If yous think almost the construction, then app-championship should not be styled equally set in GlobalStyle. But it doesn't work that way. Wherever you lot choose to render your GlobalStyle, it will be injected when your component is rendered.

Be careful: createGlobalStyles will only be rendered if and when it's in the DOM.

CSS Helper

Already we've seen how to accommodate styles based on props. What if we wanted to go a little further? The CSS helper function helps to achieve this. Permit's presume we take two text-input fields with states: empty and active, each with a different color. Nosotros can do this:

          const StyledTextField = styled.input`   color: ${(props) => (props.isEmpty ? "none" : "black")}; `;        

All's well. Subsequently, if we need to add together another country of filled, we'd have to alter our styles:

          const StyledTextField = styled.input`   color: ${(props) =>     props.isEmpty ? "none" : props.active ? "purple" : "blue"}; `;        

Now the ternary performance is growing in complexity. What if nosotros add another land to our text-input fields later on? Or what if we desire to give each state additional styles, other than color? Can you imagine cramping the styles into the ternary performance? The css helper comes in handy.

          const StyledTextField = styled.input`   width: 100%;   height: 40px;    ${(props) =>     (props.empty &&       css`         colour: none;         backgroundcolor: white;       `) ||     (props.active &&       css`         color: black;         backgroundcolor: whitesmoke;       `)} `;        

What we've washed is sort of expanded our ternary syntax to accommodate more styles, and with a more understandable and organized syntax. If the previous statement seems wrong, it's because the lawmaking is trying to do also much. Then, permit's step dorsum and refine:

          const StyledTextField = styled.input` width: 100%; top: 40px;  // 1. Empty state ${(props) =>   props.empty &&   css`     color: none;     backgroundcolor: white;   `}  // 2. Active land ${(props) =>   props.agile &&   css`     color: black;     backgroundcolor: whitesmoke;   `}  // 3. Filled country ${(props) =>   props.filled &&   css`     color: blackness;     backgroundcolor: white;     border: 1px solid green;   `} `;        

Our refinement splits the styling into three different manageable and easy-to-empathise chunks. It'south a win.

StyleSheetManager

Similar the CSS helper, StyleSheetManager is a helper method for modifying how styles are processed. Information technology takes sure props — like disableVendorPrefixes (you lot tin check out the total list) — that assistance you opt out of vendor prefixes from its subtree.

          import styled, {StyleSheetManager} from "styled-components";  const StyledCard = styled.div`   width: 200px;   backgroundcolor: white; `;  const StyledNav = styled.div`   width: calc(100% - var(--side-nav-width)); `;  function Contour() {   return (     <div>       <StyledNav />       <StyleSheetManager disableVendorPrefixes>         <StyledCard> This is a card </StyledCard>       </StyleSheetManager>     </div>   ); }        

disableVendorPrefixes is passed every bit a prop to <StyleSheetManager>. And so, the styled components wrapped past <StyleSheetManager> would be disabled, but non the ones in <StyledNav>.

Easier Debugging

When introducing styled components to ane of my colleagues, one of their complaints was that it'southward hard to locate a rendered element in the DOM — or in React Developer Tools, for that matter. This is one of the drawbacks of styled components: In trying to provide unique class names, it assigns unique hashes to elements, which happen to be cryptic, but it makes the displayName readable for easier debugging.

          import React from "react"; import styled from "styled-components"; import "./App.css";  const LoginButton = styled.push`   background-color: white;   colour: black;   border: 1px solid red; `;  function App() {   render (     <div className="App">       <LoginButton>Login</LoginButton>     </div>   ); }        

By default, styled components render LoginButton equally <push class="LoginButton-xxxx xxxx">Login</push button> in the DOM, and every bit LoginButton in React Programmer Tools, which makes debugging easier. We can toggle the displayName boolean if we don't want this behavior. This requires a Babel configuration.

Note: In the documentation, the package boom-boom-plugin-styled-components is specified, as well as a .babelrc configuration file. The issue with this is that, considering nosotros're using create-react-app, we can't configure a lot of things unless we eject. This is where Babel macros come in.

Nosotros'll need to install boom-boom-plugin-macros with npm or Yarn, then create a boom-boom-plugin-macros.config.js at the root of our awarding, with the content:

          module.exports = {   styledComponents: {     displayName: true,     fileName: false,   }, };        

With the fileName value inverted, the displayName will be prefixed with the file name for even more than unique precision.

Nosotros besides now need to import from the macro:

          // Before import styled from "styled-components";  // After import styled from "styled-components/macro";        

Conclusion

Now that you tin can programmatically compose your CSS, do not abuse the freedom. For what information technology's worth, do your very best to maintain sanity in your styled components. Don't try to compose heavy conditionals, nor suppose that every affair should be a styled component. Also, practise not over-abstruse by creating nascent styled components for use cases that y'all are only guessing are somewhere effectually the corner.

Farther Resources

  1. Documentation, Styled Components
  2. "Building a Reusable Component System with React.js and styled-components", Lukas Gisder-Dubé
  3. Usage with Next.js
  4. Usage with Gatsby

Smashing Editorial (ks, ra, yk, al, il)

0 Response to "Only Styled-component Classes Can Be Targeted in This Fashion"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel