Futó szöveg (marquee) — egy vizuális effekt, amely során a szöveg automatikusan vízszintesen görget egy korlátozott területen belül, lehetővé téve hosszú sorok megjelenítését egy kompakt tárolóban. Történetileg a kifejezés az <marquee> HTML címkétől származik, amely az 1990-es évek webén volt népszerű. A modern mobilfejlesztésben a scrolling text lejátszókban, hírcsíkokban és állapotsorokban használatos. Az Apple Human Interface Guidelines és Google Material Design szerint a futó szöveg csak korlátozott forgatókönyvekben engedélyezett, ahol a statikus levágás három ponttal rontja az UX-et.
Főbb pontok
Futó szöveg — egy UI effekt, amely során a szöveg vízszintesen mozog egy rögzített területen belül, ciklikusan görgetve, hogy a felhasználó elolvashassa az összes tartalmat, amely nem fér el a tárolóban. Ellentétben az ellipsize-val, amely elrejti a szöveg egy részét, a marquee a teljes szöveget megjeleníti, de mozgásban.
A marquee kifejezés (angolul — „előtető“, „reklámtábla“) az <marquee> HTML címkének köszönhetően rögzült, amelyet a Netscape és Internet Explorer böngészők korai verzióihoz adtak hozzá. A címke lehetővé tette görgő szöveg létrehozását JavaScript és CSS nélkül, de soha nem volt része a HTML szabványnak. A modern böngészők továbbra is támogatják a visszafelé kompatibilitás érdekében, de használata nem ajánlott.
A mobilfejlesztésben a futó szöveg megoldja a hosszú címkék problémáját kompakt tárolókban: dalnevek a lejátszóban, árfolyamcsíkok, hírsorok TV képernyőkön. Az animáció miatt azonban terheli az accessibility-t és irritálhatja a felhasználókat — ezért célzottan alkalmazzák.
A Nielsen Norman Group (2023) kutatása szerint a mozgó szöveg 15-20%-kal csökkenti az olvasási sebességet és növeli a kognitív terhelést. Csak akkor használjon futó szöveget, ha a statikus levágás (ellipsize) valóban elfogadhatatlan.
Androidon a futó szöveg a TextView beépített mechanizmusán keresztül implementálható az android:ellipsize="marquee" attribútummal. Ez az egyetlen ellipsize mód, amely nem vágja le a szöveget, hanem animálja a görgetését.
A marquee aktiválásához három feltételnek kell teljesülnie: singleLine="true" (vagy maxLines="1"), ellipsize="marquee" és setSelected(true) a kódban. A setSelected() meghívása nélkül az animáció nem indul el.
<!-- XML layout -->
<TextView
android:id="@+id/marquee_text"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever" />
// Kotlin: marquee aktiválása
textView.setSelected(true)
textView.isSingleLine = true
A marqueeRepeatLimit attribútum határozza meg az animáció ismétléseinek számát: marquee_forever (végtelen) vagy egy konkrét szám. Alapértelmezett — marquee_forever. Ha a szöveg rövidebb, mint a tároló szélessége, az animáció nem indul el — a TextView statikus szöveget jelenít meg.
Fontos jellemző: a setSelected(true) csak akkor működik, ha a TextView fókuszban van vagy selected módban van. RecyclerView-ban ez problémákat okozhat — az animáció csak egy elemre indul el. Megoldás — használjon egyéni MarqueeTextView-t, amely felülírja az isFocused()-ot és mindig true-t ad vissza.
Android 9-től (API 28) kezdve a Google javította a marquee viselkedését — az animáció simább lett és nem akad le a lista görgetésekor. Régebbi eszközökön azonban a marquee rángatózhat, különösen nagy pixelsűrűségnél.
iOS-en nincs beépített megfelelője az android:ellipsize="marquee"-nak. A futó szöveg manuálisan implementálható a Core Animation vagy SwiftUI animáció segítségével. A legelterjedtebb megközelítés — a layer.position animációja clipping tárolóval kombinálva.
UIKit-ben a futó szöveg három elemre épül: UILabel tároló clipsToBounds = true, maga a szöveg és CABasicAnimation a szöveg X tengely mentén történő mozgatásához végtelen ismétléssel és autoreverses = false, hogy a sáv egy irányba görögjön és ugrással térjen vissza.
func startMarquee(for label: UILabel) {
label.clipsToBounds = true
label.numberOfLines = 1
let textWidth = (label.text as? NSString)?
.size(withAttributes: [.font: label.font as any]).width ?? 0
guard textWidth > label.bounds.width else { return }
let animation = CABasicAnimation(keyPath: "position.x")
animation.fromValue = label.layer.position.x + label.bounds.width / 2
animation.toValue = label.layer.position.x - textWidth - label.bounds.width / 2
animation.duration = CFTimeInterval(textWidth / 60)
animation.repeatCount = .infinity
animation.autoreverses = false
label.layer.add(animation, forKey: "marquee")
}
A duration = textWidth / 60 számítás körülbelül 60 képpont/másodperc sebességet ad — kényelmes tempó az olvasáshoz. Ha a sebesség meghaladja a 120 px/s-ot, a szöveg olvashatatlanná válik. Ha 30 px/s alatt van — az animáció lassúnak tűnik. Változtassa a speed-et az adott forgatókönyv szerint.
SwiftUI-ben a futó szöveg egyszerűbben implementálható — az offset() módosítóval ismétlődő animációval és .animation(.linear(duration:).repeatForever(autoreverses: false)). A SwiftUI automatikusan kezeli az animáció életciklusát, de GeometryReader-t igényel a szöveg szélességének meghatározásához.
A weben az elavult <marquee> címke nem ajánlott használatra, bár a böngészők továbbra is támogatják. A futó szöveg modern implementációja — CSS animáció kulcskockákkal és transform: translateX.
A CSS megközelítés előnyei: teljes kontroll a sebesség, szünet és animációs görbe felett, prefers-reduced-motion támogatás az accessibility-hez, szemantikailag helytelen címke hiánya.
.marquee {
overflow: hidden;
white-space: nowrap;
width: 300px;
}
.marquee-content {
display: inline-block;
animation: marquee 10s linear infinite;
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
}
/* Pause on hover */
.marquee-content:hover {
animation-play-state: paused;
}
A kulcs trükk: a display: inline-block a tartalmon garantálja, hogy az elem szélessége megegyezik a szöveg szélességével, és a translateX(-100%) pontosan ezzel a szélességgel tolja balra. Ha a tartalom display: block, a translateX(-100%) a tároló szélességével lesz egyenlő, nem a szövegével, és az animáció elromlik.
Az accessibility-hez adja hozzá: @media (prefers-reduced-motion: reduce) { .marquee-content { animation: none; } } — a vesztibuláris rendellenességgel élő felhasználók statikus szöveget látnak görgetési lehetőséggel.
A futó szöveg indokolt olyan forgatókönyvekben, ahol a felhasználó nem tudja maga kibővíteni a tárolót, és a teljes szöveg kritikus fontosságú: aktuális szám a lejátszóban zárt képernyőn, hírsor TV panelen, futó szöveg taxi alkalmazásban (rendelés állapota).
A futó szöveg nem használandó táblázatokban, listákban, űrlapokban és párbeszédablakokban — mindenhol, ahol a felhasználó aktívan interakcióba lép a felülettel. Az animáció elvonja a figyelmet, növeli az elem keresési idejét és kényelmetlenséget okoz. A WebAIM (2024) szerint minden 3 vesztibuláris rendellenességgel élő felhasználóból 1 kényelmetlenséget jelez az animált szöveg nézésekor.
Ökölszabály: ha a szöveg lerövidíthető vagy a következő sorba helyezhető — tegye meg. A futó szöveg végső megoldás, nem univerzális megoldás hosszú címkékre.
A futó szöveg az egyik legproblematikusabb UI animáció az accessibility szempontjából. A mozgó szöveg szédülést, hányingert és dezorientációt okozhat a vesztibuláris rendellenességgel élőknél. A WCAG 2.2 szerint minden 5 másodpercnél tovább tartó animációnak rendelkeznie kell szüneteltető vagy kikapcsoló mechanizmussal.
iOS-en használja az UIAccessibility.isReduceMotionEnabled tulajdonságot a rendszerbeállítás ellenőrzéséhez. Ha a reduceMotion be van kapcsolva — ne indítsa el az animációt, jelenítsen meg statikus szöveget ellipsize-val.
Androidon ellenőrizze a rendszer animációt a Settings.Global.ANIMATOR_DURATION_SCALE segítségével. Ha a globális animáció ki van kapcsolva (duration scale = 0), a futó szöveg nem kapcsolható be.
A weben használja a prefers-reduced-motion média funkciót: @media (prefers-reduced-motion: reduce) { .marquee-content { animation: none; } }. Ez egy szabványos CSS képesség, amelyet minden modern böngésző támogat. Ellenőrizze DevTools-ban: kapcsolja be a prefers-reduced-motion emulációt és győződjön meg róla, hogy az animáció kikapcsol.
Gyakran ismételt kérdések
Ellipsize levágja a szöveget és három pontot tesz, elrejtve a tartalom egy részét. A Marquee a teljes szöveget görgeti, de mozgásban. A választás a prioritástól függ: mindent mutatni (marquee) vagy statikus maradni (ellipsize).
A beépített android:ellipsize="marquee" nem teszi lehetővé a sebesség változtatását — azt a rendszer ScrollSpeed határozza meg. Egyéni sebességhez használjon Animation vagy ValueAnimator-t manuálisan.
A view-k újrafelhasználása miatt a setSelected(true) visszaáll. Megoldás: hozzon létre egyéni MarqueeTextView-t, amely felülírja az isFocused()-ot és true-t ad vissza, vagy használjon egyéni animációt az Adapter.onViewAttachedToWindow()-ban.
Igen, a translateY segítségével a translateX helyett. A függőleges marquee stáblistákhoz (credits) vagy hírsorokhoz használatos függőleges sávokban. Az elv ugyanaz, de az animáció tengelye változik.
CSS-ben: :hover { animation-play-state: paused; }. Androidon: kövesse a fókuszt OnFocusChangeListener segítségével és állítsa vissza a setSelected(false)-et. iOS-en: távolítsa el az animációt a layer.removeAnimation(forKey:) segítségével.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is