→ לכל המאגר

B24 · כפתור שהאותיות בו מתחלפות בהובר

התנהגויות CSS transform · JS split hover ומיקרוטעינה ופידבק ממתין

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

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

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

הדמו

העבר עכבר, או הגע עם Tab

הטקסט האמיתי נשמר ב-aria-label ושתי השכבות מסומנות aria-hidden, אחרת קורא מסך היה מקריא את המילה פעמיים. ההשהיה המדורגת היא 22 מילישניות לאות: מעל 30 זה מתחיל להרגיש איטי, ומתחת ל-15 האפקט נעלם.

קוד להדבקה

הקוד כאן עומד בפני עצמו. כל טוקן עיצוב נושא ברירת מחדל, מחלקות העזר של המאגר מוטמעות בו, ותגי הסקריפט מסודרים לפי הסדר הנכון. פרויקט שמגדיר --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}
.center{text-align:center}

/* B24 · כפתור שהאותיות בו מתחלפות בהובר */
.rb{--rb-bg:var(--ink, #16182b);--rb-fg:#fff;
  display:inline-flex;align-items:center;gap:10px;border:0;cursor:pointer;font:inherit;font-weight:600;font-size:17px;
  background:var(--rb-bg);color:var(--rb-fg);border-radius:999px;padding:16px 30px;overflow:hidden;position:relative}
.rb.ghost{--rb-bg:transparent;--rb-fg:var(--ink, #16182b);border:1px solid var(--line, #e4e4ee)}
.rb.accent{--rb-bg:var(--accent, #4a3aff)}
.rb-txt{display:inline-flex;position:relative;overflow:hidden;line-height:1.25}
.rb-row{display:inline-flex}
.rb-row.b{position:absolute;inset-inline-start:0;top:0}
.rb-ch{display:inline-block;transition:transform .42s cubic-bezier(.2,.6,.2,1);transition-delay:calc(var(--i) * 22ms)}
.rb-row.a .rb-ch{transform:translateY(0)}
.rb-row.b .rb-ch{transform:translateY(105%)}
.rb:hover .rb-row.a .rb-ch,.rb:focus-visible .rb-row.a .rb-ch{transform:translateY(-105%)}
.rb:hover .rb-row.b .rb-ch,.rb:focus-visible .rb-row.b .rb-ch{transform:translateY(0)}
.rb-arrow{transition:transform .42s cubic-bezier(.2,.6,.2,1)}
.rb:hover .rb-arrow{transform:translateX(-5px)}
.rb-demo{display:flex;gap:16px;flex-wrap:wrap;justify-content:center}
@media (prefers-reduced-motion: reduce){.rb-ch,.rb-arrow{transition:none}}

HTML

<div class="stage tight center"><div class="rb-demo">
  <button class="rb accent"><span class="rb-txt" data-rb>קבעו שיחה</span><span class="rb-arrow" aria-hidden="true">←</span></button>
  <button class="rb"><span class="rb-txt" data-rb>לכל העבודות</span><span class="rb-arrow" aria-hidden="true">←</span></button>
  <button class="rb ghost"><span class="rb-txt" data-rb>המחירון שלנו</span></button>
</div>
<p style="color:var(--muted);font-size:14px;margin-top:22px">העבר עכבר, או הגע עם Tab</p></div>

JS

(function(){
  document.querySelectorAll("[data-rb]").forEach(el=>{
    const text=el.textContent.trim();
    el.textContent="";
    el.setAttribute("aria-label",text);
    // שתי שכבות זהות: העליונה יוצאת, התחתונה נכנסת
    ["a","b"].forEach(k=>{
      const row=document.createElement("span");
      row.className="rb-row "+k;
      row.setAttribute("aria-hidden","true");
      [...text].forEach((c,i)=>{
        const s=document.createElement("span");
        s.className="rb-ch";
        s.style.setProperty("--i",k==="a"?i:i);
        s.textContent=c===" "?"\u00a0":c;
        row.appendChild(s);
      });
      el.appendChild(row);
    });
  });
})();