跳至主要内容

Using styled-components to build a corporate landing page

· 閱讀時間約 5 分鐘
阿昇
Software Engineer

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.

Ref​