स्प्लिट लेटर और वर्ड ऐनिमेशन बनाने के तरीके के बारे में बुनियादी जानकारी.
इस पोस्ट में, मैं वेब के लिए स्प्लिट टेक्स्ट ऐनिमेशन और इंटरैक्शन को हल करने के तरीकों के बारे में बताना चाहता हूं. ये तरीके कम से कम, ऐक्सेस किए जा सकने वाले, और सभी ब्राउज़र पर काम करने वाले होने चाहिए. डेमो आज़माएं.
अगर आपको वीडियो देखना ज़्यादा पसंद है, तो इस पोस्ट का YouTube वर्शन यहां दिया गया है:
खास जानकारी
टेक्स्ट को अलग-अलग हिस्सों में बांटकर बनाए गए ऐनिमेशन शानदार हो सकते हैं. इस पोस्ट में, हम ऐनिमेशन की संभावनाओं के बारे में सिर्फ़ बुनियादी जानकारी देंगे. हालांकि, इससे आपको ऐनिमेशन बनाने में मदद मिलेगी. इसका मकसद, धीरे-धीरे ऐनिमेशन दिखाना है. टेक्स्ट डिफ़ॉल्ट रूप से पढ़ा जा सकने वाला होना चाहिए. साथ ही, ऐनिमेशन को टेक्स्ट के ऊपर बनाया जाना चाहिए. स्प्लिट टेक्स्ट मोशन इफ़ेक्ट बहुत ज़्यादा और संभावित रूप से रुकावट डालने वाले हो सकते हैं. इसलिए, हम सिर्फ़ एचटीएमएल में बदलाव करेंगे या मोशन स्टाइल तब लागू करेंगे, जब उपयोगकर्ता को मोशन से कोई समस्या न हो.
वर्कफ़्लो और नतीजों के बारे में यहां खास जानकारी दी गई है:
- सीएसएस और JS के लिए, मोशन कम करने की शर्त वाली वैरिएबल तैयार करें.
- JavaScript में, टेक्स्ट को स्प्लिट करने की यूटिलिटी तैयार करें.
- पेज लोड होने पर, शर्तों और यूटिलिटी को ऑर्केस्ट्रेट करें.
- अक्षरों और शब्दों के लिए सीएसएस ट्रांज़िशन और ऐनिमेशन लिखें (यह सबसे मज़ेदार हिस्सा है!).
यहां शर्त के हिसाब से दिखाए जाने वाले नतीजों की झलक दी गई है:

अगर कोई उपयोगकर्ता मोशन कम करने की सुविधा को चुनता है, तो हम एचटीएमएल दस्तावेज़ में कोई बदलाव नहीं करते और न ही कोई ऐनिमेशन दिखाते हैं. अगर मोशन ठीक है, तो हम उसे छोटे-छोटे हिस्सों में बांट देते हैं. यहां JavaScript के ज़रिए टेक्स्ट को अक्षर के हिसाब से बांटने के बाद, एचटीएमएल की झलक दी गई है.

मोशन कंडीशनल तैयार किए जा रहे हैं
इस प्रोजेक्ट में, सीएसएस और JavaScript से @media
(prefers-reduced-motion: reduce)
मीडिया क्वेरी का इस्तेमाल किया जाएगा. यह क्वेरी आसानी से उपलब्ध है. यह मीडिया क्वेरी, टेक्स्ट को बांटने या न बांटने का फ़ैसला करने के लिए हमारी मुख्य शर्त है. सीएसएस मीडिया क्वेरी का इस्तेमाल ट्रांज़िशन और ऐनिमेशन को रोकने के लिए किया जाएगा. वहीं, JavaScript मीडिया क्वेरी का इस्तेमाल एचटीएमएल में बदलाव को रोकने के लिए किया जाएगा.
सीएसएस की शर्त तैयार की जा रही है
मैंने Media Queries Level 5 के सिंटैक्स को चालू करने के लिए, PostCSS का इस्तेमाल किया. इससे मुझे मीडिया क्वेरी बूलियन को किसी वैरिएबल में सेव करने की सुविधा मिलती है:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
JS की शर्त तैयार करना
JavaScript में, ब्राउज़र मीडिया क्वेरी की जांच करने का तरीका उपलब्ध कराता है. मैंने मीडिया क्वेरी की जांच से मिले बूलियन नतीजे को निकालने और उसका नाम बदलने के लिए, डीस्ट्रक्चरिंग का इस्तेमाल किया:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
इसके बाद, मैं motionOK
की जांच कर सकता हूं. साथ ही, अगर उपयोगकर्ता ने मोशन कम करने का अनुरोध नहीं किया है, तो सिर्फ़ दस्तावेज़ में बदलाव कर सकता हूं.
if (motionOK) {
// document split manipulations
}
PostCSS का इस्तेमाल करके, Nesting Draft 1 से @nest
सिंटैक्स को चालू करके, इसी वैल्यू की जांच की जा सकती है. इससे मुझे पैरंट और बच्चों के लिए, ऐनिमेशन और उसके स्टाइल से जुड़ी सभी ज़रूरी शर्तों को एक ही जगह पर सेव करने में मदद मिलती है:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
PostCSS कस्टम प्रॉपर्टी और JavaScript बूलियन की मदद से, हम इफ़ेक्ट को शर्त के हिसाब से अपग्रेड करने के लिए तैयार हैं. अब हम अगले सेक्शन पर चलते हैं. इसमें मैंने स्ट्रिंग को एलिमेंट में बदलने के लिए, JavaScript के बारे में बताया है.
टेक्स्ट को हिस्सों में बांटना
सीएसएस या JS का इस्तेमाल करके, टेक्स्ट के अक्षरों, शब्दों, लाइनों वगैरह को अलग-अलग ऐनिमेट नहीं किया जा सकता. इस इफ़ेक्ट को पाने के लिए, हमें बॉक्स की ज़रूरत होती है. अगर हमें हर अक्षर को ऐनिमेट करना है, तो हर अक्षर को एक एलिमेंट होना चाहिए. अगर हमें हर शब्द को ऐनिमेट करना है, तो हर शब्द को एक एलिमेंट होना चाहिए.
- स्ट्रिंग को एलिमेंट में बांटने के लिए, JavaScript के यूटिलिटी फ़ंक्शन बनाना
- इन यूटिलिटी के इस्तेमाल को व्यवस्थित करना
अक्षरों को अलग-अलग करने वाला यूटिलिटी फ़ंक्शन
शुरुआत करने के लिए, एक ऐसा फ़ंक्शन इस्तेमाल करें जो किसी स्ट्रिंग को लेता है और उसके हर अक्षर को एक अरे में दिखाता है.
export const byLetter = text =>
[...text].map(span)
ES6 के स्प्रेड सिंटैक्स की मदद से, इस काम को आसानी से किया जा सका.
शब्दों को अलग-अलग करने वाला यूटिलिटी फ़ंक्शन
अक्षरों को अलग-अलग करने की तरह ही, यह फ़ंक्शन एक स्ट्रिंग लेता है और हर शब्द को एक अरे में दिखाता है.
export const byWord = text =>
text.split(' ').map(span)
JavaScript स्ट्रिंग पर मौजूद
split()
मेथड की मदद से, यह तय किया जा सकता है कि किन वर्णों को स्लाइस करना है.
मैंने एक खाली जगह छोड़ी है, जिससे पता चलता है कि शब्दों को अलग किया गया है.
बॉक्स बनाने का यूटिलिटी फ़ंक्शन
इस इफ़ेक्ट के लिए, हर अक्षर के लिए बॉक्स की ज़रूरत होती है. साथ ही, हमें इन फ़ंक्शन में दिखता है कि map()
को span()
फ़ंक्शन के साथ कॉल किया जा रहा है. यहां span()
फ़ंक्शन दिया गया है.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
यह ध्यान रखना ज़रूरी है कि --index
नाम की कस्टम प्रॉपर्टी को ऐरे की पोज़िशन के साथ सेट किया जा रहा है. अक्षर के ऐनिमेशन के लिए बॉक्स होना अच्छी बात है, लेकिन सीएसएस में इस्तेमाल करने के लिए इंडेक्स का होना एक छोटा बदलाव है, लेकिन इसका असर बहुत ज़्यादा होता है.
इस बड़े बदलाव में सबसे अहम बात यह है कि
स्टैगरिंग.
हम --index
का इस्तेमाल, ऐनिमेशन को ऑफ़सेट करने के लिए कर पाएंगे, ताकि उन्हें एक साथ न दिखाया जाए.
यूटिलिटी के बारे में निष्कर्ष
splitting.js
मॉड्यूल पूरा होने पर:
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
export const byLetter = text =>
[...text].map(span)
export const byWord = text =>
text.split(' ').map(span)
इसके बाद, इन byLetter()
और byWord()
फ़ंक्शन को इंपोर्ट करके इस्तेमाल किया जाता है.
स्प्लिट ऑर्केस्ट्रेशन
स्प्लिट करने की सुविधाएं इस्तेमाल करने के लिए तैयार हैं. इसलिए, इन सभी को एक साथ इस्तेमाल करने का मतलब है:
- यह पता लगाना कि किन एलिमेंट को स्प्लिट करना है
- उन्हें स्प्लिट करना और टेक्स्ट को एचटीएमएल से बदलना
इसके बाद, सीएसएस कंट्रोल अपने हाथ में ले लेती है और एलिमेंट / बॉक्स को ऐनिमेट करती है.
तत्वों को ढूंढना
मैंने एट्रिब्यूट और वैल्यू का इस्तेमाल करके, पसंद के मुताबिक ऐनिमेशन और टेक्स्ट को अलग-अलग हिस्सों में बांटने के तरीके के बारे में जानकारी सेव की है. मुझे एचटीएमएल में इन डिक्लेरेटिव विकल्पों को शामिल करना अच्छा लगा. split-by
एट्रिब्यूट का इस्तेमाल JavaScript से किया जाता है, ताकि एलिमेंट ढूंढे जा सकें. साथ ही, अक्षरों या शब्दों के लिए बॉक्स बनाए जा सकें. सीएसएस में, letter-animation
या word-animation
एट्रिब्यूट का इस्तेमाल किया जाता है. इससे एलिमेंट के चाइल्ड को टारगेट किया जाता है. साथ ही, ट्रांसफ़ॉर्म और ऐनिमेशन लागू किए जाते हैं.
यहां एचटीएमएल का एक सैंपल दिया गया है, जिसमें दोनों एट्रिब्यूट दिखाए गए हैं:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
JavaScript से एलिमेंट ढूंढना
मैंने एट्रिब्यूट की मौजूदगी के लिए सीएसएस सिलेक्टर सिंटैक्स का इस्तेमाल किया है, ताकि उन एलिमेंट की सूची इकट्ठा की जा सके जिनके टेक्स्ट को अलग-अलग करना है:
const splitTargets = document.querySelectorAll('[split-by]')
सीएसएस से एलिमेंट ढूंढना
मैंने सीएसएस में एट्रिब्यूट प्रेज़ेंस सिलेक्टर का इस्तेमाल किया है, ताकि सभी लेटर ऐनिमेशन को एक जैसी स्टाइल दी जा सके. बाद में, हम एट्रिब्यूट की वैल्यू का इस्तेमाल करके, ज़्यादा खास स्टाइल जोड़ेंगे, ताकि असर डाला जा सके.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
टेक्स्ट को उसी जगह पर बांटना
JavaScript में हमें जितने भी स्प्लिट टारगेट मिलेंगे, हम उनके टेक्स्ट को एट्रिब्यूट की वैल्यू के आधार पर स्प्लिट करेंगे. साथ ही, हर स्ट्रिंग को <span>
से मैप करेंगे. इसके बाद, हम एलिमेंट के टेक्स्ट को बनाए गए बॉक्स से बदल सकते हैं:
splitTargets.forEach(node => {
const type = node.getAttribute('split-by')
let nodes = null
if (type === 'letter') {
nodes = byLetter(node.innerText)
}
else if (type === 'word') {
nodes = byWord(node.innerText)
}
if (nodes) {
node.firstChild.replaceWith(...nodes)
}
})
ऑर्केस्ट्रेशन के बारे में खास जानकारी
index.js
में पूरा हुआ:
import {byLetter, byWord} from './splitting.js'
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
if (motionOK) {
const splitTargets = document.querySelectorAll('[split-by]')
splitTargets.forEach(node => {
const type = node.getAttribute('split-by')
let nodes = null
if (type === 'letter')
nodes = byLetter(node.innerText)
else if (type === 'word')
nodes = byWord(node.innerText)
if (nodes)
node.firstChild.replaceWith(...nodes)
})
}
JavaScript को इस तरह से अंग्रेज़ी में पढ़ा जा सकता है:
- कुछ हेल्पर यूटिलिटी फ़ंक्शन इंपोर्ट करें.
- देखें कि इस उपयोगकर्ता के लिए मोशन ठीक है या नहीं. अगर ऐसा नहीं है, तो कुछ न करें.
- हर उस एलिमेंट के लिए जिसे स्प्लिट करना है.
- उन्हें इस आधार पर बांटें कि उन्हें कैसे बांटा जाना चाहिए.
- टेक्स्ट को एलिमेंट से बदलें.
ऐनिमेशन और ट्रांज़िशन को अलग-अलग करना
दस्तावेज़ को ऊपर दिए गए तरीके से स्प्लिट करने पर, सीएसएस या JavaScript की मदद से कई तरह के ऐनिमेशन और इफ़ेक्ट इस्तेमाल किए जा सकते हैं. इस लेख के सबसे नीचे कुछ लिंक दिए गए हैं. इनसे आपको स्प्लिट टेस्ट करने के लिए आइडिया मिल सकते हैं.
अब इस सुविधा का इस्तेमाल करके, अपनी क्रिएटिविटी दिखाएं! मैं सीएसएस की मदद से बनाए गए चार ऐनिमेशन और ट्रांज़िशन शेयर करूंगी. 🤓
अक्षरों को अलग-अलग करना
स्प्लिट लेटर इफ़ेक्ट के लिए, मुझे यह सीएसएस काम की लगी. मैंने सभी ट्रांज़िशन और एनिमेशन को मोशन मीडिया क्वेरी के पीछे रखा है. इसके बाद, हर नए चाइल्ड लेटर span
को डिसप्ले प्रॉपर्टी दी है. साथ ही, सफ़ेद जगहों के लिए स्टाइल दी है:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
सफ़ेद जगहों की स्टाइल ज़रूरी है, ताकि लेआउट इंजन सिर्फ़ स्पेस वाले स्पैन को छोटा न कर दे. अब स्टेटफ़ुल फ़ंक्शन के बारे में बात करते हैं.
अक्षरों को अलग-अलग करने के ट्रांज़िशन का उदाहरण
इस उदाहरण में, टेक्स्ट को दो हिस्सों में बांटने वाले इफ़ेक्ट के लिए सीएसएस ट्रांज़िशन का इस्तेमाल किया गया है. ट्रांज़िशन के लिए, हमें इंजन को ऐनिमेट करने के लिए स्थितियों की ज़रूरत होती है. मैंने तीन स्थितियां चुनी हैं: कोई होवर नहीं, वाक्य में होवर करना, और किसी अक्षर पर होवर करना.
जब उपयोगकर्ता वाक्य, यानी कंटेनर पर कर्सर घुमाता है, तो मैं सभी चाइल्ड को इस तरह से छोटा कर देता हूं जैसे उपयोगकर्ता ने उन्हें और दूर कर दिया हो. इसके बाद, जब उपयोगकर्ता किसी अक्षर पर कर्सर घुमाता है, तो मैं उसे आगे लाता हूं.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
स्प्लिट किए गए अक्षरों को ऐनिमेट करने का उदाहरण
इस उदाहरण में, हर अक्षर को लगातार ऐनिमेट करने के लिए, पहले से तय किए गए @keyframe
ऐनिमेशन का इस्तेमाल किया गया है. साथ ही, स्टैगर्ड इफ़ेक्ट बनाने के लिए, इनलाइन कस्टम प्रॉपर्टी इंडेक्स का इस्तेमाल किया गया है.
@media (--motionOK) {
[letter-animation="breath"] > span {
animation:
breath 1200ms ease
calc(var(--index) * 100 * 1ms)
infinite alternate;
}
}
@keyframes breath {
from {
animation-timing-function: ease-out;
}
to {
transform: translateY(-5px) scale(1.25);
text-shadow: 0 0 25px var(--glow-color);
animation-timing-function: ease-in-out;
}
}
शब्दों को अलग-अलग करना
इन उदाहरणों में, Flexbox ने मेरे लिए कंटेनर टाइप के तौर पर काम किया. साथ ही, इसने ch
यूनिट का इस्तेमाल करके, दो आइटम के बीच सही दूरी तय की.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
ट्रांज़िशन स्प्लिट शब्दों का उदाहरण
इस ट्रांज़िशन के उदाहरण में, मैंने फिर से होवर का इस्तेमाल किया है. इस इफ़ेक्ट में, होवर करने तक कॉन्टेंट छिपा रहता है. इसलिए, मैंने यह पक्का किया कि इंटरैक्शन और स्टाइल सिर्फ़ तब लागू हों, जब डिवाइस में होवर करने की सुविधा हो.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
स्प्लिट किए गए शब्दों को ऐनिमेट करने का उदाहरण
इस ऐनिमेशन के उदाहरण में, मैंने सीएसएस @keyframes
का इस्तेमाल करके, टेक्स्ट के सामान्य पैराग्राफ़ पर स्टैगर्ड इनफ़िनिट ऐनिमेशन बनाया है.
[word-animation="trampoline"] > span {
display: inline-block;
transform: translateY(100%);
animation:
trampoline 3s ease
calc(var(--index) * 150 * 1ms)
infinite alternate;
}
@keyframes trampoline {
0% {
transform: translateY(100%);
animation-timing-function: ease-out;
}
50% {
transform: translateY(0);
animation-timing-function: ease-in;
}
}
नतीजा
अब आपको पता चल गया है कि मैंने यह कैसे किया. अब आप इसे कैसे करेंगे?! 🙂
आइए, हम अपने तरीकों में विविधता लाएं और वेब पर काॅन्टेंट पोस्ट करने के सभी तरीके जानें. Codepen बनाएं या अपना डेमो होस्ट करें. इसके बाद, मुझे ट्वीट करके इसकी जानकारी दें. मैं इसे यहां दिए गए कम्यूनिटी रीमिक्स सेक्शन में जोड़ दूंगा.
स्रोत
ज़्यादा डेमो और प्रेरणा
कम्यूनिटी रीमिक्स
<text-hover>
CodeSandbox पर gnehcwu का वेब कॉम्पोनेंट