सेटिंग कॉम्पोनेंट बनाना

स्लाइडर और चेकबॉक्स के सेटिंग कॉम्पोनेंट को बनाने के तरीके की बुनियादी जानकारी.

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

डेमो

अगर आपको वीडियो देखना ज़्यादा पसंद है या आपको इस सुविधा के यूज़र इंटरफ़ेस (यूआई) और यूज़र अनुभव (यूएक्स) की झलक चाहिए, तो YouTube पर इसका छोटा वॉकथ्रू देखें:

खास जानकारी

मैंने इस कॉम्पोनेंट के पहलुओं को इन सेक्शन में बांटा है:

  1. लेआउट
  2. रंग
  3. कस्टम रेंज का इनपुट
  4. कस्टम चेकबॉक्स इनपुट
  5. सुलभता से जुड़ी बातें
  6. JavaScript

लेआउट

यह सभी सीएसएस ग्रिड वाला पहला जीयूआई चैलेंज डेमो है! यहां हर ग्रिड को ग्रिड के लिए Chrome DevTools की मदद से हाइलाइट किया गया है:

रंगीन आउटलाइन और गैप स्पेसिंग ओवरले, जो सेटिंग लेआउट बनाने वाले सभी बॉक्स को दिखाने में मदद करते हैं

सिर्फ़ गैप के लिए

सबसे सामान्य लेआउट:

foo {
  display: grid;
  gap: var(--something);
}

हम इस लेआउट को "सिर्फ़ गैप के लिए" कहते हैं, क्योंकि यह ब्लॉक के बीच गैप जोड़ने के लिए सिर्फ़ ग्रिड का इस्तेमाल करता है.

पांच लेआउट इस रणनीति का इस्तेमाल करते हैं. यहां उन सभी को दिखाया गया है:

वर्टिकल ग्रिड लेआउट, जिनमें आउटलाइन के साथ हाइलाइट किया गया है और अंतराल भरे गए हैं

fieldset एलिमेंट में हर इनपुट ग्रुप (.fieldset-item) होता है. यह एलिमेंट, एलिमेंट के बीच में हेयरलाइन बॉर्डर बनाने के लिए gap: 1px का इस्तेमाल करता है. बॉर्डर के लिए कोई मुश्किल समाधान नहीं!

भरा हुआ गैप
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
बॉर्डर ट्रिक
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

ग्रिड को अपने-आप रैप होना

सबसे जटिल लेआउट, मैक्रो लेआउट था. यह <main> और <form> के बीच का लॉजिकल लेआउट सिस्टम था.

रैप किए गए कॉन्टेंट को बीच में रखना

फ़्लेक्सबॉक्स और ग्रिड, दोनों में align-items या align-content की सुविधाएं मिलती हैं. साथ ही, रैपिंग एलिमेंट के साथ काम करते समय, content लेआउट अलाइनमेंट, चाइल्ड एलिमेंट के बीच एक ग्रुप के तौर पर जगह बांटेगा.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

मुख्य एलिमेंट में place-content: center अलाइनमेंट के शॉर्टहैंड का इस्तेमाल किया गया है, ताकि बच्चे एक और दो कॉलम वाले लेआउट, दोनों में वर्टिकल और हॉरिज़ॉन्टल तौर पर सेंटर में हों.

ऊपर दिए गए वीडियो में देखें कि रैपिंग होने के बावजूद, "कॉन्टेंट" बीच में कैसे बना रहता है.

अपने-आप फ़िट होने वाले कम से कम और ज़्यादा से ज़्यादा साइज़ को दोहराना

<form>, हर सेक्शन के लिए अडैप्टिव ग्रिड लेआउट का इस्तेमाल करता है. यह लेआउट, उपलब्ध जगह के हिसाब से एक से दो कॉलम में स्विच हो जाता है.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

इस ग्रिड में row-gap (--space-xl) के लिए, column-gap (--space-xxl) से अलग वैल्यू है, ताकि रिस्पॉन्सिव लेआउट पर कस्टम टच दिया जा सके. जब कॉलम स्टैक होते हैं, तो हमें एक बड़ा गैप चाहिए. हालांकि, यह गैप उतना बड़ा नहीं होना चाहिए जितना कि वाइड स्क्रीन पर होता है.

grid-template-columns प्रॉपर्टी, तीन सीएसएस फ़ंक्शन का इस्तेमाल करती है: repeat(), minmax(), और min(). Una Kravets ने इस बारे में एक शानदार लेआउट ब्लॉग पोस्ट लिखी है. इसमें इसे RAM कहा गया है.

Una के लेआउट की तुलना में, हमारे लेआउट में तीन खास चीज़ें जोड़ी गई हैं:

  • हम एक अतिरिक्त min() फ़ंक्शन पास करते हैं.
  • हम align-items: flex-start का इस्तेमाल करते हैं.
  • max-width: 89vw स्टाइल है.

अतिरिक्त min() फ़ंक्शन के बारे में, एवन मिंटो ने अपने ब्लॉग पर minmax() और min() के साथ, रिस्पॉन्सिव सीएसएस ग्रिड पोस्ट में अच्छी तरह से बताया है. हमारा सुझाव है कि आप इसे पढ़ें. flex-start अलाइनमेंट में बदलाव करने का मकसद, डिफ़ॉल्ट तौर पर स्ट्रेच होने की वजह से होने वाले असर को हटाना है. इससे इस लेआउट के बच्चों की ऊंचाई एक जैसी नहीं होनी चाहिए. उनकी ऊंचाई, नैचुरल और अपने-आप तय होनी चाहिए. YouTube वीडियो में, अलाइनमेंट जोड़ने के बारे में कम शब्दों में बताया गया है.

max-width: 89vw के बारे में इस पोस्ट में थोड़ा बताया गया है. आइए, हम आपको स्टाइल के साथ और उसके बिना लेआउट दिखाते हैं:

क्या हो रहा है? max-width की वैल्यू देने पर, auto-fit लेआउट एल्गोरिदम के लिए कॉन्टेक्स्ट, साइज़ या सटीक साइज़ दिया जाता है. इससे यह पता चलता है कि स्पेस में कितनी बार दोहराया जा सकता है. ऐसा लगता है कि स्पेस "पूरी चौड़ाई" में है. हालांकि, सीएसएस ग्रिड स्पेसिफ़िकेशन के मुताबिक, कोई तय साइज़ या ज़्यादा से ज़्यादा साइज़ दिया जाना चाहिए. मैंने मैक्स-साइज़ दिया है.

तो, 89vw ही क्यों? क्योंकि मेरे लेआउट के लिए "यह काम किया". मैं और Chrome के कुछ अन्य लोग इस बात की जांच कर रहे हैं कि 100vw जैसी सही वैल्यू क्यों काम नहीं कर रही है. साथ ही, यह भी पता लगा रहे हैं कि क्या यह वाकई में कोई गड़बड़ी है.

स्पेसिंग

इस लेआउट का ज़्यादातर हिस्सा, स्पेसिंग के सीमित पैलेट से मिलता-जुलता है.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

इन फ़्लो का इस्तेमाल, ग्रिड, सीएसएस @nest, और @media के लेवल 5 सिंटैक्स के साथ बहुत अच्छा होता है. यहां एक उदाहरण दिया गया है, जिसमें स्टाइल का पूरा <main> लेआउट सेट है.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

बीच में कॉन्टेंट वाला ग्रिड, जो डिफ़ॉल्ट रूप से मोबाइल की तरह थोड़ा पैड किया गया हो. हालांकि, विज़ुअल के लिए ज़्यादा जगह उपलब्ध होने पर, पैडिंग बढ़ाकर उसे बड़ा किया जाता है. 2021 सीएसएस काफ़ी अच्छी लग रही है!

क्या आपको "सिर्फ़ गैप के लिए" वाला पुराना लेआउट याद है? इस कॉम्पोनेंट में ये एलिमेंट कैसा दिखते हैं, इसका ज़्यादा बेहतर वर्शन यहां दिया गया है:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

रंग

रंग का सही तरीके से इस्तेमाल करके, इस डिज़ाइन को ज़्यादा बेहतर बनाया गया है. मैं ऐसा करता/करती हूं:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

मैं अपने प्लैटफ़ॉर्म और टेक्स्ट के रंगों को संख्याओं के बजाय, surface-dark और surface-darker जैसे नामों से नामित करता हूं. ऐसा इसलिए, क्योंकि मीडिया क्वेरी में, मुझे उन्हें फ़्लिप करना होगा और हल्के और गहरे रंग का कोई मतलब नहीं होगा.

मैं उन्हें इस तरह की प्राथमिकता वाली मीडिया क्वेरी में फ़्लिप करता/करती हूं:

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

रंग के सिंटैक्स की जानकारी देने से पहले, पूरी तस्वीर और रणनीति के बारे में थोड़ी जानकारी देना ज़रूरी है. हालांकि, मैंने थोड़ा आगे बढ़ लिया है, इसलिए, मुझे थोड़ा पीछे लौटना होगा.

LCH?

कलर थ्योरी के बारे में ज़्यादा जानकारी दिए बिना, LCH एक ऐसा सिंटैक्स है जो इंसानों के हिसाब से बनाया गया है. इससे हमें यह पता चलता है कि हम रंग को कैसे देखते हैं, न कि हम रंग को गणित के हिसाब से (जैसे कि 255) कैसे मेज़र करते हैं. इससे, इस भाषा को लिखना ज़्यादा आसान हो जाता है. साथ ही, अन्य लोग भी इन बदलावों के हिसाब से काम कर पाएंगे.

pod.link/csspodcast वेबपेज का स्क्रीनशॉट, जिसमें Color 2: Perception एपिसोड को खोला गया है
CSS Podcast पर, पर्सीव्ड कलर (और अन्य चीज़ों) के बारे में जानें

आज के इस डेमो में, सिंटैक्स और उन वैल्यू पर फ़ोकस करते हैं जिन्हें हल्के और गहरे रंग में बदला जा रहा है. आइए, एक सतह और एक टेक्स्ट कलर पर नज़र डालते हैं:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) का मतलब है 10% लाइटनेस, 0 क्रोमा, और 0 ह्यू: बहुत गहरे रंग का स्लेटी रंग. इसके बाद, लाइट मोड के लिए मीडिया क्वेरी में, लाइटनेस को --surface1: lch(90 0 0); के साथ 90% पर फ़्लिप किया जाता है. यही इस रणनीति का मकसद है. सबसे पहले, दो थीम के बीच सिर्फ़ हल्केपन में बदलाव करें. साथ ही, डिज़ाइन के लिए ज़रूरी कंट्रास्ट रेशियो या सुलभता बनाए रखने के लिए ज़रूरी कंट्रास्ट रेशियो बनाए रखें.

यहां lch() का फ़ायदा यह है कि लाइटनेस, लोगों के हिसाब से होती है. इसलिए, इसमें % बदलाव करने पर हमें अच्छा महसूस होता है. यह बदलाव, % के हिसाब से और लगातार दिखेगा. उदाहरण के लिए, hsl() इतना भरोसेमंद नहीं है.

अगर आपको रंगों के स्पेस और lch() के बारे में ज़्यादा जानना है, तो यहां जाएं. यह सुविधा जल्द ही उपलब्ध होगी!

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

Lea Verou

कलर-स्कीम के साथ अडैप्टिव फ़ॉर्म कंट्रोल

कई ब्राउज़र में, डार्क थीम के कंट्रोल होते हैं. फ़िलहाल, Safari और Chromium में ये कंट्रोल मौजूद हैं. हालांकि, आपको सीएसएस या एचटीएमएल में यह बताना होगा कि आपके डिज़ाइन में इनका इस्तेमाल किया गया है.

ऊपर, DevTools के स्टाइल पैनल से प्रॉपर्टी के असर को दिखाया गया है. डेमो में एचटीएमएल टैग का इस्तेमाल किया गया है. मेरी राय में, आम तौर पर यह बेहतर होता है:

<meta name="color-scheme" content="dark light">

इस बारे में पूरी जानकारी पाने के लिए, थॉमस स्टाइनर के इस color-scheme लेख को पढ़ें. डार्क चेकबॉक्स इनपुट के अलावा, आपको और भी बहुत कुछ मिल सकता है!

सीएसएस accent-color

फ़ॉर्म एलिमेंट पर accent-color के लिए, हाल ही में कोई गतिविधि हुई है. यह एक सीएसएस स्टाइल है, जो ब्राउज़र के इनपुट एलिमेंट में इस्तेमाल किए गए टिन्ट कलर को बदल सकती है. इसके बारे में ज़्यादा जानने के लिए, GitHub पर यहां जाएं. मैंने इसे इस कॉम्पोनेंट के लिए अपनी स्टाइल में शामिल किया है. ब्राउज़र इस सुविधा के साथ काम करते हैं. इसलिए, मेरे चेकबॉक्स, गुलाबी और बैंगनी रंग के पॉप के साथ थीम के मुताबिक दिखेंगे.

input[type="checkbox"] {
  accent-color: var(--brand);
}

Linux पर Chromium के गुलाबी चेकबॉक्स का स्क्रीनशॉट

फ़िक्स किए गए ग्रेडिएंट और फ़ोकस-इन के साथ कलर पॉप

रंग का इस्तेमाल कम करने पर, वह सबसे ज़्यादा असरदार होता है. मुझे रंगों का इस्तेमाल, यूज़र इंटरफ़ेस (यूआई) के इंटरैक्शन के ज़रिए करना पसंद है.

ऊपर दिए गए वीडियो में यूज़र इंटरफ़ेस (यूआई) के फ़ीडबैक और इंटरैक्शन की कई लेयर हैं. इनकी मदद से, इंटरैक्शन को ज़्यादा दिलचस्प बनाया जा सकता है. इसके लिए:

  • कॉन्टेक्स्ट को हाइलाइट करना.
  • वैल्यू की रेंज में "कितना फ़ुल" है, इसकी जानकारी देने वाला यूज़र इंटरफ़ेस (यूआई) फ़ीडबैक.
  • यूज़र इंटरफ़ेस (यूआई) से यह फ़ीडबैक देना कि कोई फ़ील्ड इनपुट स्वीकार कर रहा है.

किसी एलिमेंट के साथ इंटरैक्ट करने पर सुझाव देने के लिए, सीएसएस अलग-अलग एलिमेंट के दिखने का तरीका बदलने के लिए, :focus-within सूडो क्लास का इस्तेमाल कर रही है. आइए, .fieldset-item के बारे में ज़्यादा जानें, यह बहुत दिलचस्प है:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

जब इस एलिमेंट के किसी चाइल्ड एलिमेंट पर फ़ोकस-इन होता है, तो:

  1. .fieldset-item बैकग्राउंड को ज़्यादा कंट्रास्ट वाला सरफ़ेस कलर असाइन किया गया है.
  2. नेस्ट किए गए svg को ज़्यादा कंट्रास्ट के लिए सफ़ेद रंग से भरा गया है.
  3. नेस्ट किया गया <picture> clip-path, पूरे सर्कल में बड़ा हो जाता है और बैकग्राउंड में चमकदार फ़िक्स्ड ग्रेडिएंट भर जाता है.

पसंद के मुताबिक बनाई गई सीमा

नीचे दिए गए एचटीएमएल इनपुट एलिमेंट की मदद से, हम आपको दिखाएंगे कि हमने इसकी दिखने की क्वालिटी को कैसे अपनी पसंद के मुताबिक बनाया:

<input type="range">

इस एलिमेंट के तीन हिस्से हैं, जिन्हें हमें पसंद के मुताबिक बनाना है:

  1. रेंज एलिमेंट / कंटेनर
  2. ट्रैक करना
  3. Thumb

रेंज एलिमेंट की स्टाइल

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

सीएसएस की शुरुआती कुछ लाइनें, स्टाइल के कस्टम हिस्से होती हैं. हमें उम्मीद है कि उन्हें साफ़ तौर पर लेबल करने से आपको मदद मिलेगी. बाकी स्टाइल ज़्यादातर रीसेट स्टाइल होती हैं, ताकि कॉम्पोनेंट के मुश्किल हिस्सों को बनाने के लिए एक जैसा फ़ाउंडेशन दिया जा सके.

ट्रैक स्टाइल

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

इसके लिए, फ़ील्ड के रंग को "दिखाया" जाना चाहिए. ऐसा करने के लिए, सबसे ऊपर हार्ड स्टॉप ग्रेडिएंट का इस्तेमाल किया जाता है. ग्रेडिएंट, भरने के प्रतिशत तक पारदर्शी होता है. इसके बाद, वह ट्रैक के उस हिस्से के रंग का इस्तेमाल करता है जिसे नहीं भरा गया है. उस खाली जगह के पीछे, पूरी चौड़ाई वाला रंग है, जो पारदर्शिता के ज़रिए दिखने का इंतज़ार कर रहा है.

ट्रैक को भरने का स्टाइल

मेरे डिज़ाइन में, भरने के स्टाइल को बनाए रखने के लिए JavaScript की ज़रूरत है. सिर्फ़ सीएसएस वाली रणनीतियां हैं, लेकिन उनके लिए ज़रूरी है कि थंबनेल एलिमेंट की ऊंचाई, ट्रैक की ऊंचाई के बराबर हो. मुझे इन सीमाओं के अंदर कोई समाधान नहीं मिला.

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

मुझे लगता है कि इससे विज़ुअल को बेहतर बनाया जा सकता है. स्लाइडर, JavaScript के बिना भी बेहतर तरीके से काम करता है. --track-fill प्रॉपर्टी की ज़रूरत नहीं है. अगर यह मौजूद नहीं है, तो इसमें भरने का स्टाइल नहीं होगा. अगर JavaScript उपलब्ध है, तो उपयोगकर्ता के किसी भी बदलाव को देखते हुए, कस्टम प्रॉपर्टी को पॉप्युलेट करें. साथ ही, कस्टम प्रॉपर्टी को वैल्यू के साथ सिंक करें.

ऐना ट्यूडर की लिखी CSS-Tricks पर यह एक बेहतरीन पोस्ट है. इसमें ट्रैक फ़िल के लिए, सिर्फ़ सीएसएस का इस्तेमाल करके समाधान दिखाया गया है. मुझे यह range एलिमेंट भी काफ़ी प्रेरणादायक लगा.

थंब स्टाइल

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

इनमें से ज़्यादातर स्टाइल, अच्छा सर्कल बनाने के लिए हैं. यहां आपको फिर से बैकग्राउंड ग्रेडिएंट दिखेगा, जो थंबनेल, ट्रैक, और उनसे जुड़े एसवीजी एलिमेंट के डाइनैमिक रंगों को एक जैसा बनाता है. मैंने इंटरैक्शन के लिए स्टाइल को अलग-अलग किया है, ताकि हॉवर हाइलाइट के लिए इस्तेमाल की जा रही box-shadow तकनीक को अलग किया जा सके:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

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

अगर चेकबॉक्स पर हाइलाइट करने का तरीका इतना आसान होता…

अलग-अलग ब्राउज़र के लिए सिलेक्टर

मुझे पता चला कि अलग-अलग ब्राउज़र पर एक जैसी परफ़ॉर्मेंस पाने के लिए, मुझे इन -webkit- और -moz- सिलेक्टर की ज़रूरत है:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

कस्टम चेकबॉक्स

यहां दिए गए एचटीएमएल इनपुट एलिमेंट की मदद से, हम आपको दिखाएंगे कि हमने इसकी दिखने की क्वालिटी को कैसे अपनी पसंद के मुताबिक बनाया:

<input type="checkbox">

इस एलिमेंट के तीन हिस्से हैं, जिन्हें हमें पसंद के मुताबिक बनाना है:

  1. चेकबॉक्स एलिमेंट
  2. इससे जुड़े लेबल
  3. हाइलाइट इफ़ेक्ट

चेकबॉक्स एलिमेंट

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

transform-style और position स्टाइल, ऐसे स्यूडो-एलिमेंट के लिए तैयार हैं जिसे हम हाइलाइट की स्टाइल तय करने के लिए बाद में पेश करेंगे. इसके अलावा, मेरे वीडियो में ज़्यादातर ऐसा कॉन्टेंट होता है जिसमें मेरे विचारों को थोड़ा अलग तरीके से दिखाया जाता है. मुझे कर्सर को पॉइंटर के तौर पर इस्तेमाल करना पसंद है. मुझे आउटलाइन ऑफ़सेट भी पसंद है. डिफ़ॉल्ट चेकबॉक्स बहुत छोटे हैं. अगर accent-color का इस्तेमाल किया जा सकता है, तो इन चेकबॉक्स को ब्रैंड कलर स्कीम में लाएं.

चेकबॉक्स लेबल

चेकबॉक्स के लिए लेबल देना दो वजहों से ज़रूरी है. पहला, "किसके लिए चालू या बंद करें?" का जवाब देने के लिए, यह बताना कि चेकबॉक्स की वैल्यू का इस्तेमाल किस लिए किया जाता है. दूसरा, यूज़र एक्सपीरियंस के लिए, वेब उपयोगकर्ताओं को उनके लेबल के ज़रिए चेकबॉक्स के साथ इंटरैक्ट करने की आदत हो गई है.

इनपुट
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
लेबल
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

अपने लेबल पर, for एट्रिब्यूट डालें, जो आईडी: <label for="text-notifications"> के हिसाब से चेकबॉक्स पर ले जाता हो. अपने चेकबॉक्स में, नाम और आईडी, दोनों को दो बार डालें, ताकि यह अलग-अलग टूल और टेक्नोलॉजी, जैसे कि माउस या स्क्रीन रीडर से मिल जाए: <input type="checkbox" id="text-notifications" name="text-notifications">. :hover, :active वगैरह, कनेक्शन के साथ मुफ़्त में मिलते हैं. इससे आपके फ़ॉर्म के साथ इंटरैक्ट करने के तरीकों की संख्या बढ़ जाती है.

चेकबॉक्स हाइलाइट करना

मुझे अपने इंटरफ़ेस को एक जैसा रखना है. स्लाइडर एलिमेंट में एक अच्छा Thumbnail हाइलाइट है, जिसे मुझे चेकबॉक्स के साथ इस्तेमाल करना है. थंबनेल में box-shadow और spread प्रॉपर्टी का इस्तेमाल करके, शेडो को बड़ा और छोटा किया जा सकता है. हालांकि, यह इफ़ेक्ट यहां काम नहीं करता, क्योंकि हमारे चेकबॉक्स स्क्वेयर हैं और ऐसे होने चाहिए.

मैंने सूडो एलिमेंट और बहुत सी मुश्किल सीएसएस का इस्तेमाल करके, वही विज़ुअल इफ़ेक्ट हासिल किया:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

सर्कल स्यूडो-एलिमेंट बनाना आसान है, लेकिन इसे उस एलिमेंट के पीछे रखना मुश्किल था जिससे इसे अटैच किया गया था. यहां इस समस्या को ठीक करने से पहले और बाद की इमेज दी गई है:

यह माइक्रो इंटरैक्शन है, लेकिन मेरे लिए विज़ुअल को एक जैसा बनाए रखना ज़रूरी है. ऐनिमेशन स्केलिंग की यह तकनीक, वही है जिसका इस्तेमाल हम दूसरी जगहों पर कर रहे हैं. हमने कस्टम प्रॉपर्टी को नई वैल्यू पर सेट किया है और मोशन सेटिंग के आधार पर, सीएसएस को ट्रांज़िशन करने दिया है. यहां मुख्य सुविधा translateZ(-1px) है. पैरंट एलिमेंट ने 3D स्पेस बनाया और इस स्यूडो-एलिमेंट चाइल्ड ने उसमें टैप किया. इसके लिए, उसने खुद को z-स्पेस में थोड़ा पीछे रखा.

सुलभता

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

एचटीएमएल एलिमेंट के विकल्प

<form>
<header>
<fieldset>
<picture>
<label>
<input>

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

एचटीएमएल एट्रिब्यूट

हम ऐसे एलिमेंट छिपा सकते हैं जिनकी स्क्रीन रीडर को ज़रूरत नहीं होती. उदाहरण के लिए, इस मामले में स्लाइडर के बगल में मौजूद आइकॉन:

<picture aria-hidden="true">

ऊपर दिए गए वीडियो में, Mac OS पर स्क्रीन रीडर के फ़्लो के बारे में बताया गया है. ध्यान दें कि इनपुट फ़ोकस, एक स्लाइडर से सीधे अगले स्लाइडर पर कैसे जाता है. ऐसा इसलिए है, क्योंकि हमने उस आइकॉन को छिपा दिया है जो अगले स्लाइडर पर जाने के रास्ते में हो सकता है. इस एट्रिब्यूट के बिना, उपयोगकर्ता को वीडियो को रोककर, सुनकर, उस इमेज को आगे बढ़ना होगा जिसे वह शायद न देख पाए.

एसवीजी में गणित के कई फ़ॉर्मूले होते हैं. आइए, माउस को घुमाने पर दिखने वाले टाइटल के लिए <title> एलिमेंट जोड़ें. साथ ही, गणित के फ़ॉर्मूले से क्या बन रहा है, इस बारे में ऐसी टिप्पणी जोड़ें जिसे कोई भी पढ़ सके:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

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

JavaScript

मैंने पहले ही बताया है कि JavaScript से ट्रैक के भरे हुए हिस्से का रंग कैसे मैनेज किया जा रहा था. इसलिए, अब <form> से जुड़े JavaScript को देखें:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

जब भी फ़ॉर्म से इंटरैक्ट किया जाता है और उसमें बदलाव किया जाता है, तो Console उस फ़ॉर्म को टेबल में ऑब्जेक्ट के तौर पर लॉग करता है. इससे, सर्वर पर सबमिट करने से पहले, फ़ॉर्म की आसानी से समीक्षा की जा सकती है.

console.table() के नतीजों का स्क्रीनशॉट, जिसमें फ़ॉर्म का डेटा टेबल में दिखाया गया है

नतीजा

अब आपको पता है कि मैंने इसे कैसे किया, तो आप इसे कैसे करेंगे?! इससे कॉम्पोनेंट आर्किटेक्चर को मज़ेदार बनाया जा सकता है! अपने पसंदीदा फ़्रेमवर्क में स्लॉट के साथ पहला वर्शन कौन बनाएगा? 🙂

आइए, अलग-अलग तरीकों का इस्तेमाल करके, वेब पर कॉन्टेंट बनाने के सभी तरीके जानें. कोई डेमो बनाएं और मुझे ट्वीट करें लिंक भेजें. हम इसे यहां दिए गए कम्यूनिटी रीमिक्स सेक्शन में जोड़ देंगे!

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

  • @tomayac ने चेकबॉक्स लेबल के लिए, कर्सर घुमाने पर दिखने वाले हिस्से के स्टाइल के बारे में बताया! इस वर्शन में, एलिमेंट: डेमो और सोर्स के बीच कोई होवर गैप नहीं है.