दिन 15: Forms और Tables की Styling
✅ आज आप सीखेंगे
- एक जैसे inputs: padding, borders, radius, font: inherit
- दिखने वाले पर सुंदर focus rings
- :user-invalid / :user-valid और :has() से validation colours
- Custom select arrow, pill radios, accent-color checkboxes
- Data tables: zebra rows, sticky header, phones पर responsive card layout
🏢 असली दुनिया में
Forms वह जगह है जहाँ business पैसा कमाता है – orders, admissions, enquiries। Default browser form हर phone पर अलग दिखता है, user के कुछ लिखने से पहले ही लाल errors दिखाता है, और admin panel की order table mobile पर बाहर निकलती है। आज आप Sharma Sweets के order form और admin orders table के लिए यह सब ठीक करेंगे।
पूरा, styled order form
<style>
:root { --brand: #264de4; --ok: #15803d; --err: #b91c1c; --line: #cbd5e1; }
* { box-sizing: border-box; }
.form { max-width: 440px; background: #fff; padding: 20px; border-radius: 16px; box-shadow: 0 10px 30px rgb(0 0 0 / 8%); display: grid; gap: 14px; }
.field label { display: block; font-weight: 600; margin-bottom: 4px; }
.field input, .field select {
width: 100%; padding: 10px 12px; font: inherit;
border: 1.5px solid var(--line); border-radius: 10px; background: #fff;
transition: border-color .2s, box-shadow .2s;
}
.field input:focus, .field select:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px rgb(38 77 228 / 15%); }
.field input::placeholder { color: #94a3b8; }
/* validation only after the user has typed (not on page load) */
.field input:user-invalid { border-color: var(--err); }
.field input:user-valid { border-color: var(--ok); }
.hint { font-size: .8rem; color: #64748b; }
.field:has(input:user-invalid) .hint { color: var(--err); }
.field select { appearance: none; background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23475569' stroke-width='2' fill='none'/%3E%3C/svg%3E") no-repeat right 12px center; padding-right: 34px; }
.choices { display: flex; gap: 10px; flex-wrap: wrap; }
.choice input { position: absolute; opacity: 0; }
.choice span { display: inline-block; padding: 8px 14px; border: 1.5px solid var(--line); border-radius: 99px; cursor: pointer; }
.choice input:checked + span { background: var(--brand); border-color: var(--brand); color: #fff; }
.choice input:focus-visible + span { outline: 3px solid #f59e0b; outline-offset: 2px; }
.check { display: flex; gap: 8px; align-items: center; }
.check input { width: 20px; height: 20px; accent-color: var(--brand); }
.submit { background: var(--brand); color: #fff; border: 0; padding: 12px; border-radius: 10px; font: 600 1rem system-ui; cursor: pointer; }
.submit:disabled { opacity: .5; cursor: not-allowed; }
</style>
<form class="form" onsubmit="alert('Valid! Order sent.'); return false">
<div class="field">
<label for="n">Full name</label>
<input id="n" required minlength="2" placeholder="e.g. Aarti Gupta" autocomplete="name">
</div>
<div class="field">
<label for="m">Mobile</label>
<input id="m" type="tel" required pattern="[6-9][0-9]{9}" placeholder="10-digit mobile" aria-describedby="mh">
<div class="hint" id="mh">Starts with 6–9, 10 digits</div>
</div>
<div class="field">
<label for="s">Sweet</label>
<select id="s" required><option value="">Choose…</option><option>Kaju katli</option><option>Ghewar</option></select>
</div>
<fieldset class="choices" style="border:0;padding:0;margin:0">
<legend style="font-weight:600;margin-bottom:6px">Box size</legend>
<label class="choice"><input type="radio" name="b" checked><span>500 g</span></label>
<label class="choice"><input type="radio" name="b"><span>1 kg</span></label>
<label class="choice"><input type="radio" name="b"><span>2 kg</span></label>
</fieldset>
<label class="check"><input type="checkbox" required> Gift wrap with a card</label>
<button class="submit">Place order</button>
</form>| तकनीक | क्यों |
|---|---|
| inputs पर font: inherit | Browsers default में inputs में छोटा system font लेते हैं |
| padding ≥ 10px, ऊँचाई ≥ 44px | Phones पर आसानी से tap |
| box-shadow ring के साथ :focus | Keyboard users के लिए दिखने वाला, brand जैसा focus |
| :user-invalid / :user-valid | Errors user के interact करने के बाद ही – page load पर नहीं |
| .field:has(input:user-invalid) .hint | बिना JavaScript hint लाल |
| appearance: none + SVG arrow | हर device पर एक जैसा select design |
| छिपा radio + styled span | Keyboard-accessible pill buttons |
| accent-color | एक line में brand-colour checkboxes |
अकेले outline: none से form keyboard से इस्तेमाल लायक नहीं रहता। हमेशा ऊपर वाले box-shadow ring जैसा दिखने वाला विकल्प साथ रखें।
:invalid तुरंत लागू होता है, तो ख़ाली required field page खुलते ही लाल हो जाता है – user को डाँटने जैसा लगता है। :user-invalid तब तक रुकता है जब तक user लिखकर field छोड़ न दे या submit न करे।
पढ़ने लायक रहने वाली data tables
<style>
.tbl-wrap { max-height: 230px; overflow: auto; border: 1px solid #e2e8f0; border-radius: 12px; }
table { width: 100%; border-collapse: collapse; font-size: .92rem; }
th, td { padding: 10px 12px; text-align: left; border-bottom: 1px solid #f1f5f9; }
thead th { position: sticky; top: 0; background: #f8fafc; color: #475569; font-size: .75rem; text-transform: uppercase; letter-spacing: .05em; z-index: 1; }
tbody tr:nth-child(even) { background: #fafafa; }
tbody tr:hover { background: #eef2ff; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.st { padding: 2px 10px; border-radius: 99px; font-size: .75rem; font-weight: 700; }
.st.done { background: #dcfce7; color: #166534; } .st.pack { background: #fef3c7; color: #92400e; } .st.new { background: #dbeafe; color: #1e40af; }
</style>
<div class="tbl-wrap"><table>
<thead><tr><th>Order</th><th>Customer</th><th>Items</th><th class="num">Amount</th><th>Status</th></tr></thead>
<tbody>
<tr><td>#1042</td><td>Aarti Gupta</td><td>Kaju katli 2 kg</td><td class="num">₹1,800</td><td><span class="st done">Delivered</span></td></tr>
<tr><td>#1043</td><td>R. Meena</td><td>Ghewar 1 kg</td><td class="num">₹650</td><td><span class="st pack">Packing</span></td></tr>
<tr><td>#1044</td><td>S. Khan</td><td>Assorted box</td><td class="num">₹720</td><td><span class="st new">New</span></td></tr>
<tr><td>#1045</td><td>P. Jain</td><td>Rasmalai 3 kg</td><td class="num">₹2,100</td><td><span class="st new">New</span></td></tr>
<tr><td>#1046</td><td>V. Singh</td><td>Ladoo 5 kg</td><td class="num">₹2,500</td><td><span class="st pack">Packing</span></td></tr>
<tr><td>#1047</td><td>M. Bansal</td><td>Kaju katli 500 g</td><td class="num">₹450</td><td><span class="st done">Delivered</span></td></tr>
</tbody>
</table></div>On phones: turn rows into cards
<style>
table { width: 100%; border-collapse: collapse; }
th, td { padding: 8px 10px; text-align: left; border-bottom: 1px solid #e2e8f0; }
@media (max-width: 520px) {
thead { position: absolute; left: -9999px; } /* hide visually, keep for screen readers */
tr { display: block; margin-bottom: 10px; border: 1px solid #e2e8f0; border-radius: 10px; padding: 6px; }
td { display: flex; justify-content: space-between; border: 0; padding: 4px 6px; }
td::before { content: attr(data-label); font-weight: 600; color: #64748b; }
}
</style>
<table>
<thead><tr><th>Order</th><th>Customer</th><th>Amount</th></tr></thead>
<tbody>
<tr><td data-label="Order">#1042</td><td data-label="Customer">Aarti Gupta</td><td data-label="Amount">₹1,800</td></tr>
<tr><td data-label="Order">#1043</td><td data-label="Customer">R. Meena</td><td data-label="Amount">₹650</td></tr>
</tbody>
</table>
<p style="font:13px system-ui;color:#64748b">Narrow the window below 520px to see the card layout.</p>Option A: scroll wrapper
- Table के चारों ओर overflow-x: auto
- Table का आकार बना रहता है
- कई numeric columns (reports) के लिए बेहतर
Option B: stacked cards
- Rows labelled cards बनती हैं
- बग़ल में scroll नहीं
- 3–6 columns (orders, students) के लिए बेहतर
🏅 आज के Job Skills
Practice tasks
🏋️ Practice – ख़ुद करें
Solution देखें
Quick quiz
🧠 Quick Quiz – ख़ुद को जाँचें
Interview corner
💼 Interview Corner
Custom radio button accessible ढंग से कैसे style करें?
असली input DOM में रखें (दिखने से छिपा, display: none नहीं) ताकि focus हो और बोला जाए; :checked और :focus-visible selectors से बग़ल वाला element style करें; बड़े click target के लिए दोनों को label में रखें।
चौड़ी table responsive कैसे?
या तो overflow-x: auto container में रखें (तुलना बनी रहती है) या कम columns के लिए media query में data-label और ::before से rows को stacked cards बनाएँ। Screen readers के लिए असली thead रखें।
सारांश
- Inputs: font: inherit, पर्याप्त padding, radius, साफ़ focus ring।
- दोस्ताना validation के लिए :user-invalid / :user-valid + :has()।
- Custom controls के लिए appearance: none, छिपे radios और accent-color।
- Tables: sticky head, zebra, tabular numbers; phones पर scroll या stack।
Day 16: दोबारा इस्तेमाल होने वाला UI component kit – buttons, badges, cards, alerts, tabs, modal और toast।
