What's inside
There is a popular library called styled-components
it is also one of the ways to write styles in modern SPA applications in React. One of the biggest pros is that you can write actual JS logic inside them, so your styles can be changed based on the props you pass down to them.
This allows you to write less duplicated code. Another big thing is that styled-components have an isolated scope, meaning the style you wrote for your components won’t affect other components unless you want to.
It also means you can re-use the components without worrying that it would break styles across your whole application. The library supports code-splitting, automatic vendor prefixing, and simple dynamic styling.
That’s why this library is also quite popular with React-Native projects.
styled-components
are also quite an easy way to customize your available components in the most popular UI frameworks that React developers use, such as Material-UI (MUI) and others.
Setup
Inside your project directory - run the following command:
# with npm
npm install --save styled-components
# with yarn
yarn add styled-components
How to start
In the first step make an import:
import styled from 'styled-components';
Optionally, you can assign types or interfaces:
type PhotoWrapperProps = {
readonly picture: string;
readonly position: string;
readonly bckheight: string;
readonly children?: JSX.Element;
};
In the next step write your component structure.
PhotoWrapper
is our styled wrapper which is receiving props - so they can be used to introduce some parameterization or ”easy customization” of components, meaning you can change single CSS properties based on actual React props passed to the component.
export const HeaderWithPhoto = ({
picture,
bckheight,
position,
children,
}: PhotoWrapperProps) => {
return (
<PhotoWrapper
picture={picture}
position={position}
bckheight={bckheight}
>
{children}
</PhotoWrapper>
);
};
Rules
- If you want to style html element - use dotted notation as shown in example:
const MyWrapper = styled.div`
background: red;
`;
- If you want to style some existing component - add and import at the top and use brackets:
const ButtonWrapper = styled(Button)`
background: red;
`;
//and then use ButtonWrapper instead of Button inside your components, it will work just the same, but will also have additional styles
- You can also pass types or interfaces using square brackets []:
// import styled, { StyleSheetManager } from 'styled-components'
// import stylisRTLPlugin from 'stylis-plugin-rtl';
const Box = styled.div`
background: mediumseagreen;
border-left: 10px solid red;
`;
render(
<StyleSheetManager stylisPlugins={[stylisRTLPlugin]}>
<Box>My border is now on the right!</Box>
</StyleSheetManager>
);
- You can also pass props:
We are using string interpolation syntax since the styled component is wrapped with backticks.
There are two ways of assigning props inside styled-components
:
- using props object:
`background: ${props => props.backgroundPicture };`
- using destructuring:
`background: ${({ backgroundPicture }) => backgroundPicture };`
const PhotoBackgroundWrapper = styled.div<HeaderWithPhotoBackgroundProps>`
background: rgba(0, 0, 0, 0.5);
background: ${({ picture }) =>
`linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('${picture}') no-repeat
`};
min-height: ${props => props.bckheight};
background-position: ${props => props.position};
`;
Using
- If-else logic inside
styled-components
:
Using if-else logic inside styled-components
helps to reduce boilerplate code and duplication.
Before styled-components
you had to change the className attribute based on some property value:
<>
{someBooleanValue
? <div className="style-1`">content</div>
: <div className="style-2">content</div>
}
</>
or if you had more props then probably something like this - and create a lot of css classes and nested if statements:
{someBooleanValue
? <div className=`style-1 red-border ${classNameDependsOnCondtion}`>content</div>
: <div className="style-2 blue-border">content</div>
}
Also you got a lot of boilerplate - divs/spans with classes.
It obscures code readability if you had a lot of these conditions.
In the styled component case you wrap the component you want to style and give it a name like StyledSidebar
and can use it instead of a component from some UI library.
Another thing is, that with class based components, css code is not encapsulated, so nested components can affect other components styles. With styled components - it generates unique class names for your styles/components.
That’s why the styled-components
library is quite popular with React-Native
developers.
- Ternary operator:
const Box = styled.div`
height: ${props => props.size === 'small' ? '20px' : '40px'}
width: ${props => props.size === 'small' ? '20px' : '40px'}
`;
- Logical operators:
const Box = styled.div`
// last value after || operator is default option
height: ${({size}) =>
size === 'small' && '25px' ||
size === 'large' && '100px' ||
'50px'
};
width: ${({size}) => size === 'small' && '25px' ||
size === 'large' && '100px' ||
'50px'
}';
// Render.
<Box/>// 50px - Normal.
<Box size="small"/>// 25px - Small.
<Box size="large"/>// 100px - Large.
or using css helper method from styled-components
const Box = styled.div`
height:100px;
width:100px;
${props => props.size === 'small' && css`
height:20px;
width:20px;
`}
`;
But what if you want to change the behavior of one component based on the style of the other component?
This one is pretty tricky, but we can use the example that which is being referred to in styled-components documentation:
const Link = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Icon = styled.svg`
flex: none;
transition: fill 0.25s;
width: 48px;
height: 48px;
// you can use reference to other styled components this way
// as styled-components use string interpolation mechanism ⬇
${Link}:hover & {
fill: rebeccapurple;
}
`;
Summary
Styled-components
is a really powerful library, even in cases you decide to go with some UI framework. It can help you write and style your own controls in a really efficient way.
Also, there is a spinoff
library - called Emotion
which uses some parts of the styled-components
API.
Links to Check
More Resources
Contact Us
Partner with Sunscrapers for streamlined solutions tailored to your needs. Contact us today and let's bring your ideas to life!