שורות טקסט מונחות זו אחרי זו בעומק. הגלילה מסיעה את הצופה קדימה: כל שורה גדלה, חולפת על פניו ונעלמת, והבאה מגיעה מהרחוק. מניפסט שנקרא כמו מסע.
מתי משתמשים: מניפסט, ערכים, "מה אנחנו מאמינים", פתיחת סיפור מותג. ארבע עד שבע שורות קצרות.
הדמו כאן עיצובי-ניטרלי בכוונה. כשהמהלך נכנס לפרויקט, מיובאת רק ההתנהגות: הצבעים, הרדיוסים, הפונטים והצללים יורשים את העיצוב של אותו פרויקט.
הקוד כאן עומד בפני עצמו. כל טוקן עיצוב נושא ברירת מחדל, מחלקות העזר של המאגר מוטמעות בו, ותגי הסקריפט מסודרים לפי הסדר הנכון. פרויקט שמגדיר --accent או --line משלו יורש אותם אוטומטית. הרכיב הזה מסתמך על dir="rtl".
/* G91 · טקסט שנוסע במנהרה לעומק */
.tn{position:relative;height:320vh}
.tn-pin{position:sticky;top:0;height:100vh;overflow:hidden;perspective:900px;background:var(--ink, #16182b);color:var(--bg, #f7f7fa);display:grid;place-items:center}
.tn-space{position:absolute;inset:0;transform-style:preserve-3d;display:grid;place-items:center}
.tn-line{position:absolute;font-size:clamp(28px,5vw,72px);font-weight:800;white-space:nowrap;will-change:transform,opacity;text-align:center;padding-inline:20px}
.tn-line small{display:block;font-size:.4em;font-weight:500;opacity:.7;margin-top:.3em}
.tn-glow{position:absolute;inset:30%;border-radius:50%;background:radial-gradient(closest-side,color-mix(in srgb,var(--accent, #4a3aff) 45%,transparent),transparent);filter:blur(40px)}
@media(max-width:767px){.tn{height:260vh}.tn-pin{perspective:600px}}
<div class="tn">
<div class="tn-pin"><div class="tn-glow"></div><div class="tn-space">
<div class="tn-line">אנחנו לא בונים אתרים.<small>שורה ראשונה</small></div>
<div class="tn-line">אנחנו בונים דרך להגיע אליכם.</div>
<div class="tn-line">בלי רעש. בלי קישוטים.</div>
<div class="tn-line">רק מה שמזיז לקוח לפעולה.</div>
<div class="tn-line">וזה נמדד. כל יום.</div>
</div></div>
</div>
gsap.registerPlugin(ScrollTrigger);
(function(){
const lines=gsap.utils.toArray(".tn-line"),STEP=matchMedia("(max-width:767px)").matches?700:1000;
if(matchMedia("(prefers-reduced-motion: reduce)").matches){lines.forEach((l,i)=>gsap.set(l,{position:"static",marginBottom:20}));return;}
lines.forEach((l,i)=>gsap.set(l,{z:-i*STEP,opacity:i===0?1:0}));
const total=(lines.length-1)*STEP+STEP*.6;
const tl=gsap.timeline({scrollTrigger:{trigger:".tn",start:"top top",end:"bottom bottom",scrub:.7}});
tl.to(lines,{z:"+="+total,ease:"none",duration:1},0);
// השקיפות יושבת באותו טיימליין ולא ב-onUpdate נפרד, כך שהיא נכונה גם בסקראב לאחור וגם בקפיצה.
// לכל שורה: מופיעה כשהיא במרחק 1.2 צעדים, מלאה מ-0.4 צעד, ונעלמת כשהיא חולפת על פני המצלמה.
const at=(i,z)=>Math.max(0,(z+i*STEP)/total); // הזמן (0..1) שבו השורה i מגיעה לעומק z
lines.forEach((l,i)=>{
if(i>0)tl.fromTo(l,{opacity:0},{opacity:1,duration:Math.max(.001,at(i,-STEP*.4)-at(i,-STEP*1.2)),ease:"none"},at(i,-STEP*1.2));
tl.to(l,{opacity:0,duration:Math.max(.001,at(i,300)-at(i,100)),ease:"none"},at(i,100));
});
})();