When I noticed this UI button interaction, I was like
- set up a react project
npx create-react-app
- Add framer-motion
npm install framer-motion
Now everything is ready.
This is how we're going to achieve this effect...!
HTML STRUCTURE
Create the main component, and add the button wrapper and button elements.
Now add the main component and styles to our App component.
Add some default styles to our Project
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap');
:root {
--bg: hsla(330, 6%, 12%, 1);
--button: hsla(160, 27%, 98%, 1);
--buttonText: hsla(330, 8%, 20%, 1);
--notSelected: hsla(330, 6%, 46%, 1);
}
html {
scroll-behavior: smooth;
text-rendering: optimizeSpeed;
min-width: 100%;
overflow-x: hidden;
font-size: 100%;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
*::after,
*::before {
box-sizing: border-box;
}
img {
max-width: 100%;
display: block;
overflow: hidden;
}
a {
text-decoration: none;
}
svg {
width: 24px;
height: 24px;
pointer-events: none;
}
body {
background-color: var(--bg);
font-family: 'Inter',
sans-serif;
font-weight: 400;
line-height: 1.75;
position: relative;
transition: background 0.4s ease-in-out;
}
Fun part
Create a Separate component for our animation(span element)
Now import motion from framer motion add it to our span element and add a layoutId button(will explain about this later).
Setting up a state using useState hook
Now add motion to our both buttons and wrap both buttons by Animateshared layout from framer motion.
Based on the state, we're going to add a class to our button element active and non-active class.
Based on the state, we're going to render the Anicomp.
Now add the Onclick event to both buttons and set the button state regarding each button.
Button styles
button {
appearance: none;
border: none;
background-color: unset;
font-size: 1rem;
letter-spacing: 4px;
padding: 1.125em 1.5em;
position: relative;
border-radius: 50px;
cursor: pointer;
}
// active and non active classes
.active {
color: var(--buttonText);
}
.notActive {
color: var(--notSelected);
}
//span element styles
.button--bg {
position: absolute;
left: 0;
right: 0;
top: 0;
right: 0;
background: var(--button);
display: block;
width: 100%;
height: 100%;
z-index: -1;
border-radius: 50px;
}
Final Output
AnimateShared Layout
Animateshared layout changes across, and between, multiple components. with help of the same layout id, framer motion shares the transition across the components.
More about AnimateShared layout and Layout animations using framer motion.
Top comments (0)