Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Shiqi

Animate the element that is clicked when having same class name

Go to solution Solved by Cassie,

Recommended Posts

Hi, I want to use gsap to animate the two pseudo elements (::before and ::after) of my buttons. The each button element is inside a Group component in my react project. I want to play the animations on ::before and ::after alternately. Here is my code:

import React, { useState } from "react";
import { gsap } from "gsap";
import { CSSRulePlugin } from "gsap/CSSRulePlugin";

const animation = (qseudoElement) => {
  gsap.registerPlugin(CSSRulePlugin);

  const qseudo = CSSRulePlugin.getRule(qseudoElement);

  const tl = gsap.timeline();

  tl.fromTo(
    qseudo,
    {
      cssRule: {
        opacity: 0,
        scale: 0
      }
    },
    {
      cssRule: {
        opacity: 1,
        scale: 1
      },
      duration: 1
    }
  );

  tl.to(qseudo, {
    cssRule: {
      scale: 0,
      opacity: 0
    },
    duration: 1
  });
};

const Group = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);

    if (count % 2 === 0) {
      animation(".btn::before");
    } else {
      animation(".btn::after");
    }
  };

  return (
    <div>
      <button className="btn" onClick={() => handleClick()}>Click Me</button>
    </div>
  );
};

export default Group;

And I have multiple Group components in my App.

import Group from "./components/Group";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <Group /> 
      <Group /> 
      <Group /> 
    </div>
  );
}

 

The problem is that if I click on any button, the animations are fire on all buttons. I know this is because of they have the same css class. How can I select the button that is clicked and animate its pseudo elements? I want to achieve something like this:

const handleClick = (e) => {
	setCount(count + 1);
  
  	if(count % 2 === 0){
   		animation(e::before);
    } else {
    	animation(e::after);
    }
}

 

I appreciate your help and I made a demo here: codesandbox

 

 

 

Link to comment
Share on other sites

  • Solution

mmm. This is a tricky one 

I'd probably avoid pseudo elements if you can because browsers don't allow you to target them like normal elements. I tend to use spans instead!

If you wanna stick with pseudos it would probably be a better idea to use css vars I guess? Like so?

See the Pen 0f37cca39c40004bb1275835ea2e30d3?editors=0111 by cassie-codes (@cassie-codes) on CodePen

 

 

  • Like 3
Link to comment
Share on other sites

Thank you @Cassie. I think using span tag is a good idea. I have modifies my code and now it works as I needed.

 

codesandbox

 

 

  • Like 1
Link to comment
Share on other sites

Thank you @OSUblake . That's exactly what I want. The selector function is so cool!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×