😀😊 Đây là giải thích đầy đủ, ngắn gọn và thực tế về các option quan trọng của ScrollTrigger (ok)

1. start

🔹 Ý nghĩa: Xác định khi nào trigger bắt đầu kích hoạt 🔹 Cú pháp: "triggerPosition viewportPosition"

Ví dụ
Giải thích

"top top"

Khi top của trigger chạm top viewport

"bottom bottom"

Khi bottom của trigger chạm bottom viewport

"top center"

Khi top trigger chạm giữa viewport

"top+=100 top"

Khi top trigger + 100px chạm top viewport

"center center+=50"

Khi center trigger chạm center viewport + 50px

Thường dùng: "top top" hoặc "top center"

2. end

🔹 Ý nghĩa: Xác định khi nào trigger kết thúc 🔹 Cú pháp: giống start

Ví dụ
Giải thích

"bottom top"

Khi bottom trigger chạm top viewport

"+=500"

Kết thúc sau khi scroll thêm 500px

"bottom+=200 top"

Bottom trigger + 200px chạm top viewport

Thường dùng: "+=scrollDistance" khi scroll horizontal gallery

3. pin

🔹 Ý nghĩa: Pin (cố định) phần tử được trigger khi scroll 🔹 Giá trị: true (pin trigger element) hoặc selector khác

Option
Giải thích

pin: true

Pin chính trigger element

pin: ".my-element"

Pin element khác

Ứng dụng: Pin section gallery, hero content, sticky sidebar

4. pinSpacing

🔹 Ý nghĩa: Quyết định ScrollTrigger có tạo spacing phía dưới pinned element hay không

Giá trị
Giải thích

true (default)

Tạo spacing bằng height pinned element, scroll tới content dưới bình thường

false

Không tạo spacing, pinned element sẽ che section dưới

Thường giữ mặc định true, chỉ dùng false khi overlay fixed.

5. anticipatePin

🔹 Ý nghĩa: Làm mượt hiện tượng jump khi pin bắt đầu 🔹 Giá trị: Số nguyên (thường 1 hoặc 2) 🔹 Hoạt động: ScrollTrigger dự đoán pin trước khi thực hiện, giúp layout không giật khi pin activate.

Thường dùng: anticipatePin: 1

6. scrub

🔹 Ý nghĩa: Gắn animation với scroll position 🔹 Giá trị:

Option
Giải thích

true

Animation chạy bám sát scroll position

number

Delay scrub (mượt hơn, không quá gắt)

Ứng dụng: Horizontal gallery scroll, text reveal bám scroll

🚀 7. Tóm tắt nhanh cấu hình chuẩn (example)

jsCopyEditScrollTrigger.create({
  trigger: ".section",
  start: "top top",
  end: "+=1000",
  pin: true,
  pinSpacing: true,
  anticipatePin: 1,
  scrub: true,
  markers: true
});
Option
Ý nghĩa

start

Bắt đầu khi top section chạm top viewport

end

Kết thúc sau 1000px scroll

pin

Pin section

pinSpacing

Tạo spacing phía dưới

anticipatePin

Mượt khi bắt đầu pin

scrub

Animation gắn chặt với scroll position

Dưới đây là 📚 Full Advanced GSAP ScrollTrigger Cheat Sheet + Gallery Horizontal Scroll + Hero Scroll Effect được hệ thống hóa tối ưu cho dự án của bạn, phục vụ học tập, triển khai production, và lưu làm notes GSAP nhanh.

1. Cấu hình cơ bản

Option
Ý nghĩa
Example

trigger

Phần tử kích hoạt scroll

.section

start

Thời điểm bắt đầu trigger

"top center", "bottom bottom", "+=100"

end

Thời điểm kết thúc trigger

"bottom top", "+=500"

pin

Giữ cố định phần tử khi scroll

true, ".sidebar"

pinSpacing

Có tạo spacing dưới pin không

true (default) / false

scrub

Gắn animation theo scroll position

true / 0.5

anticipatePin

Mượt khi pin bắt đầu

1

markers

Hiện markers debug

true

2. Timeline integration

gsap.timeline({
  scrollTrigger: {
    trigger: ".section",
    start: "top top",
    end: "+=500",
    scrub: true,
    pin: true,
    markers: true
  }
})
.to(".element", { opacity: 1, y: -50 })
.to(".other", { scale: 1.2 });

3. Utility

Function
Ý nghĩa

ScrollTrigger.refresh()

Refresh tất cả ScrollTriggers

ScrollTrigger.kill()

Kill ScrollTrigger

gsap.utils.toArray(".class")

Convert NodeList to array

ScrollTrigger.getAll()

Lấy tất cả ScrollTriggers hiện tại

🎨 II. Hero Scroll Effect Example

Goal

  • Pin hero section

  • Animate title và subtitle theo scroll (fade out + move up)


🔧 Code

htmlCopyEdit<section class="hero">
  <h1>Hero Title</h1>
  <p>Subtitle description here</p>
</section>

<section class="content">Main Content</section>
cssCopyEdit.hero {
  height: 100vh;
  background: #333;
  color: white;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.content {
  height: 200vh;
  background: #eee;
}
jsCopyEditgsap.registerPlugin(ScrollTrigger);

const tl = gsap.timeline({
  scrollTrigger: {
    trigger: ".hero",
    start: "top top",
    end: "+=500",
    scrub: true,
    pin: true,
    markers: true
  }
});

tl.to(".hero h1", {
  y: -100,
  opacity: 0
})
.to(".hero p", {
  y: -50,
  opacity: 0
}, "<");

Goal

  • Pin gallery section

  • Scroll các item ngang theo vertical scroll


🔧 Code

htmlCopyEdit<section class="gallery-section">
  <div class="gallery-container">
    <div class="gallery-item">Item 1</div>
    <div class="gallery-item">Item 2</div>
    <div class="gallery-item">Item 3</div>
    <div class="gallery-item">Item 4</div>
  </div>
</section>

<section class="after">Section After</section>
cssCopyEdit.gallery-section {
  height: 100vh;
  overflow: hidden;
  background: #111;
  color: white;
}
.gallery-container {
  display: flex;
  height: 100%;
}
.gallery-item {
  min-width: 100vw;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 3rem;
}
.after {
  height: 100vh;
  background: #eee;
}
jsCopyEditconst container = document.querySelector(".gallery-container");
const scrollWidth = container.scrollWidth;
const viewportWidth = window.innerWidth;
const scrollDistance = scrollWidth - viewportWidth;

gsap.to(container, {
  x: -scrollDistance,
  ease: "none",
  scrollTrigger: {
    trigger: ".gallery-section",
    start: "top top",
    end: () => "+=" + scrollDistance,
    pin: true,
    scrub: true,
    anticipatePin: 1,
    markers: true
  }
});

🔥 IV. Kỹ thuật nâng cao

1. ScrollSmoother integration

jsCopyEditconst smoother = ScrollSmoother.create({
  wrapper: "#wrapper",
  content: "#content",
  smooth: 1.5,
  effects: true
});

2. SplitText + ScrollTrigger

jsCopyEditconst split = new SplitText(".text", { type: "chars" });
gsap.from(split.chars, {
  y: 100,
  opacity: 0,
  stagger: 0.05,
  scrollTrigger: {
    trigger: ".text",
    start: "top 80%",
    end: "bottom top",
    scrub: true,
    markers: true
  }
});

3. Counter animation on scroll

jsCopyEditScrollTrigger.create({
  trigger: ".counter",
  start: "top bottom",
  onEnter: () => {
    gsap.to(counterObj, {
      value: endValue,
      duration: 2,
      ease: "power1.out",
      onUpdate: () => {
        counterEl.innerText = Math.floor(counterObj.value);
      }
    });
  }
});

🎯 V. Kết luận

✅ Đây là Full Advanced Cheat Sheet + Hero Effect + Gallery Horizontal Scroll giúp bạn:

  • Nắm chắc ScrollTrigger options

  • Áp dụng nhanh gallery landing page

  • Tạo hero scroll effect mượt


💡 Tip cuối cùng

🔹 Luôn kiểm tra marker để debug start/end chính xác 🔹 Luôn ScrollTrigger.refresh() khi load dynamic content hoặc resize window


Nếu bạn cần, tôi có thể viết template landing page GSAP production-ready kết hợp toàn bộ các hiệu ứng này cho dự án frontend của bạn tuần này. Hãy cho tôi biết để tôi lên cấu trúc tối ưu.

🔍 Rất hay khi bạn hỏi về endTrigger trong ScrollTrigger, đây là một option quan trọng nhưng ít người hiểu rõ.

1. endTrigger là gì?

🔹 endTrigger xác định phần tử dùng làm mốc tính toán end thay vì mặc định là trigger element.


⚠️ 2. Mặc định behavior

Nếu bạn viết:

jsCopyEditScrollTrigger.create({
  trigger: ".section",
  start: "top top",
  end: "bottom top",
  ...
});

end sẽ tính dựa trên trigger element (.section), ví dụ:

  • Khi bottom của .section chạm top viewport → ScrollTrigger kết thúc.


🔧 3. Khi dùng endTrigger

Nếu bạn muốn end dựa vào phần tử khác, ví dụ .footer:

jsCopyEditScrollTrigger.create({
  trigger: ".section",
  start: "top top",
  endTrigger: ".footer",
  end: "bottom top",
  ...
});

Ý nghĩa:

  • start: Khi top .section chạm top viewport.

  • end: Khi bottom .footer chạm top viewport.


🎯 4. Ứng dụng thực tế

🔹 Pin sidebar tới footer:

jsCopyEditScrollTrigger.create({
  trigger: ".sidebar",
  start: "top top",
  endTrigger: ".footer",
  end: "top bottom",
  pin: true,
  scrub: true
});

✅ Sidebar được pin từ đầu đến khi .footer bắt đầu scroll lên.


🔧 5. Ví dụ minh họa khác

jsCopyEditScrollTrigger.create({
  trigger: ".section",
  start: "top center",
  endTrigger: ".next-section",
  end: "top center",
  scrub: true
});

➡️ Animation scrub từ khi .section top chạm center viewport đến khi .next-section top chạm center viewport.


6. Tóm tắt

Option
Ý nghĩa

endTrigger

Phần tử dùng làm mốc tính end

Mặc định

endTrigger = trigger


💡 Tip: Rất hữu ích khi bạn cần pin đến một phần tử khác hoặc control animation dài nhiều section.


Nếu cần, tôi có thể viết full bài học ScrollTrigger pin sidebar with endTrigger + ScrollSmoother integration để bạn áp dụng cho dự án tuần này. Hãy cho tôi biết.

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>CodePen - Hero &amp; Column Pin</title>
  <link rel='stylesheet' href='https://codepen.io/GreenSock/pen/xxmzBrw.css'>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    .header {
      position: fixed;
      width: 100%;
      height: 200px;
      background-color: #a0a0a0;
      z-index: 10;
    }
    .wrapper {
      padding-top: 200px;
    }
    .hero {
      width: 100%;
      height: 40vh;
    }
    .row {
      display: flex;
      justify-content: flex-start;
      width: 100%;
      height: 100vh;
    }
    .right-row {
      justify-content: flex-end;
    }
    .column {
      width: 50%;
      height: 100%;
    }
    .spacer {
      width: 100%;
      height: 100vh;
    }
  </style>
</head>
<body>
<!-- partial:index.partial.html -->
<div class="header"></div>
<div class="wrapper">
  <div class="hero gradient-purple"></div>
  <div class="row left-row">
    <div class="column gradient-green">
      <h1>Lorem ipsum dolor sit amet.</h1>
    </div>
  </div>
  <div class="row right-row">
    <div class="column gradient-blue">
      <h1>Lorem ipsum dolor sit amet.</h1>
    </div>
  </div>
</div>
<div class="spacer gradient-red"></div>
<!-- partial -->
  <script src='https://unpkg.com/gsap@3/dist/gsap.min.js'></script>
<script src='https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js'></script>
<script>
  gsap.registerPlugin(ScrollTrigger);
  // pin the image
  const heroSt = ScrollTrigger.create({
    trigger: ".hero",
    start: "bottom 250",
    end: "top bottom",
    endTrigger: ".spacer",
    pin: true,
    pinSpacing: false,
    // markers: true,
    id: "hero"
  });
  // Pin left column
  ScrollTrigger.create({
    trigger: ".left-row",
    start: () => heroSt.start,
    end: () => heroSt.end,
    pin: true,
    pinSpacing: false,
    // markers: { indent: 150 },
    id: "lft"
  });
  // Pin right column
  ScrollTrigger.create({
    trigger: ".right-row",
    start: "top 250",
    end: heroSt.end,
    pin: true,
    pinSpacing: false,
    // markers: { indent: 300 },
    id: "rgt"
  });
</script>
</body>
</html>

Last updated

Was this helpful?