Skip to main content
GSAP Animation TutorialArticle 02

GSAP Targeting Elements: Classes, IDs and Multiple Elements

Learn how to tell GSAP exactly which elements should move—from one class or unique ID to nested selectors and complete collections.

GSAP Targeting Elements - Classes IDs and Multiple Elements - NavTechSolution

In the first lesson, you loaded GSAP and created a tween. The next question is just as important: how does GSAP know which part of the page to animate? Before timelines or advanced effects, you need a reliable way to connect your HTML to your JavaScript.

A GSAP tween has two central ingredients: a target and an object containing the animation properties. In this example, ".box" is the target:

Target plus properties
gsap.to(".box", {
  x: 200,
  duration: 1
})
Lesson idea

HTML element → CSS selector → GSAP target → animation. Once that connection is clear, targeting becomes predictable.

1. What is a GSAP target?

A target is the element—or group of elements—that receives the animated values. A selector string such as .box follows the same CSS selector rules you already use in a stylesheet.

HTML target
<div class="box"></div>
GSAP tween
gsap.to(".box", {
  x: 200,
  duration: 1
})

GSAP resolves .box, finds the matching HTML element, and changes its horizontal transform until it reaches 200 pixels.

2. Target elements using classes

Classes are a natural default for animation because they describe reusable groups. One class can identify a single component today and several matching components later without changing the GSAP syntax.

Class target
<div class="box"></div>

<script>
gsap.to(".box", {
  x: 250,
  duration: 1.2,
  ease: "power2.out"
})
</script>
.box

The demo is ready.

3. Target elements using IDs

An ID represents one unique element. Prefix the ID value with # when you use it as a selector:

Unique heading target
<h1 id="hero-title">
  Build Better Web Experiences
</h1>

gsap.to("#hero-title", {
  y: -20,
  opacity: 1,
  duration: 1,
  ease: "power2.out"
})
.boxClass
#hero-titleID

A dot means class; a hash means ID. Use an ID only once in a document. For repeated components such as cards, classes are the safer choice.

4. Target HTML elements directly

Regular element names are valid CSS selectors, so GSAP can target them directly:

Element selectors
gsap.to("h2", {
  y: -10,
  duration: 0.8
})

gsap.to("button", {
  scale: 1.05,
  duration: 0.3
})

Broad selectors need care. button may match navigation controls, form actions, demo buttons, and accessibility controls. Prefer a component-specific class when only one part of the interface should move.

5. Target multiple elements

When a selector matches more than one element, GSAP collects all matches. The following tween affects all three cards at the same time:

Multiple matching cards
<div class="card">HTML</div>
<div class="card">CSS</div>
<div class="card">JavaScript</div>

gsap.to(".card", {
  y: -20,
  opacity: 1,
  duration: 0.8
})
HTML
CSS
JavaScript

Three cards match the same class selector.

No stagger yet

These cards animate together. Staggered timing is a separate technique covered later in the series.

6. Combine multiple selectors

A comma-separated selector list can bring different elements into one tween. In a hero section, a title, supporting line, and call-to-action might share the same entrance:

Combined hero targets
gsap.to(".title, .subtitle, .cta-button", {
  y: -15,
  opacity: 1,
  duration: 0.8
})

The comma means “match this selector or that selector.” Every match becomes part of the target collection.

7. Use descendant and nested selectors

A space between selectors describes a descendant relationship. This lets you limit an animation to cards inside one section instead of every card on the page.

Feature cards inside a section
<section class="features">
  <div class="feature-card"><h3>Fast</h3></div>
  <div class="feature-card"><h3>Responsive</h3></div>
</section>

gsap.to(".features .feature-card", {
  y: -20,
  opacity: 1,
  duration: 1
})

.features is the parent scope. .feature-card is the descendant target. The space joins those two conditions.

8. Select one element with querySelector()

GSAP does not require a selector string. You can resolve the element yourself and pass the resulting DOM element to GSAP:

First matching element
const box = document.querySelector(".box")

gsap.to(box, {
  x: 250,
  duration: 1
})

querySelector() returns the first matching element, or null when nothing matches. A stored reference is useful when several event handlers need the same element or when you want to check that a target exists before animating.

9. Select all matches with querySelectorAll()

All matching elements
const cards = document.querySelectorAll(".card")

gsap.to(cards, {
  y: -20,
  opacity: 1,
  duration: 0.8
})

querySelectorAll() returns a NodeList containing every match. GSAP accepts that collection directly.

querySelector()One card
querySelectorAll()CardCardCard

10. Normalize targets with gsap.utils.toArray()

GSAP array utility
const cards = gsap.utils.toArray(".card")

gsap.utils.toArray() turns a selector or element collection into a standard array. That makes it convenient for workflows where you later loop, filter, or organize targets. For now, remember it as a reliable bridge from “things that match” to “an array of elements.”

11. Keep selector scope intentional

A selector can be technically valid and still be a poor target. This example may hide layout wrappers, navigation, footer content, and the demo itself:

Too broad
gsap.to("div", {
  opacity: 0
})

A meaningful selector limits the effect to the intended component:

Specific component target
gsap.to(".pricing-card", {
  opacity: 1
})

12. Interactive targeting playground

Use the buttons to compare one DOM element with a NodeList containing all three. Both animations use identical values; only the target changes.

Box1
Box2
Box3

Choose one target or all matching targets.

Playground logic
const firstBox = document.querySelector(".target-box")
const boxes = document.querySelectorAll(".target-box")

gsap.to(firstBox, {
  y: -30,
  rotation: 10,
  duration: 0.6,
  ease: "power2.out"
})

gsap.to(boxes, {
  y: -30,
  rotation: 10,
  duration: 0.6,
  ease: "power2.out"
})

13. Common targeting mistakes

The selector name is wrong

If the HTML uses class="box", .boxes will not match it. Use .box.

The selector prefix is wrong

#box looks for an ID. Use .box when the markup contains a class.

The target does not exist yet

Wait for DOMContentLoaded when your script may execute before the article markup is available.

An ID is duplicated

An ID should be unique. Use a shared class when several elements need the same behavior.

The selector is too broad

A target such as div can reach unrelated layout, header, or footer elements.

Your code loads before GSAP

Load the GSAP CDN script before the custom file that calls gsap.to().

Wait for the document
document.addEventListener("DOMContentLoaded", () => {
  gsap.to(".box", {
    x: 200
  })
})

14. Performance-friendly properties

For common interface motion, begin with transform-based properties such as x, y, scale, and rotation, plus opacity. Transforms change how an element is presented without repeatedly changing the document's layout measurements.

That does not make every transform automatically fast. The number and size of animated elements, visual effects, device capability, and other page work still matter. Test the finished interaction on realistic devices.

15. Respect reduced-motion preferences

Targeting the correct element is only part of responsible animation. When a visitor requests reduced motion, skip non-essential travel or show the destination immediately:

Reduced motion check
const reduceMotion = window.matchMedia(
  "(prefers-reduced-motion: reduce)"
).matches

if (reduceMotion) {
  gsap.set(".box", { x: 200 })
} else {
  gsap.to(".box", { x: 200, duration: 1 })
}

Every interactive demo in this article applies its final state immediately when reduced motion is enabled.

16. Mini challenge: target a skills group

Start with this markup:

Challenge HTML
<section class="skills">
  <div class="skill-card">HTML</div>
  <div class="skill-card">CSS</div>
  <div class="skill-card">JavaScript</div>
</section>
  1. Target only the first card.
  2. Target every .skill-card.
  3. Target cards only when they are inside .skills.
  4. Animate opacity and y.
  5. Create a reset that restores the starting values.
Show one possible solution
Challenge solution
const firstSkill = document.querySelector(".skills .skill-card")
const allSkills = document.querySelectorAll(".skills .skill-card")

gsap.to(firstSkill, { y: -20, opacity: 1, duration: 0.6 })
gsap.to(allSkills, { y: -20, opacity: 1, duration: 0.6 })

// Reset
gsap.set(allSkills, { y: 0, opacity: 1 })

17. Targeting quick reference

SelectorMeaningExample
.classClass.card
#idUnique ID#hero
elementHTML elementh2
.parent .childNested descendant.features .card
querySelectorFirst matchdocument.querySelector(".card")
querySelectorAllAll matchesdocument.querySelectorAll(".card")

Frequently asked questions

How does GSAP select an HTML element?

GSAP accepts a CSS selector string, a DOM element, a collection of elements, or an array as its target. It resolves that target before applying the animation values.

Can GSAP animate multiple elements?

Yes. A class selector, NodeList, or array can contain several elements, and GSAP can animate every matching target together.

What is the difference between .class and #id?

A dot selects elements by class and may match several elements. A hash selects an ID, which should identify one unique element on a page.

Can I use querySelector with GSAP?

Yes. document.querySelector() returns the first matching DOM element, which can be passed directly to gsap.to() or another GSAP method.

Can I use querySelectorAll with GSAP?

Yes. document.querySelectorAll() returns a NodeList containing every match, and GSAP can use that collection as an animation target.

Does GSAP work on a PHP website?

Yes. PHP produces the HTML on the server, and GSAP selects and animates that HTML in the browser after the page loads.

18. What comes next?

You can now tell GSAP exactly which elements should be animated: one element, every class match, a scoped descendant, a DOM reference, a NodeList, or a normalized array. Next, you will focus on what gsap.to() does with those targets and how it moves them from their current values to a destination.