React
Styled Components
#react
npm install styled-components
import { styled } from "styled-components";
const ControlContainer = styled.div`
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1.5rem;
`;
export default function AuthInputs() {
return (
<ControlContainer>
// content
</ControlContainer>
)
}Use this to replace div and it’s styles inside index.css to a single styled component.div element.
- They also use children prop, to wrap them around content
- They also forward all passed props to underlying JSX
Dynamic and Conditional Styling
<ControlLabel className={`label $${emailNotValid ? "invalid" : ""}`}>
// css
label.invalid {
color: <span style={{ color: 'rgb(116,62,228)' }}>#f87171</span>;
}Above styling can be done using Styled Components. So we’ll use that.
const ControlLabel = styled.label`
// ...
// color:$$ {(props) => (props.invalid ? "#f87171" : "#6b7280")};
color: $${({ invalid }) => (invalid ? "#f87171" : "#6b7280")};
// 1. Pass invalid
export default function AuthInputs() {
return <ControlLabel invalid={emailNotValid}>Email</ControlLabel>
}- Use template literals, where you can pass conditions inside a function, which takes props as input. Might destructure
- You don’t want to collide with in-built props. that’s why common convention to use$$ invalid.
Nested Rules, Media Queries and Pseudo Selectors
To apply styling to elements in inside a styled component. Simple place all css inside double backticks. And change all instances of component’s element to & .
- No need to create separate styled components for every element
const StyledHeader = styled.header`
display: flex;
margin-bottom: 2rem;
// applies to img inside header
& img {
object-fit: contain;
}
p {
text-align: center;
}
// apply pseudo selectors using this.
// Applies hover to children if whitespace in b/w
&:hover {
background-color: <span style={{ color: 'rgb(116,62,228)' }}>#f0920e</span>;
}
@media (min-width: 768px) {
margin-bottom: 4rem; // applies to header
& h1 {
font-size: 2.25rem;
}
}
`;-
Modularize components that might be used multiple times
-
Export a single component which multiple commonly used styled components together. Like label and input. And export them as a function
-
Eg: this→ authInputs.jsx
import { styled } from "styled-components";
const ControlLabel = styled.label`
display: block;
color: $${({$$ invalid }) => ( $$invalid ? "#f87171" : "#6b7280")};
`;
const ControlInput = styled.input`
width: 100%;
border-color:$$ {({ $$invalid }) => ($$ invalid ? "#f73f3f" : undefined)};
`;
export default function AuthInput() {
// ...
return (
<p>
<ControlLabel $$invalid={emailNoValid}>Email</ControlLabel>
<ControlInput
type="email"$$ invalid={emailNoValid}
onChange={(event) =>
handleInputChange("email", event.target.value)
}
/>
</p>
<p>
<ControlLabel $$invalid={passwordNotValid}>Password</ControlLabel>
<ControlInput
type="password"$$ invalid={passwordNotValid}
onChange={(event) =>
handleInputChange("password", event.target.value)
}
/>
</p>
);
}- Can be converted into ⇒
- CustomInput.jsx
import { styled } from "styled-components";
const ControlLabel = styled.label`
display: block;
color: $${({$$ invalid }) => ( $$invalid ? "#f87171" : "#6b7280")};
`;
const ControlInput = styled.input`
width: 100%;
border-color:$$ {({ $$invalid }) => ($$ invalid ? "#f73f3f" : undefined)};
`;
const CustomInput = ({ label, invalid, ...props }) => {
return (
<p>
<ControlLabel $$invalid={invalid}> {label} </ControlLabel>
<ControlInput$$ invalid={invalid} {...props} />
</p>
);
};
export default CustomInput;- authInputs.jsx
import CustomInput from "./CustomInput.jsx";
export default function AuthInputs() {
// ...
return (
<CustomInput
label="Email"
invalid={emailNotValid}
type="email"
onChange={(event) => handleInputChange("email", event.target.value)}
/>
<CustomInput
label="Password"
invalid={passwordNotValid}
type="password"
onChange={(event) => handleInputChange("password", event.target.value)
}
/>
);
}- Now we have a nice reusable Label-Input component with variable Label Name, invalid state and Custom props on input. Which imports two styled components, concisely.
Summary:
- Think and code CSS like react
- Scoped to a component
- But can be annoying to have CSS in same file and modularize every like component