→ לכל המאגר

G23 · Flip: פריט קופץ לגריד וחזרה

GSAP GSAP · Flip כרטיסיםתמונות וגלריותhover ומיקרו ממתין

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

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

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

הדמו

לחץ על כרטיס כדי להגדיל אותו, ולחץ שוב כדי להחזיר

1
2
3
4

קוד להדבקה

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

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

CSS

/* מחלקות עזר של המאגר שהרכיב הזה משתמש בהן */
.stage{padding:var(--sec, clamp(120px, 12vw, 260px)) var(--gutter, clamp(24px, 5vw, 96px));position:relative}
.stage.tight{padding-block:clamp(48px,5vw,90px)}
.stage.full{padding-inline:0}
.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-l{background:rgba(16,18,43,.72);color:#fff;padding:.18em .7em;border-radius:999px;line-height:1.3;font-size:max(.78em,12px)}
.center{text-align:center}

/* G23 · Flip: פריט קופץ לגריד וחזרה */
.flip-zone{padding-inline:var(--gutter, clamp(24px, 5vw, 96px))}
.flip-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;position:relative;overflow:hidden}
.flip-item{height:120px;cursor:pointer;font-size:15px}
.flip-item.big{grid-column:1/-1;height:320px;font-size:26px}
@media(max-width:767px){.flip-grid{grid-template-columns:repeat(2,1fr)}}

HTML

<div class="stage tight flip-zone"><p class="center" style="color:var(--muted);font-size:14px;margin-top:0">לחץ על כרטיס כדי להגדיל אותו, ולחץ שוב כדי להחזיר</p>
<div class="flip-grid">
<div class="flip-item ph ph-a"><span class="ph-l">1</span></div><div class="flip-item ph ph-b"><span class="ph-l">2</span></div>
<div class="flip-item ph ph-c"><span class="ph-l">3</span></div><div class="flip-item ph ph-d"><span class="ph-l">4</span></div>
</div></div>

JS

gsap.registerPlugin(Flip);

const grid=document.querySelector(".flip-grid");
const items=[...document.querySelectorAll(".flip-item")];
const D=.55,E="power2.inOut";
let busy=false;

items.forEach(item=>{
  item.addEventListener("click",()=>{
    if(busy)return; busy=true;

    const state=Flip.getState(items);
    const h0=grid.getBoundingClientRect().height;
    const fs0=items.map(el=>getComputedStyle(el).fontSize);

    items.forEach(b=>{if(b!==item)b.classList.remove("big")});
    item.classList.toggle("big");

    const h1=grid.getBoundingClientRect().height;
    const fs1=items.map(el=>getComputedStyle(el).fontSize);

    // absolute:true מוציא את כל הפריטים מהזרימה, הגריד מתרוקן ומתכווץ לאפס,
    // וכל מה שמתחת קופץ למעלה ובחזרה. מנפישים את גובה הגריד במקביל.
    gsap.fromTo(grid,{height:h0},{height:h1,duration:D,ease:E,
      onComplete:()=>gsap.set(grid,{clearProps:"height"})});

    // Flip לא מאינטרפל font-size, ולכן הטקסט קופץ למידה החדשה בפריים הראשון.
    items.forEach((el,i)=>{
      if(fs0[i]===fs1[i])return;
      gsap.fromTo(el,{fontSize:fs0[i]},{fontSize:fs1[i],duration:D,ease:E,
        onComplete:()=>gsap.set(el,{clearProps:"fontSize"})});
    });

    Flip.from(state,{duration:D,ease:E,absolute:true,onComplete:()=>{busy=false}});
  });
});