Using styled-components to build a corporate landing page
2021-07-09 · 5 min read
I am a front-end engineer of OmniSegment, and our team are dedicated to improving marketing effectiveness of our customers.
Recently, I took the job of renewing our corp landing page. Although building a static web page is not complicated, there are something deserved to be recorded at this moment, and perhaps this post can help others in the future.
CSS Style
Our team mainly used inline style to manage CSS style in our products.
inline style
We used inline style in this way:
class Button extends PureComponent {
render() {
...
return (
<div className="button" style={Styles.button}>
...
</div>
);
}
}
const Styles = {
button: {
position: "absolute",
top: "50%",
right: "4rem",
transform: "translate(0, -50%)",
},
};
In the above example, style={Styles.headerButton}
is inline style, and we cannot addressing responsive web design (RWD), pseudo-elements and pseudo-classes...etc in this situation, hence we must find another solution to to deal with RWD.
styled-components
In order to solve the above issue, I introduced styled-components in our project.
According to official introduction, styled-components allows you to write actual CSS code to style your components, and here is a simple example:
const Container = styled.div`
display: flex;
flex-direction: column;
width: 100%;
margin-bottom: 1rem;
`;
Handle RWD with styled-components
How styled-components works is based on ES6 template literal
, and therefore we can address RWD through styled-components like this:
const breakpoints = {
xs: 0,
sm: 576,
md: 768,
lg: 1024,
xl: 1200,
};
function breakpointAt(size) {
return `@media screen and (min-width: ${breakpoints[size.toLowerCase()]}px)`;
}
const Container = styled.div`
...
${breakpointAt("md")} {
flex-direction: row-reverse;
padding: 0 1.5rem 0rem;
margin-bottom: 0;
}
${breakpointAt("lg")} {
padding: 0 1.5rem 3rem;
}
${breakpointAt("xl")} {
max-width: 1200px;
padding: 0 0 6rem;
}
`;
Element state
Moreover, styled-components allow developers to use the ampersand (&
) to refer back to the main component, so we can use &
to modify pseudo-classes like this:
const Button = styled.button`
background-color: transparent;
&:hover {
background: rgba(0, 0, 0, 0.5);
}
&:active {
background: rgb(0, 0, 0);
}
`;
Increase the specificity of rules
Since we use Semantic UI in our app, and therefore some styles might be overridden by semantic-ui style due to specificity.
For example, when we use Semantic UI's Image, the component's style will just like this:
.ui.image {
max-width: 100%;
...;
}
Obviously, .ui.image
has two classes, so if our styled-components only contains one class, the style will be overridden.
In order to override the style max-width
, we must increase the specificity.
We can use !important
in our style, but here is a simple and resilient solution to handle this problem, and the solution is using &
three times in styled-components:
const MainImage = styled(Image)`
&&& {
max-width: 200px;
margin: 0 auto 1rem;
}
`;
This solution will make the component's style like this:
.oFSmX.oFSmX.oFSmX {
max-width: 550px;
}
Animation
We want to decorate our landing page with some animations, and styled-components can help us to achieve this request.
This is the original image:
We want to add some moving dots on the image:
Define movement trajectory
According to CSS position, if we want to define the position of elements, the coordinate will be like this:
In order to define these position more easily, I name the blocks alphabetically:
Therefore, we can define how moving dots float between these positions.
For instance, I want a dot moving from A to B, so I should define the positions as below:
"A": left: 10.5%; top: 45.6%;
"B": left: 27%; top: 45.6%;
CSS keyframes
Prerequisite knowledge
Original CSS
If we want to create animation by original CSS, here is an example:
/* global.css */
div.dot {
height: 100px;
width: 100px;
animation-name: animation;
animation-duration: 8s;
animation-iteration-count: infinite;
}
@keyframes animation {
0% {
height: 100px;
width: 100px;
}
100% {
height: 100px;
width: 100px;
opacity: 0.6;
}
}
styled-components
As for styled-components, we can create animation in this way:
const animation = keyframes`
0% { height: 100px; width: 100px; }
100% { height: 100px; width: 100px; opacity: 0.6; }
`;
After knowing these prerequisite knowledge, lets back to our landing page case.
In our case, I define two functions to help us define how dots moving:
function pointCoordinate() {
return {
"A": `left: 10.5%; top: 45.6%;`,
"B": `left: 27%; top: 45.6%;`,
...
};
}
function movingAnimation(name) {
switch (name) {
case "a-b":
return keyframes`
from { ${pointCoordinate()["A"]} }
to { ${pointCoordinate()["B"]} }
`;
...
default:
return null;
}
}
Next, I define component like this;
const MovingSpot = styled.div`
...
animation-duration: ${(props) =>
props.animaDuration ? props.animaDuration : "12s"};
animation-name: ${(props) =>
props.animaName ? movingAnimation(props.animaName) : "none"};
animation-iteration-count: infinite;
`;
The result will looks like this: https://media.giphy.com/media/fK7uYVNkUaQtLZxKee/giphy.gif
Or you can just visit our official website.