→ לכל המאגר

G123 · מסוע אופקי שנע עם הגלילה

GSAP GSAP · ScrollTrigger תמונות וגלריותרקע ואווירה ממתין

שתי שורות של תמונות או לוגואים שנעות אופקית בכיוונים מנוגדים, לא בלולאה אלא בקשר ישיר לגלילה: גוללים למטה, השורה העליונה נוסעת ימינה והתחתונה שמאלה. עוצרים, הכל עוצר.

מתי משתמשים: קיר לוגואים, גלריית פרויקטים, פס תמונות בין סקשנים. ששה עד עשרה פריטים בשורה.

הדמו כאן עיצובי-ניטרלי בכוונה. כשהמהלך נכנס לפרויקט, מיובאת רק ההתנהגות: הצבעים, הרדיוסים, הפונטים והצללים יורשים את העיצוב של אותו פרויקט.

הדמו

גלול למטה, הדמו מגיע ↓
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
עוד מסלול גלילה. נסה גם חזרה למעלה ↑
בלי pin: x של כל שורה הוא פונקציה של progress הסקשן במסך (מהכניסה ליציאה), ולכן המסוע תמיד בתנועה כשהוא נראה ולא דורש גלילה נוספת. במובייל המרחק קטן ל-40vw כדי שלא יעברו יותר מדי פריטים.

קוד להדבקה

הקוד כאן עומד בפני עצמו. כל טוקן עיצוב נושא ברירת מחדל, מחלקות העזר של המאגר מוטמעות בו, ותגי הסקריפט מסודרים לפי הסדר הנכון. פרויקט שמגדיר --accent או --line משלו יורש אותם אוטומטית. הרכיב הזה מסתמך על dir="rtl".

פתח קובץ עצמאי ↗
הצג את הקוד כאן

CSS

/* מחלקות עזר של המאגר שהרכיב הזה משתמש בהן */
.ph{display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;border-radius:var(--r, 14px)}
.ph-a{background:linear-gradient(160deg,#3b5bdb,#748ffc)}
.ph-b{background:linear-gradient(160deg,#5f3dc4,#9775fa)}
.ph-c{background:linear-gradient(160deg,#0b7285,#3bc9db)}
.ph-d{background:linear-gradient(160deg,#2b8a3e,#69db7c)}
.ph-e{background:linear-gradient(160deg,#e8590c,#ffa94d)}
.ph-l{background:rgba(16,18,43,.72);color:#fff;padding:.18em .7em;border-radius:999px;line-height:1.3;font-size:max(.78em,12px)}

/* G123 · מסוע אופקי שנע עם הגלילה */
.cv-belt{overflow:hidden;padding-block:40px;display:grid;gap:14px}
.cv-row{display:flex;gap:14px;width:max-content;will-change:transform}
.cv-row .ph{width:clamp(140px,18vw,260px);aspect-ratio:4/3;font-size:18px;flex:none}
.cv-row.r2{margin-inline-start:-12vw}

HTML

<div class="cv-belt">
  <div class="cv-row r1"><div class="ph ph-a"><span class="ph-l">1</span></div><div class="ph ph-b"><span class="ph-l">2</span></div><div class="ph ph-c"><span class="ph-l">3</span></div><div class="ph ph-d"><span class="ph-l">4</span></div><div class="ph ph-e"><span class="ph-l">5</span></div><div class="ph ph-a"><span class="ph-l">6</span></div><div class="ph ph-b"><span class="ph-l">7</span></div><div class="ph ph-c"><span class="ph-l">8</span></div></div>
  <div class="cv-row r2"><div class="ph ph-d"><span class="ph-l">9</span></div><div class="ph ph-e"><span class="ph-l">10</span></div><div class="ph ph-a"><span class="ph-l">11</span></div><div class="ph ph-b"><span class="ph-l">12</span></div><div class="ph ph-c"><span class="ph-l">13</span></div><div class="ph ph-d"><span class="ph-l">14</span></div><div class="ph ph-e"><span class="ph-l">15</span></div><div class="ph ph-a"><span class="ph-l">16</span></div></div>
</div>

JS

gsap.registerPlugin(ScrollTrigger);

(function(){
  if(matchMedia("(prefers-reduced-motion: reduce)").matches)return;
  const D=()=>innerWidth*(matchMedia("(max-width:767px)").matches?.4:.3);
  // RTL: שורה ראשונה מתחילה מוזזת שמאלה ונוסעת ימינה; השנייה הפוך
  gsap.fromTo(".cv-row.r1",{x:()=>-D()},{x:()=>D(),ease:"none",scrollTrigger:{trigger:".cv-belt",start:"top bottom",end:"bottom top",scrub:.4,invalidateOnRefresh:true}});
  gsap.fromTo(".cv-row.r2",{x:()=>D()},{x:()=>-D(),ease:"none",scrollTrigger:{trigger:".cv-belt",start:"top bottom",end:"bottom top",scrub:.4,invalidateOnRefresh:true}});
})();