मार्की (marquee) एक दृश्य प्रभाव है जिसमें टेक्स्ट स्वचालित रूप से एक सीमित क्षेत्र के अंदर क्षैतिज रूप से स्क्रॉल होता है, जिससे लंबी स्ट्रिंग्स को एक कॉम्पैक्ट कंटेनर में प्रदर्शित किया जा सकता है। ऐतिहासिक रूप से, यह शब्द HTML टैग <marquee> से आया है, जो 1990 के दशक में वेब पर लोकप्रिय था। आधुनिक मोबाइल डेवलपमेंट में, scrolling text का उपयोग प्लेयर, न्यूज़ टिकर और स्टेटस बार में किया जाता है। Apple Human Interface Guidelines और Google Material Design के अनुसार, मार्की केवल सीमित परिदृश्यों में स्वीकार्य है जहाँ एलिप्सिस के साथ स्टैटिक ट्रंकेशन UX को खराब करता है।
मुख्य बिंदु
मार्की एक UI प्रभाव है जिसमें टेक्स्ट एक निश्चित क्षेत्र के अंदर क्षैतिज रूप से चलता है, चक्रीय रूप से स्क्रॉल करता है ताकि उपयोगकर्ता वह सभी सामग्री पढ़ सके जो कंटेनर में फिट नहीं होती। ellipsize के विपरीत, जो टेक्स्ट के हिस्से को छिपाता है, marquee पूरा टेक्स्ट दिखाता है, लेकिन गति में।
मार्की शब्द HTML टैग <marquee> के कारण स्थापित हुआ, जो Netscape और Internet Explorer ब्राउज़रों के शुरुआती संस्करणों में जोड़ा गया था। यह टैग JavaScript या CSS के बिना स्क्रॉलिंग टेक्स्ट बनाने की अनुमति देता था, लेकिन कभी HTML मानक का हिस्सा नहीं था। आधुनिक ब्राउज़र पिछड़ी संगतता के लिए इसे समर्थन करना जारी रखते हैं, लेकिन इसका उपयोग अनुशंसित नहीं है।
मोबाइल डेवलपमेंट में, marquee कॉम्पैक्ट कंटेनरों में लंबे लेबल की समस्या को हल करता है: प्लेयर में ट्रैक नाम, मुद्रा टिकर, टीवी स्क्रीन पर न्यूज़ टिकर। हालांकि, एनिमेशन के कारण, यह एक्सेसिबिलिटी पर बोझ डालता है और उपयोगकर्ताओं को परेशान कर सकता है — इसलिए इसका चयनात्मक रूप से उपयोग किया जाता है।
Nielsen Norman Group (2023) के शोध के अनुसार, चलता टेक्स्ट पढ़ने की गति को 15-20% कम करता है और संज्ञानात्मक भार बढ़ाता है। मार्की का उपयोग केवल तब करें जब स्टैटिक ट्रंकेशन (ellipsize) वास्तव में अस्वीकार्य हो।
Android पर, मार्की TextView की अंतर्निहित प्रणाली के माध्यम से android:ellipsize="marquee" विशेषता के ज़रिए कार्यान्वित होता है। यह एकमात्र ellipsize मोड है जो टेक्स्ट को ट्रंकेट नहीं करता बल्कि उसके स्क्रॉलिंग को एनिमेट करता है।
मार्की को सक्रिय करने के लिए तीन शर्तें पूरी होनी चाहिए: singleLine="true" (या maxLines="1"), ellipsize="marquee", और कोड में setSelected(true)। setSelected() को कॉल किए बिना, एनिमेशन शुरू नहीं होगा।
<!-- 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: activate marquee
textView.setSelected(true)
textView.isSingleLine = true
marqueeRepeatLimit विशेषता एनिमेशन दोहराव की संख्या निर्धारित करती है: marquee_forever (अनंत) या एक विशिष्ट संख्या। डिफ़ॉल्ट marquee_forever है। यदि टेक्स्ट कंटेनर की चौड़ाई से छोटा है, तो एनिमेशन शुरू नहीं होता — TextView स्थिर टेक्स्ट दिखाता है।
एक महत्वपूर्ण विशेषता: setSelected(true) केवल तब काम करता है जब TextView फोकस में हो या चयनित मोड में हो। RecyclerView में, यह समस्या पैदा कर सकता है — एनिमेशन केवल एक आइटम के लिए शुरू होता है। समाधान: एक कस्टम MarqueeTextView बनाएं जो isFocused() को ओवरराइड करे और हमेशा true लौटाए।
Android 9 (API 28) से शुरू करके, Google ने marquee व्यवहार में सुधार किया — एनिमेशन चिकना हो गया और सूची स्क्रॉल करते समय फ्रीज़ नहीं होता। हालांकि, पुराने उपकरणों पर, marquee लड़खड़ा सकता है, विशेष रूप से उच्च पिक्सेल घनत्व पर।
iOS में android:ellipsize="marquee" का कोई अंतर्निहित समकक्ष नहीं है। मार्की मैन्युअल रूप से Core Animation या SwiftUI एनिमेशन के माध्यम से कार्यान्वित किया जाता है। सबसे सामान्य दृष्टिकोण एक क्लिपिंग कंटेनर के साथ layer.position को एनिमेट करना है।
UIKit में, मार्की तीन तत्वों पर बनाया जाता है: clipsToBounds = true वाला UILabel कंटेनर, टेक्स्ट स्वयं, और X पर टेक्स्ट को शिफ्ट करने के लिए अनंत दोहराव और autoreverses = false वाली CABasicAnimation, ताकि लाइन एक दिशा में स्क्रॉल हो और वापस कूद जाए।
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")
}
duration = textWidth / 60 की गणना लगभग 60 पिक्सेल प्रति सेकंड की गति देती है — पढ़ने के लिए एक आरामदायक गति। यदि गति 120 px/s से अधिक है, तो टेक्स्ट अपठनीय हो जाता है। यदि 30 px/s से कम है, तो एनिमेशन सुस्त दिखता है। अपने विशिष्ट परिदृश्य के अनुसार गति समायोजित करें।
SwiftUI में, मार्की अधिक सरलता से कार्यान्वित किया जाता है — दोहराने योग्य एनिमेशन के साथ offset() मॉडिफायर और .animation(.linear(duration:).repeatForever(autoreverses: false)) के माध्यम से। SwiftUI स्वचालित रूप से एनिमेशन जीवनचक्र का प्रबंधन करता है लेकिन टेक्स्ट की चौड़ाई निर्धारित करने के लिए GeometryReader की आवश्यकता होती है।
वेब पर, पुराना <marquee> टैग अनुशंसित नहीं है, हालाँकि ब्राउज़र इसे समर्थन करना जारी रखते हैं। मार्की का आधुनिक कार्यान्वयन keyframes और transform: translateX के साथ CSS एनिमेशन है।
CSS दृष्टिकोण के लाभ: गति, ठहराव और एनिमेशन वक्र पर पूर्ण नियंत्रण, एक्सेसिबिलिटी के लिए prefers-reduced-motion का समर्थन, और शब्दार्थ रूप से गलत टैग की अनुपस्थिति।
.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;
}
मुख्य तरकीब: सामग्री पर display: inline-block यह सुनिश्चित करता है कि तत्व की चौड़ाई टेक्स्ट की चौड़ाई के बराबर हो, और translateX(-100%) इसे बाईं ओर ठीक उस चौड़ाई पर शिफ्ट करता है। यदि सामग्री display: block है, तो translateX(-100%) कंटेनर की चौड़ाई के बराबर होगा, टेक्स्ट की चौड़ाई के नहीं, और एनिमेशन टूट जाएगा।
एक्सेसिबिलिटी के लिए, @media (prefers-reduced-motion: reduce) { .marquee-content { animation: none; } } जोड़ें — वेस्टिबुलर विकारों वाले उपयोगकर्ता स्क्रॉलिंग क्षमता के साथ स्थिर टेक्स्ट देखेंगे।
मार्की उन परिदृश्यों में उचित है जहाँ उपयोगकर्ता स्वयं कंटेनर का विस्तार नहीं कर सकता और पूरा टेक्स्ट महत्वपूर्ण है: लॉक स्क्रीन पर प्लेयर में वर्तमान ट्रैक, टीवी पैनल पर न्यूज़ टिकर, राइड-हेलिंग ऐप में मार्की (ऑर्डर स्थिति)।
मार्की का उपयोग तालिकाओं, सूचियों, फ़ॉर्म और डायलॉग में नहीं किया जाना चाहिए — जहाँ भी उपयोगकर्ता सक्रिय रूप से इंटरफ़ेस के साथ इंटरैक्ट करता है। एनिमेशन लक्ष्य से विचलित करता है, तत्व खोज समय बढ़ाता है और असुविधा पैदा करता है। WebAIM (2024) के अनुसार, वेस्टिबुलर विकारों वाले 3 में से 1 उपयोगकर्ता एनिमेटेड टेक्स्ट देखने पर असुविधा की रिपोर्ट करता है।
एक सामान्य नियम: यदि टेक्स्ट को छोटा किया जा सकता है या अगली पंक्ति में लपेटा जा सकता है — तो करें। मार्की अंतिम उपाय है, लंबे लेबल के लिए सार्वभौमिक समाधान नहीं।
मार्की एक्सेसिबिलिटी के दृष्टिकोण से सबसे समस्याग्रस्त UI एनिमेशन में से एक है। चलता टेक्स्ट वेस्टिबुलर विकारों वाले लोगों में चक्कर, मतली और भटकाव पैदा कर सकता है। WCAG 2.2 के अनुसार, 5 सेकंड से अधिक समय तक चलने वाले किसी भी एनिमेशन में ठहराव या निष्क्रिय करने की प्रणाली होनी चाहिए।
iOS पर, सिस्टम सेटिंग जाँचने के लिए UIAccessibility.isReduceMotionEnabled प्रॉपर्टी का उपयोग करें। यदि reduceMotion सक्षम है — तो एनिमेशन शुरू न करें, ellipsize के साथ स्थिर टेक्स्ट दिखाएँ।
Android पर, Settings.Global.ANIMATOR_DURATION_SCALE के माध्यम से सिस्टम एनिमेशन जाँचें। यदि वैश्विक एनिमेशन अक्षम है (duration scale = 0), तो मार्की सक्षम नहीं किया जाना चाहिए।
वेब पर, prefers-reduced-motion मीडिया फ़ीचर का उपयोग करें: @media (prefers-reduced-motion: reduce) { .marquee-content { animation: none; } }। यह एक मानक CSS सुविधा है जो सभी आधुनिक ब्राउज़रों द्वारा समर्थित है। DevTools में जाँचें: prefers-reduced-motion एमुलेशन सक्षम करें और सत्यापित करें कि एनिमेशन बंद हो जाता है।
अक्सर पूछे जाने वाले प्रश्न
Ellipsize टेक्स्ट को काटता है और एलिप्सिस जोड़ता है, सामग्री के हिस्से को छिपाता है। Marquee पूरा टेक्स्ट स्क्रॉल करता है, लेकिन गति में। चुनाव प्राथमिकता पर निर्भर करता है: सब कुछ दिखाना (marquee) या स्थिर प्रदर्शन बनाए रखना (ellipsize)।
अंतर्निहित android:ellipsize="marquee" गति बदलने की अनुमति नहीं देता — यह सिस्टम ScrollSpeed द्वारा निर्धारित होती है। कस्टम गति के लिए, मैन्युअल रूप से Animation या ValueAnimator का उपयोग करें।
व्यू रीसाइक्लिंग के कारण, setSelected(true) रीसेट हो जाता है। समाधान: एक कस्टम MarqueeTextView बनाएं जो isFocused() को ओवरराइड करे और true लौटाए, या Adapter.onViewAttachedToWindow() में कस्टम एनिमेशन का उपयोग करें।
हाँ, translateX के बजाय translateY का उपयोग करके। वर्टिकल मार्की का उपयोग क्रेडिट या वर्टिकल फ़ीड में न्यूज़ टिकर के लिए किया जाता है। सिद्धांत समान है, लेकिन एनिमेशन अक्ष बदल जाता है।
CSS में: :hover { animation-play-state: paused; }। Android पर: OnFocusChangeListener के माध्यम से फ़ोकस ट्रैक करें और setSelected(false) रीसेट करें। iOS पर: layer.removeAnimation(forKey:) के माध्यम से एनिमेशन हटाएँ।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें