स्प्लिट टेक्स्ट ऐनिमेशन बनाना

इस वीडियो में, स्प्लिट लेटर और वर्ड ऐनिमेशन बनाने के बारे में बुनियादी जानकारी दी गई है.

इस पोस्ट में, हम वेब के लिए स्प्लिट टेक्स्ट ऐनिमेशन और इंटरैक्शन को हल करने के तरीकों के बारे में बताएंगे. ये तरीके आसान हैं, ऐक्सेस किए जा सकते हैं, और सभी ब्राउज़र पर काम करते हैं. डेमो आज़माएं.

डेमो

अगर आपको वीडियो देखना पसंद है, तो इस पोस्ट का YouTube वर्शन यहां देखें:

खास जानकारी

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

यहां वर्कफ़्लो और नतीजों के बारे में खास जानकारी दी गई है:

  1. सीएसएस और JS के लिए, कम मोशन वाले कंडिशनल वैरिएबल तैयार करें.
  2. JavaScript में टेक्स्ट को स्प्लिट करने वाली यूटिलिटी तैयार करें.
  3. पेज लोड होने पर, शर्तों और यूटिलिटी को ऑर्केस्ट्रेट करना.
  4. Write CSS transitions and animations for letters and words (the rad part!).

यहां उन कंडीशनल नतीजों की झलक दी गई है जिन्हें हमें पाना है:

Chrome DevTools का स्क्रीनशॉट, जिसमें एलिमेंट पैनल खुला है और कम मोशन को 'कम करें' पर सेट किया गया है. साथ ही, h1 को बिना स्प्लिट किए दिखाया गया है
उपयोगकर्ता को कम मोशन पसंद है: टेक्स्ट को पढ़ा जा सकता है / उसे अलग नहीं किया गया है

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

Chrome DevTools का स्क्रीनशॉट, जिसमें एलिमेंट पैनल खुला है और कम मोशन को 'कम करें' पर सेट किया गया है. साथ ही, h1 को बिना स्प्लिट किए दिखाया गया है
उपयोगकर्ता को मोशन से कोई समस्या नहीं है; टेक्स्ट को कई <span> एलिमेंट में बांटा गया है

मोशन कंडीशनल तैयार किए जा रहे हैं

इस प्रोजेक्ट में, सीएसएस और JavaScript से @media (prefers-reduced-motion: reduce) मीडिया क्वेरी का इस्तेमाल किया जाएगा. यह क्वेरी आसानी से उपलब्ध है. यह मीडिया क्वेरी, टेक्स्ट को बांटने या न बांटने का फ़ैसला लेने के लिए हमारी मुख्य शर्त है. सीएसएस मीडिया क्वेरी का इस्तेमाल, ट्रांज़िशन और ऐनिमेशन को रोकने के लिए किया जाएगा. वहीं, JavaScript मीडिया क्वेरी का इस्तेमाल, एचटीएमएल में बदलाव करने से रोकने के लिए किया जाएगा.

सीएसएस कंडीशनल तैयार करना

मैंने मीडिया क्वेरी लेवल 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 का इस्तेमाल करके, नेस्टिंग ड्राफ़्ट 1 से @nest सिंटैक्स को चालू करके, उसी वैल्यू की जांच कर सकता हूं. इससे मुझे ऐनिमेशन और पैरंट और चाइल्ड के लिए स्टाइल की ज़रूरी शर्तों के बारे में सारा लॉजिक एक ही जगह पर सेव करने की सुविधा मिलती है:

letter-animation {
  @media (--motionOK) {
    /* animation styles */
  }
}

PostCSS कस्टम प्रॉपर्टी और JavaScript बूलियन की मदद से, हम शर्त के हिसाब से इफ़ेक्ट को अपग्रेड करने के लिए तैयार हैं. इसके बाद, हम अगले सेक्शन पर चलते हैं. इसमें हम स्ट्रिंग को एलिमेंट में बदलने के लिए, JavaScript को अलग-अलग हिस्सों में बांटते हैं.

टेक्स्ट को बांटना

टेक्स्ट के अक्षरों, शब्दों, लाइनों वगैरह को सीएसएस या जेएस की मदद से अलग-अलग ऐनिमेट नहीं किया जा सकता. इस इफ़ेक्ट को पाने के लिए, हमें बॉक्स की ज़रूरत होगी. अगर हमें हर अक्षर को ऐनिमेट करना है, तो हर अक्षर को एक एलिमेंट होना चाहिए. अगर हमें हर शब्द को ऐनिमेट करना है, तो हर शब्द को एक एलिमेंट होना चाहिए.

  1. स्ट्रिंग को एलिमेंट में बांटने के लिए, JavaScript यूटिलिटी फ़ंक्शन बनाना
  2. इन यूटिलिटी के इस्तेमाल को मैनेज करना

अक्षरों को अलग-अलग करने वाला उपयोगिता फ़ंक्शन

शुरुआत करने के लिए, एक ऐसा फ़ंक्शन इस्तेमाल करें जो स्ट्रिंग लेता है और हर अक्षर को एक कलेक्शन में दिखाता है.

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() फ़ंक्शन को इंपोर्ट करके इस्तेमाल करें.

स्प्लिट ऑर्केस्ट्रेशन

स्प्लिटिंग यूटिलिटी का इस्तेमाल करने के लिए, सभी चीज़ों को एक साथ रखने का मतलब है:

  1. यह तय करना कि किन एलिमेंट को स्प्लिट करना है
  2. स्प्लिट करना और टेक्स्ट को एचटीएमएल से बदलना

इसके बाद, सीएसएस एलिमेंट / बॉक्स को ऐनिमेट करेगी.

एलिमेंट ढूंढना

मैंने अपनी पसंद के ऐनिमेशन और टेक्स्ट को बांटने के तरीके की जानकारी सेव करने के लिए, एट्रिब्यूट और वैल्यू का इस्तेमाल किया. मुझे एचटीएमएल में इन डिक्लेरेटिव विकल्पों को जोड़ना पसंद आया. 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 को इस तरह पढ़ा जा सकता है:

  1. कुछ हेल्पर यूटिलिटी फ़ंक्शन इंपोर्ट करें.
  2. देखें कि इस उपयोगकर्ता के लिए मोशन ठीक है या नहीं. अगर नहीं, तो कुछ न करें.
  3. हर उस एलिमेंट के लिए जिसे आपको बांटना है.
    1. उन्हें इस आधार पर बांटें कि वे किस तरह से बांटना चाहते हैं.
    2. टेक्स्ट को एलिमेंट से बदलें.

ऐनिमेशन और ट्रांज़िशन को स्प्लिट करना

ऊपर दिए गए स्प्लिटिंग डॉक्यूमेंट मैनिपुलेशन ने सीएसएस या 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;
  }
}

शब्दों को अलग-अलग करना

इन उदाहरणों में, फ़्लेक्सबॉक्स ने मेरे लिए कंटेनर टाइप के तौर पर काम किया. साथ ही, गैप की लंबाई के लिए ch यूनिट का इस्तेमाल किया.

word-animation {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 1ch;
}
शब्दों के बीच का गैप दिखाने वाले Flexbox devtools

ट्रांज़िशन स्प्लिट वर्ड का उदाहरण

इस ट्रांज़िशन के उदाहरण में, मैं फिर से होवर का इस्तेमाल करता हूं. यह इफ़ेक्ट, कॉन्टेंट को तब तक छिपाकर रखता है, जब तक उस पर कर्सर न घुमाया जाए. इसलिए, मैंने यह पक्का किया कि इंटरैक्शन और स्टाइल सिर्फ़ तब लागू हों, जब डिवाइस में कर्सर घुमाने की सुविधा हो.

@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 बनाएं या अपना डेमो होस्ट करें. इसके बाद, मुझे ट्वीट करें. मैं इसे नीचे दिए गए कम्यूनिटी रीमिक्स सेक्शन में जोड़ दूंगा.

स्रोत

ज़्यादा डेमो और प्रेरणा

कम्यूनिटी रीमिक्स