I modified this underline animation when scrolling down on Codepen in Javascript and it works. You can see it here in the Codepen It works with Intersection Observer and for the underline it uses a generated svg.
Explanation how it works:
This effect is made by positioning an SVG relative the to the text one want to emphasize and animating it in and out.
The words are wrapped to be underlined in a span element in order to allow to target the words directly.
In order to access the path element using CSS the SVG code is directly in the HTML. Add it inside of the span element you wrapped the text you want to underline in.
The SVG element has a class name so it can target it using CSS -> class="squiggle".
The squiggle position as well as the width and height are set inline directly on the SVG, to get the line to appear exactly where I want it.
Now the underline shows up in the right place. The animation happens with the stroke of an SVG path by using a combination of the stroke-dasharray and stroke-dashoffset properties.
For the beginning styles, the stroke-dasharray and stroke-dashoffset should be large enough that the stroke is not visible.
.squiggle path {
stroke-dasharray: 1600;
stroke-dashoffset: 1600;
}
When the container element is in view, we can set the animation name, duration, iteration-count, and fill-mode:
.text-effect.in-view .squiggle path {
animation-name: underline;
animation-duration: 1s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
To display the animation in reverse when the element is scrolled out of view the @keyframes underline-out does the opposite animation.
My attempt to rebuild it in React Typescript:
Now first I try only to achieve the animation React Typescript as styled component and then I try to add the Intersection Observer from the Codepen in a next step. But still I have problems with the animation. I declared my styles to use inline but I still having some difficulties to achieve the same result as it does not work.
My App.tsx
import Typography from '@mui/material/Typography';
import { Box, keyframes, styled } from '@mui/material';
import React from 'react';
const Underline = keyframes`
{
"from": {
strokeDashoffset: "1600",
},
"to": {
strokeDashoffset: "200",
}
}
`;
const styles = {
textDecoration: {
textDecoration: 'none',
cursor: 'pointer',
color: 'inherit',
},
textEffect: {
strokeDasharray: '1600',
strokeDashoffset: '200',
animationName: 'none',
},
squiggle: {
position: 'absolute',
top: '90%',
left: '-9px',
},
'squiggle path': {
stroke: '#FB9F18',
strokeWidth: '14px',
strokeLinecap: 'round',
strokeDasharray: '1600',
strokeDashoffset: '1600',
animationName: 'underline-out',
animationDuration: '1s',
animationIterationCount: '1',
},
'textEffect.in-view .squiggle path': {
animationName: 'underline',
animationDuration: '1s',
animationIterationCount: '1',
animationFillMode: 'forwards',
},
'@keyframes underline': {
from: {
strokeDashoffset: '1600',
},
to: {
strokeDashoffset: '200',
},
},
'@keyframes underline-out': {
from: {
strokeDashoffset: '200',
},
to: {
strokeDashoffset: '1600',
},
},
};
function UnderlineEffect() {
return (
<Box style={styles.textEffect}>
<Typography>
Double your efficiency,{' '}
<span class="underline">
<a style={styles.textDecoration} href="www.somewebsite.com">
guaranteed.
</a>
<svg
width="215px"
height="25px"
style={styles.squiggle}
viewBox="0 0 466 29"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:space="preserve"
xmlns:serif="http://www.serif.com/"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-4055,-7503)">
<g transform="matrix(1,0,0,1,2942.74,0)">
<g
id="squiggle-underline"
transform="matrix(0.59639,0.0106812,-0.0121867,0.680453,651.002,2140.64)">
<path
d="M976.992,7882.9C1019.57,7882.9 1065.7,7874.34 1108.59,7871.65C1246.32,7863.04 1383.5,7857.74 1521.52,7857.74C1541.4,7857.74 1709,7857.97 1714.47,7868.91C1715.77,7871.51 1710.77,7870.69 1710.29,7870.73C1695.62,7871.88 1681.88,7871.57 1667.06,7871.96C1646.09,7872.51 1625.12,7872.92 1604.15,7873.36C1564.57,7874.19 1525.13,7876.05 1485.69,7879.23C1411.5,7885.22 1337.41,7889.35 1263.06,7892.45C1196.87,7895.22 1130.52,7894 1064.4,7897.12C1021.44,7899.14 978.37,7907.57 935.437,7907.57"
style="fill:none;"
/>
</g>
</g>
</g>
</svg>
</span>
</Typography>
</Box>
);
}
export { UnderlineEffect };