רצועת תוכן שזורמת בלולאה מושלמת: העותקים משוכפלים לפי רוחב המסך, ההזזה היא רוחב קבוצה מדויק, ומסכת קצה ממיסה את החיתוך. הובר עוצר.
מתי משתמשים: נקודות אמון בתחתית הירו, רצועת לוגואים, פסי אווירה.
הדמו כאן עיצובי-ניטרלי בכוונה. כשהמהלך נכנס לפרויקט, מיובאת רק ההתנהגות: הצבעים, הרדיוסים, הפונטים והצללים יורשים את העיצוב של אותו פרויקט.
הקוד כאן עומד בפני עצמו. כל טוקן עיצוב נושא ברירת מחדל, מחלקות העזר של המאגר מוטמעות בו, ותגי הסקריפט מסודרים לפי הסדר הנכון. פרויקט שמגדיר --accent או --line משלו יורש אותם אוטומטית. הרכיב הזה מסתמך על dir="rtl".
/* מחלקות עזר של המאגר שהרכיב הזה משתמש בהן */
.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}
/* B01 · מרקי (רצועה נעה) */
.marq{overflow:hidden;white-space:nowrap;-webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);border-block:1px solid var(--line, #e4e4ee);background:var(--bg, #f7f7fa);padding-block:22px}
/* ההזזה היא רוחב קבוצה אחת בפיקסלים (משתנה שנקבע ב-JS), ולא אחוז מהרצועה.
אחוז נשבר ברגע שמספר העותקים משתנה, ופיקסלים מדויקים תמיד. */
.marq-track{display:flex;width:max-content;animation:marq linear infinite;animation-duration:var(--marq-dur,32s)}
.marq:hover .marq-track{animation-play-state:paused}
/* הריווח בין הקבוצות יושב על כל קבוצה בצד הפנימי, ולכן גם התפר וגם הסגירה זהים */
.marq-set{display:flex;gap:56px;padding-inline-end:56px}
.marq-track span{font-weight:800;font-size:22px;color:var(--muted, #6a6d85);opacity:.75;white-space:nowrap}
@keyframes marq{from{transform:translateX(0)}to{transform:translateX(var(--marq-shift,50%))}}
<div class="stage tight full"><div class="marq" aria-hidden="true"><div class="marq-track">
<div class="marq-set"><span>אמינות</span><span>·</span><span>מקצועיות</span><span>·</span><span>שירות</span><span>·</span><span>ניסיון</span><span>·</span></div>
</div></div></div>
(function(){
// כמה עותקים צריך: אחרי הזזה של קבוצה אחת, מה שנשאר חייב עדיין לכסות את כל הרוחב.
// שני עותקים בלבד משאירים שטח ריק בקצה ברגע שהקבוצה צרה מהמסך.
function build(marq){
const track=marq.querySelector(".marq-track");
const proto=track.firstElementChild;
[...track.children].slice(1).forEach(c=>c.remove());
const setW=proto.getBoundingClientRect().width;
if(!setW)return;
const need=Math.ceil(marq.getBoundingClientRect().width/setW)+1;
for(let i=1;i<need;i++){
const c=proto.cloneNode(true);c.setAttribute("aria-hidden","true");track.appendChild(c);
}
track.style.setProperty("--marq-shift",setW+"px");
// מהירות אחידה בפיקסלים לשנייה, כדי שתוכן ארוך לא ירוץ מהר יותר
track.style.setProperty("--marq-dur",(setW/55).toFixed(2)+"s");
}
const all=[...document.querySelectorAll(".marq")];
all.forEach(build);
// מדידה לפני שהפונט נטען נותנת רוחב קטן יותר, וההזזה יוצאת קצרה מקבוצה שלמה: קפיצה בכל סיבוב
if(document.fonts)document.fonts.ready.then(()=>all.forEach(build));
let t;addEventListener("resize",()=>{clearTimeout(t);t=setTimeout(()=>all.forEach(build),200);});
})();