सामान्य सिबलिंग सेलेक्टर्स में महारत हासिल करना: फॉर्म के कस्टम एलिमेंट्स
() translation by (you can also view the original English article)
सामान्य सिबलिंग संयोजक (general sibling combinator) एक बहुत ही शक्तिशाली और कम प्रयोग किया जाने वाला सिलेक्टर है: ~
. आने वाले टुटोरिअल्स (tutorials) में मैं अलग अलग तरीको से ~
का प्रयोग कंपोनेंट्स (components) बनाने में करूंगा जो की दिखने में न सिर्फ आकर्षित होगा, पर कार्यात्मक और उपयोगी (functional and useful) भी होगा. यह टुटोरिअल form एलिमेंट्स को कवर करेगा; radio, checkbox, और सामान्य inputs.
हम बहुत कुछ सीखेंगे: CSS के आधुनिक सेलेक्टर्स, will-change
प्रॉपर्टी, SVG's की stroke
प्रॉपर्टीज, input के states, और बहुत कुछ!
इससे पहले की हम शुरू करें...
एक शीघ्र खंडन: यह CSS के इफेक्ट्स पुराने ब्राउज़र में काम शायद करें या शायद नहीं करें - मैंने इन्हे Chrome, Firefox, और Safari के नए संस्करणों में परिक्षण किया है.
मैं कोड लिखने की प्रक्रिया को तेज करने के लिए Haml (HTML का एक कम्पाइलर) और Sass (CSS का preprocessor) का प्रयोग करूँगा. Demos Haml का प्रयोग करेंगे जबकि कोई inline कोड नियमित HTML का प्रयोग करेंगे.
मैं vendor के prefix की बजाय गजब के AutoPrefixer का प्रयोग करूँगा. यदि आप CodePen का प्रयोग करते हैं तो, pen's की सेटिंग्स में जाएं, CSS पर क्लिक करें, और AutoPrefixer को सेलेक्ट करना सुनिश्चित करें.



Radio Inputs
हम form के बेहद ही सामान्य एलिमेंट्स में से एक के साथ शुरुआत करेंगे: radio input. इसकी दो मुख्य visual स्थितियां है (checked और unchecked) साथ ही साथ दो इन के बीच की स्थितियां हैं (hover और click/active - click नजर आने वाले checked की स्थिति के समान ही है).
SVG का Version
HTML को व्यवस्थित करना पहला कदम है. आप को एक मुख्य बाहर के कंटेनर की और दो चिल्ड्रन के साथ एक अंदर के कंटेनर की जरुरत है: एक div
जो की input तथा नजर आने वाले एलिमेंट्स और input के लिए label
को लिए हुए है. मैं बाहर के कंटेनर के लिए fieldset
को लेना पसंद करता हूँ. सुनिश्चित करें की input को वही ID दी हुई हो जो की label के for
एट्रिब्यूट की वैल्यू है.
1 |
<fieldset>
|
2 |
<div class="container"> |
3 |
<div class="svg"> |
4 |
<input id="radio-svg" type="radio" name="option"/> |
5 |
<div></div>
|
6 |
<svg viewBox="0 0 24 24"> |
7 |
<circle cx="12" cy="12" r="8"></circle> |
8 |
<circle cx="12" cy="12" r="8"></circle> |
9 |
</svg>
|
10 |
</div>
|
11 |
<label for="radio-svg">SVG</label> |
12 |
</div>
|
13 |
</fieldset>
|
अगला कदम होगा डिफ़ॉल्ट input को छुपाना, कुछ सामान्य सी visual स्टाइलिंग को जोड़े, और अतिरिक्त एलिमेंट्स को छिपाएं जो की सिर्फ तभी दिखेंगे जब radio input सेलेक्ट हो. इसके पीछे विचार है की input को अदृश्य बना दें, पर इसे दिखने वाले एलिमेंट के ऊपर रख दें, तो radio input पर क्लिक करने पर ऐसा दिखेगा की visual radio ऑप्शन पर क्लिक किया है. हम यह .svg
की position: relative
सेट कर के और input की position: absolute
करके कर सकते हैं, उसके बाद input को छुपा दें.
ध्यान दें: आप इसे अपने किसी भी तरह के चुनाव के अनुसार फॉर्मेट कर सकते हैं. मैंने एक सामान्य सा वृत (circle) लिया है जो की डिफ़ॉल्ट radio की नक़ल लगता है, सिर्फ इसके अलावा की यह समतल है.
हम Sass का प्रयोग करके कुछ color के variables को सेट करेंगे: एक जोड़ा भूरा (gray) रंग और चुने हुए radio के लिए एक चमकदार नीला (bright blue). हम एक $p
नाम के variable को भी अपने डिफ़ॉल्ट unit के लिए सेट करेंगे - 12px एक अच्छा नंबर होगा क्योंकि यह अलग अलग नंबर्स की एक विस्तृत श्रृंखला (wide range) (1, 2, 3, 4, 6) के साथ भाग करने लायक है.
मैं embed में main variable को सीधा रख दूंगा, पर अतिरिक्त स्टाइलिंग यहाँ मिलेगी या CodePen के पेज पर क्लिक करके, ऊपर दायीं ओर सेटिंग्स पर क्लिक करें, और अतिरिक्त CSS stylesheets देखने के लिए CSS टैब पर क्लिक करें.
हमने पहला वृत (circle) हल्के भूरे रंग का बनाया है और दूसरा चमकदार नीले रंग का, और उसके बाद दूसरे की सेटिंग transform: scale(0)
करके छुपा दिया. बाद में, हम वृत (circle) को एनीमेशन के साथ वापस लाएंगे, इसलिए scale को अभी सेट करना महत्वपुर्ण है.
सभी कुछ सेट करने के बाद, हमे हर स्थिति के लिए दिखने वाले style का निर्णय लेना होगा. उदाहरण के लिए, मैंने निर्णय लिया है की hover होने पर हल्का भूरा (gray) वृत (circle) एक चमकदार नीले (bright blue) रंग में परिवर्तित हो जायेगा; click करने पर, नीला वृत (circle) अंदर की तरफ आएगा और भूरा (gray) बैकग्राउंड सफ़ेद हो जाएगा, फिर यह स्थिति checked state के दौरान बनी रहेगी. radio से checked state को हटाने का एक ही तरीका है की आप दूसरे radio पर क्लिक करें, इस स्थिति में नीला और सफ़ेद रंग सीधे धुंधले पड़ते जायेंगे.
हम सबसे पहले कलर्स को सेट करेंगे, सभी states के कलर सेट होने के बाद animate करेंगे. यह वही स्थिति है जब tilde ~
के प्रयोग की जरूरत होगी. यह सामान्य सिबलिंग सिलेक्टर (सिबलिंग संयोजक (combinator)) दूसरे एलिमेंट को सेलेक्ट कर लगा जब तक की यह पहले एलिमेंट से कहीं पूर्ववर्ती (preceded) है, और दोनों के parent एक ही है. हम जब input के ऊपर hover हो तब विसुअल (visual) एलिमेंट को सेलेक्ट करने के लिए input:hover ~ div
का प्रयोग करेंगे
पहले radio को क्लिक करने की कोशिश करें, उसके बाद दूसरे को - आप hover और active/checked की स्थितियों को साफ देख पाएंगे.
अंतिम कदम हर स्थिति (each state) में एनीमेशन को सेटअप करना होगा. इन सभी स्थितियों (states) में एनीमेशन देने की कुंजी (key) है की डिफ़ॉल्ट रूप से unchecked transitions को सेट करें और checked transitions को तब सेट करें जब input पर क्लिक हो. मैं CSS की नयी प्रॉपर्टी will-change
का प्रयोग कर रहा हूँ ताकि ब्राउज़र जान सके की कौन सी प्रॉपर्टी को मैं एनिमेट करूँगा.
HTML का वर्जन
आप SVG का प्रयोग किये बिना भी कस्टम radio input को बना सकते हैं. सेटअप सामान ही होगा:
1 |
<fieldset>
|
2 |
<div class="container"> |
3 |
<div class="svg"> |
4 |
<input id="radio-html" type="radio" name="option"/> |
5 |
<div></div>
|
6 |
<div></div>
|
7 |
<div></div>
|
8 |
</div>
|
9 |
<label for="radio-html">HTML</label> |
10 |
</div>
|
11 |
</fieldset>
|
CSS लगभग वैसा ही होगा, बस दो div
एलिमेंट्स को SVG circle की जगह लेने के लिए अधिक स्टाइल देना होगा. इस स्थिति में, हम अलग अलग div एलिमेंट्स को सेलेक्ट करने के लिए nth-of-type(n)
का प्रयोग करेंगे ताकि हमें HTML में इन्हे class देने की जरूरत न रहे.
SVG के वर्जन के साथ, मार्कअप अधिक हैं पर स्टाइल काम है; HTML वर्जन के साथ, यह दूसरे तरीके से है. परिणाम एक समान है, इसलिए जो कोई भी आपकी कोडिंग की प्राथमिकता को सूट करता हो उसका प्रयोग करें!
Checkbox Inputs
अगला form एलिमेंट जिसको हम कस्टमाइज करेंगे वह होगा checkbox input. इसकी स्थितियां radio input के समान ही होंगी: दो मुख्य visual states (checked और unchecked) और दो इन के बीच के states (hover और click/active).
SVG का वर्जन
सेटअप काफी हद तक radio input की तरह ही नजर आता है, पर वृत (circle) की जगह checkmark को बनाने के लिए कुछ अतिरिक्त लाइन्स का प्रयोग करना होगा.
1 |
<fieldset>
|
2 |
<div class="container"> |
3 |
<div class="svg"> |
4 |
<input id="checkbox-svg" type="checkbox"> |
5 |
<div></div>
|
6 |
<div></div>
|
7 |
<svg viewBox="0 0 24 24"> |
8 |
<g>
|
9 |
<line x1="4.5" x2="9.24" y1="12.5" y2="17.24"></line> |
10 |
<line x1="9.24" x2="19.76" y1="17.24" y2="6.73"></line> |
11 |
</g>
|
12 |
<g>
|
13 |
<line x1="4.5" x2="9.24" y1="12.5" y2="17.24"></line> |
14 |
<line x1="9.24" x2="19.76" y1="17.24" y2="6.73"></line> |
15 |
</g>
|
16 |
</svg>
|
17 |
</div>
|
18 |
<label for="checkbox-svg">SVG</label> |
19 |
</div>
|
20 |
</fieldset>
|
पहले ग्रुप में लाइन्स का रंग हल्के भूरे (light gray) रंग का है और यह एनिमेट नहीं होंगी; input पर क्लिक करने पर दूसरे ग्रुप की लाइन्स एनिमेट करेगी.
एक div
एलिमेंट अतिरिक्त भी है; इसका प्रयोग हम क्लिक इफ़ेक्ट को बनाने के लिए वहां करेंगे जहाँ चमकीला नीला रंग बैकग्राउंड में बढ़ता है. इफ़ेक्ट को काम करने लायक बनाने के लिए, div को एक बड़ी चौड़ाई और ऊंचाई वाले वृत के रूप में बनाना होगा जो की वास्तविक checkbox से बड़ा होगा, और बाहर वाले कंटेनर में overflow:hidden;
सेट होना ही चाहिए ताकि वृत के किनारे नजर ना आएं. गोलाकार div में transform: scale(0)
सेट होना चाहिए, जैसा की radio में था.



फिर से, इसे अपनी प्राथमिकता के अनुसार प्रारूप दें. मैंने checkmark के किनारो और साथ ही सभी कोनो को गोल करने का निर्णय लिया है.
अगला कदम इसे एनिमेशन्स के लिए तैयार करना होगा. इफेक्ट्स radio के समान ही होंगे, बस वृत (circle) के बढ़ने की बजाय checkmark खुद ही draw होगा. इस एनीमेशन के लिए, हमे SVG लाइन्स पर stroke-dashoffset
का उपयोग करने की आवश्यकता होगी.
stroke-dashoffset
को एनिमेट करने के लिए, हमे हर लाइन की लम्बाई की जरूरत होगी. मैंने CodePen में एक टूल बनाया है जो की लम्बाई की गणना करेगा, पर यदि आप checkmark का प्रयोग करते हैं जो मैं पहले ही बना चुका हूँ, तो छोटी लाइन की लम्बाई 6.708
और बड़ी की 14.873
होगी. हम दोनों stroke-dashoffset
और stroke-dasharray
को सेट करने के लिए इसी वैल्यू का प्रयोग करेंगे. यह सिर्फ पहले checkmark के लिए जरूरी है (दूसरी लाइन्स का सेट डिफ़ॉल्ट रूप से unchecked state दिखता है).
जब input पर क्लिक होता है, हम stroke-dashoffset
को 0
सेट कर देंगे, जो की (transition के साथ) "drawn" लाइन की तरह दिखेगा. हमे custom radio से दूसरी स्थिति परिवर्तित होने पर जोड़ने की जरूरत है, इसमें hover होने पर बैकग्राउंड में परिवर्तित होना और वृत (circle) के क्लिक होने पर बढ़ना शामिल है.
अंतिम कदम पर हमे सभी transition को जोड़ना होगा. एक बार फिर, हम unchecked transitions को डिफ़ॉल्ट रूप से सेट करेंगे और checked transition को क्लिक होने पर सेट करेंगे. इसी प्रकार से radio के fading circle के लिए, हमारे पास unchecked होने पर checkmark का fade आउट होना है.
HTML का वर्जन
आप इसी प्रकार का इफ़ेक्ट SVG के प्रयोग करने की बजाय कुछ div एलिमेंट्स से बना सकते है; मार्कअप आसान है, पर इतना स्पष्ट रूप से चित्रित नहीं है. पहला खाली div बढ़ता हुआ नीला सर्किल है, दूसरा डिफ़ॉल्ट checkmark है और तीसरा वो checkmark है जो क्लिक करने पर एनिमेट होता है.
1 |
<fieldset>
|
2 |
<div class="container"> |
3 |
<div class="line"> |
4 |
<input id="checkbox-html" type="checkbox"> |
5 |
<div></div>
|
6 |
<div></div>
|
7 |
<div></div>
|
8 |
</div>
|
9 |
<label for="checkbox-html">HTML</label> |
10 |
</div>
|
11 |
</fieldset>
|
हम checkmark के हर हिस्से के लिए :before
और :after
का प्रयोग करेंगे, जो मार्कअप को आसान बनता है, नहीं तो आपको चार या उससे अधिक खाली एलिमेंट चाहिए होते ताकि आप दो checkmarks बना सकें. हमे लाइन्स को खुद से पोजीशन देनी होगी और उन्हें उनके स्थान पर घुमाना होगा, पर आप दोनों घुमाने और ड्रा करने के लिए एक ही transform का प्रयोग कर सकते हैं.
Symbol वर्जन
आप div एलिमेंट को घुमाने की बजाय checkmark का symbol भी प्रयोग कर सकते हैं! यह अन्य दो visually के समान नहीं है, पर यह ठीक उसी प्रकार कार्य करता है.
1 |
<fieldset>
|
2 |
<div class="container"> |
3 |
<div class="symbol"> |
4 |
<input id="checkbox-sym" type="checkbox"> |
5 |
<div></div>
|
6 |
<div>✓</div> |
7 |
<div>✓</div> |
8 |
</div>
|
9 |
<label for="checkbox-sym">Symbol</label> |
10 |
</div>
|
11 |
</fieldset>
|
ध्यान दें: आपको अंतिम दो div एलिमेंट्स के लिए सिर्फ HTML के सिंबल की जरूरत होगी, पर नीचे दिए डेमो में, मैंने इसे सभी तीनो divs में शामिल कर लिया है ताकि मैं इसे दोहराय गए लूप में शामिल कर सकूं.
क्योंकि हम सिंबल को ड्रा नहीं कर सकते, सफ़ेद वर्जन क्लिक करने पर इसे fade in और out करेगा. नीचे दिए गए सभी तीन वर्जन की जांच करें!
Regular Inputs
इस टुटोरिअल का अंतिम हिस्सा नियमित text input है. मैंने इसके लिए Google के Material लाइन इनपुट्स से प्रेरणा ली है. इन inputs की कुछ अलग अलग states हैं: डिफ़ॉल्ट, एक्टिव/फोकस (जब ब्लिंक करता हुआ कर्सर नजर आ रहा हो), और एक जटिल hover.
पिछले दो input स्टाइल्स के मुकाबले में इसका सेटअप काफी न्यूनतम है. हमारे पास एक fieldset है, input है, और एक div एलिमेंट बॉर्डर के लिए है.
1 |
<fieldset>
|
2 |
<input id="example" type="text"> |
3 |
<label for="example">Label</label> |
4 |
<div></div>
|
5 |
</fieldset>
|
अगला कदम input को स्टाइल देना होगा. हम इनपुट को इस बार छुपायेंगे नहीं क्योंकि हमे वैल्यू को दिखाने की जरूरत है. हम label भी बनाएंगे जो ऊपर और नीचे जायेगा जब हम input पर फोकस करेंगे. इसको काम करने के लिए, हमे label को input के एकदम ऊपर पोजीशन देनी होगी. div बॉर्डर के पास :after
pseudo एलिमेंट है जो इनपुट पर क्लिक होने पर बॉर्डर के ऊपर ड्रा होता है; हम pseudo एलिमेंट पर इसे एनीमेशन के लिए तैयार करने के लिए इसमें scale(0)
रखेंगे.
अगर आप ऊपर वाले डेमो इनपुट पर क्लिक करते हैं और टाइप करना शुरू करते हैं, आप ध्यान देंगे की text लेबल के ऊपर की ओर बाहर निकर रहा है. हम label को छोटा करने के लिए एनिमेट करेंगे और क्लिक करने पर ऊपर की ओर translate करेंगे. repaint होने से बचने के लिए आप पुरे transforms का प्रयोग कर सकते हैं, font-size
के प्रयोग करने की बजाय जैसे की मेने किया है, परन्तु मैंने यह पाया है की इसका प्रयोग और साथ ही साथ translateY
का प्रयोग बहुत सटीक दिखने वाला एनीमेशन देता है. हम div के :after
पर से drawing एनीमेशन बनाने के लिए scale को हटा देंगे.
अब यदि आप ऊपर दिए गए input डेमो पर क्लिक करते हैं और फिर से टाइपिंग शुरू करते है, label छोटा हो जाएगा और थोड़ा सा ऊपर खिसक जायेगा, पर यदि आप टाइप किये गए टेक्स्ट को input में ही छोड़ देते हैं और बाहर क्लिक करते हैं, label फिरसे नीचे खिसक जायेगा, input में बाधा डालते हुए. इस व्यवहार से बचने के लिए हम JavaScript का प्रयोग कर सकते हैं, पर हम CSS की input state जिसे की :valid
कहते हैं का प्रयोग भी कर सकते हैं.
हम HTML में हमारे input में एक खाली एट्रिब्यूट की तरह required
को जोड़ सकते हैं या Haml में हमारे input एट्रिब्यूट में :required => true
जोड़ सकते हैं. इसके बाद हम Sass/CSS में :focus
प्रॉपर्टी में :valid
जोड़ सकते हैं. यह हमारे input में अतिरिक्त visual state जोड़ देगा, और क्योंकि यह सादा सा एक text input है, valid state सिर्फ तभी होगा जब हम इसमें text डालेंगे.
ध्यान दें: अलग अलग input का प्रयोग जैसे की email input इस व्यवहार को तोड़ देगा, क्योंकि ईमेल inputs की वैलिडिटी की अलग आवश्यकता होती है.
प्रेरणा स्त्रोत
अगर इन तकनीकों कर प्रयोग करके आप अपनी खुद की inputs बनाना चाहते हो, पर आपको और visual प्रेरणा की जरूरत है, तो हमारी UI kits को देखें जो की Envato Elements सब्सक्रिप्शन के साथ उपलब्ध है:



निष्कर्ष
सामान्य sibling सिलेक्टर का प्रयोग करने के कईं दर्जन अलग अलग तरीके हो सकते हैं जो की विसुअल, फंक्शनल, या दोनों तरह के हो सकते हैं. यह कंपोनेंट्स को कस्टमाइज करने का एक शक्तिशाली तरीका देते हैं वो भी HTML और CSS के अलावा कुछ प्रयोग किये बिना. इस टुटोरिअल में हमने तीन अलग अलग प्रकार के form एलिमेंट्स को कवर किया; अगले में, हम menus और नेविगेशन को एक्स्प्लोर करेंगे. यदि आपका कोई प्रश्न है या फीडबैक है तो निसंकोच नीचे कमेंट करें!