Why Rebuild This In React
?
In the previous guide: Marquee · Simple, we built our marquee
using plain old HTML
and CSS
. This solution is simple and minimal, making it an excellent choice for most use-cases. In general, we want to keep things as stupid and simple as possible. The more libaries we involve, typically the more error-prone and computationally expensive the solution gets. But sometimes stakeholders have different requirements or maybe you want to make it feel more alive. For example, we may require the user to be able to hover and control the speed of the marquee
. CSS
doesn’t offer a good way to do this. This is where we benefit from converting our previous solution to using React
and Framer
which we’ll be doing in this guide. If you’re unfamiliar with Framer
, I’ll give a brief overview on it later as well.
Setting Up Our HTML
and CSS
For this we’ll be using Styled Components. Styled Components
make for very convenient styling in React. If you’re interested in a separate guide on this, please let me know!
Using our previous guide: Marquee · Simple as inspiration, we’ll replicate the HTML
and base CSS
in React
with Styled Components
. We’ll create a new file called Marquee.jsx
containing this:
import { styled } from "styled-components";
export const Marquee = ({ text }) => {
// Duplicate the text here to have enough content to fill the screen
const tickerText = `${text} ${text} ${text} ${text} ${text} ${text} `;
return (
<Container>
<Track>
{tickerText}
</Track>
</Container>
);
};
const Container = styled.div`
background: black;
overflow: hidden;
`;
const Track = styled.div`
font-size: 100px;
color: white;
width: max-content;
white-space: pre;
`;
Setting Up Framer
The main concept of Framer
is we define variants
which are our different style states of our component. So in our previous CSS
example, we have the beginning state and the animating state (that is infinitely looping). We can recreate these variants in Framer
and define them in a variants
object. Then we use a motion.div
(provided by Framer
), and pass it these variants
as well as the active variant. Read through it and I’ll add comment along the way.
export const Marquee = ({ text }) => {
// This is our identifier for our only animating state.
const animationName = "marquee"
const tickerText = `${text} ${text} ${text} ${text} ${text} ${text} `;
const variants = {
// The key here is our identifier for the animation state.
[animationName]: {
// We will be animating x to -50%.
x: "-50%",
// Now we can define the animation details here.
transition: {
x: {
repeat: Infinity,
repeatType: "loop",
ease: "linear",
duration: 30,
},
},
},
};
return (
<Container>
// We convert our normal element into a `motion.div`. We add the variants we defined above.
// And we use `whileInView` to apply our animation state while this element is in view.
<Track as={motion.div} variants={variants} whileInView={animationName}>
{tickerText}
</Track>
</Container>
);
};
Additional Features: Reverse And Vertical
In the previous guide: Marquee · Simple, there were extra challenges to allow for reversing the direction and allowing for vertical text. I’ll go through these solutions now for you.
Reversing The Direction
For reversing, we just have to adjust the initial x
and the animated x
value. reverse
can be passed in as a prop to our Marquee.jsx
component.
// Pass in a new variable `reverse`.
export const Marquee = ({ text, reverse }) => {
const tickerText = `${text} ${text} ${text} ${text} ${text} ${text} `;
const variants = {
animated: {
// Adjust the animated value based on `reverse`.
x: reverse ? "-50%" : 0,
transition: {
x: {
repeat: Infinity,
repeatType: "loop",
ease: "linear",
duration: 30,
// Adjust the initial value based on `reverse`.
...(!reverse && { from: "-50%" }),
},
},
},
};
...
Animating The Text Vertically
For animating the text vertically, we can add an extra prop to our Marquee.jsx
component called vertical
. Using that we can control the animation axis (switching to Y from X). You then also need to pass our vertical
prop into our Track Styled Component
. From there, it can be used as a variable to conditonally apply new CSS
.
export const Marquee = ({ text, reverse, vertical }) => {
const tickerText = `${text} ${text} ${text} ${text} ${text} ${text} `;
// Switch to animating the Y axis.
const transformAxis = vertical ? "y" : "x";
const variants = {
animated: {
// Dynamically use the correct axis.
[transformAxis]: reverse ? "-50%" : 0,
transition: {
// Dynamically use the correct axis.
[transformAxis]: {
repeat: Infinity,
repeatType: "loop",
ease: "linear",
duration: 30,
...(!reverse && { from: "-50%" }),
},
},
},
};
return (
<Container>
<Track
as={motion.div}
variants={variants}
whileInView="animated"
// Pass our new prop into the `Styled Component`.
{...{ vertical }}
>
{tickerText}
</Track>
</Container>
);
};
const Container = styled.div`
background: black;
overflow: hidden;
`;
const Track = styled.div`
font-size: 100px;
color: white;
width: max-content;
white-space: pre;
// Using this syntax, you gain access to the passed in variable.
// We have awesome built in CSS support for converting text to vertical.
${({ vertical }) => {
if (vertical) {
return css`
writing-mode: vertical-lr;
`;
}
}}
`;
Next Up: Adding Custom Interaction
Congrats on finishing this tutorial! We’ve built marquee
in simple HTML
and CSS
in the previous guide: Marquee · Simple. And now we’ve set it up in React
with additional features to support reverse and vertical directions.
In the next guide we’ll focus on adding interaction to the marquee
. There’s no extra challenges for this tutorial, but take some time to read about the few new libraries I introduced. They’re very commonly used in the web dev world, and I’ll be using them frequently.
- React: The industry leading JS libary used to create reusable components.
- Styled Components: Used to easily create styled
HTML
elements withinReact
. - Framer: Used to easily manage complex style animations within
React
.
As always, feel free to look at the demo page to see what you should expect from this guide.