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

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

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

डेमो

अगर आपको वीडियो देखना ज़्यादा पसंद है या आपको इस सुविधा के यूज़र इंटरफ़ेस (यूआई) और यूज़र अनुभव (यूएक्स) की झलक चाहिए, तो 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() और कम से कम() के साथ इंट्रिंसली रिस्पॉन्सिव सीएसएस ग्रिड पोस्ट में अच्छी तरह से बताया है. मेरा सुझाव है कि आप इसे एक बार पढ़ लें. 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() के बारे में ज़्यादा जानना है, तो यहां जाएं. यह सुविधा जल्द ही उपलब्ध होगी!

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

ली वेरो

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

कई ब्राउज़र में, डार्क थीम के कंट्रोल होते हैं. फ़िलहाल, 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 ने चेकबॉक्स लेबल के लिए, कर्सर घुमाने पर दिखने वाले हिस्से के स्टाइल के बारे में बताया! इस वर्शन में, एलिमेंट: डेमो और सोर्स के बीच कोई होवर गैप नहीं है.