Forms
Forms are the primary way users submit data. This guide covers production-ready form patterns in plain HTML/CSS, Tailwind CSS, and Bootstrap — including labels, selects, checkboxes, radios, validation states, floating labels, file uploads, and accessibility.
info
Every input must have an associated label for accessibility. Use the for attribute matching the input id to connect them.
| 1 | <div class="form"> |
| 2 | <div class="field"> |
| 3 | <label class="label" for="name2"> |
| 4 | Full Name |
| 5 | </label> |
| 6 | <input class="input" id="name2" type="text" placeholder="Enter your name" /> |
| 7 | </div> |
| 8 | <div class="field"> |
| 9 | <label class="label" for="email2"> |
| 10 | Email Address |
| 11 | </label> |
| 12 | <input class="input" id="email2" type="email" placeholder="your@email.com" /> |
| 13 | <span class="error-msg" id="email-error"> |
| 14 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 15 | <circle cx="12" cy="12" r="10"/> |
| 16 | <line x1="15" y1="9" x2="9" y2="15"/> |
| 17 | <line x1="9" y1="9" x2="15" y2="15"/> |
| 18 | </svg> |
| 19 | Please enter a valid email |
| 20 | </span> |
| 21 | </div> |
| 22 | <div class="field"> |
| 23 | <label class="label" for="msg2"> |
| 24 | Message |
| 25 | <span id="msg-count" style="color:#525252;font-weight:400"> |
| 26 | (0) |
| 27 | </span> |
| 28 | </label> |
| 29 | <textarea class="input" id="msg2" rows="3" placeholder="Write your message..." maxlength="200"> |
| 30 | </textarea> |
| 31 | </div> |
| 32 | <button class="btn" style="width:100%" id="submit-btn"> |
| 33 | Submit |
| 34 | </button> |
| 35 | </div> |
| 1 | .form { |
| 2 | max-width:400px; |
| 3 | margin:32px auto; |
| 4 | font-family:system-ui, |
| 5 | sans-serif |
| 6 | } |
| 7 | .field { |
| 8 | margin-bottom:20px |
| 9 | } |
| 10 | .label { |
| 11 | display:block; |
| 12 | font-size:12px; |
| 13 | font-weight:600; |
| 14 | color:#A0A0A0; |
| 15 | margin-bottom:6px |
| 16 | } |
| 17 | .input { |
| 18 | width:100%; |
| 19 | padding:10px 14px; |
| 20 | border-radius:8px; |
| 21 | font-size:13px; |
| 22 | font-family:inherit; |
| 23 | background:#0A0A0A; |
| 24 | border:1.5px solid #2A2A3E; |
| 25 | color:#E0E0E0; |
| 26 | outline:none; |
| 27 | transition:border-color .2s, |
| 28 | box-shadow .2s; |
| 29 | box-sizing:border-box |
| 30 | } |
| 31 | .input:focus { |
| 32 | border-color:#00FF41; |
| 33 | box-shadow:0 0 0 3px rgba(0, |
| 34 | 255, |
| 35 | 65, |
| 36 | .1) |
| 37 | } |
| 38 | .input::placeholder { |
| 39 | color:#525252 |
| 40 | } |
| 41 | .input.input-error { |
| 42 | border-color:#EF4444 |
| 43 | } |
| 44 | .input.input-error:focus { |
| 45 | border-color:#EF4444; |
| 46 | box-shadow:0 0 0 3px rgba(239, |
| 47 | 68, |
| 48 | 68, |
| 49 | .1) |
| 50 | } |
| 51 | .input.valid { |
| 52 | border-color:#22C55E |
| 53 | } |
| 54 | .error-msg { |
| 55 | font-size:11px; |
| 56 | color:#EF4444; |
| 57 | margin-top:4px; |
| 58 | display:none; |
| 59 | align-items:center; |
| 60 | gap:4px |
| 61 | } |
| 62 | .error-msg.show { |
| 63 | display:flex |
| 64 | } |
| 65 | textarea.input { |
| 66 | resize:vertical; |
| 67 | font-family:inherit |
| 68 | } |
| 69 | .btn { |
| 70 | padding:10px 24px; |
| 71 | border-radius:8px; |
| 72 | font-size:13px; |
| 73 | font-weight:600; |
| 74 | font-family:inherit; |
| 75 | cursor:pointer; |
| 76 | background:#00FF41; |
| 77 | color:#0A0A0A; |
| 78 | border:none; |
| 79 | transition:all .2s |
| 80 | } |
| 81 | .btn:hover { |
| 82 | background:#00E63A |
| 83 | } |
| 84 | .btn:disabled { |
| 85 | opacity:.5; |
| 86 | cursor:not-allowed; |
| 87 | transform:none!important; |
| 88 | box-shadow:none!important |
| 89 | } |
| 1 | const email=document.getElementById('email2');const err=document.getElementById('email-error');email.addEventListener('blur',()=>{const v=email.value.trim();if(v&&!v.includes('@')){email.classList.add('input-error');err.classList.add('show')}else{email.classList.remove('input-error');err.classList.remove('show');if(v)email.classList.add('valid')}});email.addEventListener('input',()=>{email.classList.remove('input-error','valid');err.classList.remove('show')});const msg=document.getElementById('msg2');const count=document.getElementById('msg-count');msg.addEventListener('input',()=>{count.textContent='('+msg.value.length+')'}) |
| 1 | <div class="max-w-sm mx-auto my-8 p-6 rounded-xl bg-[#111] border border-[#222] font-sans"> |
| 2 | <div class="mb-5"> |
| 3 | <label for="tw-name" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 4 | Full Name |
| 5 | </label> |
| 6 | <input id="tw-name" type="text" placeholder="Enter your name" class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 7 | </div> |
| 8 | <div class="mb-5"> |
| 9 | <label for="tw-email" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 10 | Email Address |
| 11 | </label> |
| 12 | <input id="tw-email" type="email" placeholder="your@email.com" class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 13 | <span id="tw-email-err" class="hidden text-[11px] text-[#EF4444] mt-1 items-center gap-1"> |
| 14 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 15 | <circle cx="12" cy="12" r="10"/> |
| 16 | <line x1="15" y1="9" x2="9" y2="15"/> |
| 17 | <line x1="9" y1="9" x2="15" y2="15"/> |
| 18 | </svg> |
| 19 | Please enter a valid email |
| 20 | </span> |
| 21 | </div> |
| 22 | <div class="mb-5"> |
| 23 | <label for="tw-msg" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 24 | Message |
| 25 | <span id="tw-count" class="text-[#525252] font-normal"> |
| 26 | (0) |
| 27 | </span> |
| 28 | </label> |
| 29 | <textarea id="tw-msg" rows="3" maxlength="200" placeholder="Write your message..." class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)] resize-y"> |
| 30 | </textarea> |
| 31 | </div> |
| 32 | <button class="w-full px-6 py-2.5 rounded-lg text-[13px] font-semibold bg-[#00FF41] text-[#0A0A0A] hover:bg-[#00E63A] transition-colors"> |
| 33 | Submit |
| 34 | </button> |
| 35 | </div> |
| 1 | <div class="container py-4" style="max-width:400px"> |
| 2 | <div class="mb-3"> |
| 3 | <label for="bs-name" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 4 | Full Name |
| 5 | </label> |
| 6 | <input id="bs-name" type="text" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="Enter your name" /> |
| 7 | </div> |
| 8 | <div class="mb-3"> |
| 9 | <label for="bs-email" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 10 | Email Address |
| 11 | </label> |
| 12 | <input id="bs-email" type="email" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="your@email.com" /> |
| 13 | <span id="bs-email-err" class="form-text text-danger d-none align-items-center gap-1" style="font-size:11px"> |
| 14 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 15 | <circle cx="12" cy="12" r="10"/> |
| 16 | <line x1="15" y1="9" x2="9" y2="15"/> |
| 17 | <line x1="9" y1="9" x2="15" y2="15"/> |
| 18 | </svg> |
| 19 | Please enter a valid email |
| 20 | </span> |
| 21 | </div> |
| 22 | <div class="mb-3"> |
| 23 | <label for="bs-msg" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 24 | Message |
| 25 | <span id="bs-count" class="text-[#525252]" style="font-weight:400"> |
| 26 | (0) |
| 27 | </span> |
| 28 | </label> |
| 29 | <textarea id="bs-msg" rows="3" maxlength="200" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px;resize:vertical" placeholder="Write your message..."> |
| 30 | </textarea> |
| 31 | </div> |
| 32 | <button class="btn w-100 fw-semibold" style="--bs-btn-bg:#00FF41;--bs-btn-color:#0A0A0A;--bs-btn-border-color:#00FF41;--bs-btn-hover-bg:#00E63A;--bs-btn-hover-border-color:#00E63A;font-size:13px"> |
| 33 | Submit |
| 34 | </button> |
| 35 | </div> |
Styled select dropdowns, checkbox inputs, and radio groups using clean CSS. The select uses appearance: none with a custom SVG arrow for consistent cross-browser styling.
| 1 | <div class="form"> |
| 2 | <div class="field"> |
| 3 | <label class="label" for="country"> |
| 4 | Country |
| 5 | </label> |
| 6 | <select class="select" id="country"> |
| 7 | <option> |
| 8 | United States |
| 9 | </option> |
| 10 | <option> |
| 11 | Canada |
| 12 | </option> |
| 13 | <option> |
| 14 | United Kingdom |
| 15 | </option> |
| 16 | <option> |
| 17 | Germany |
| 18 | </option> |
| 19 | <option> |
| 20 | Japan |
| 21 | </option> |
| 22 | </select> |
| 23 | </div> |
| 24 | <div class="field"> |
| 25 | <span class="label"> |
| 26 | Preferences |
| 27 | <span id="cb-count" style="color:#525252;font-weight:400"> |
| 28 | (1 selected) |
| 29 | </span> |
| 30 | </span> |
| 31 | <div class="checkbox-group"> |
| 32 | <label class="checkbox-label"> |
| 33 | <input type="checkbox" checked /> |
| 34 | Email notifications |
| 35 | </label> |
| 36 | <label class="checkbox-label"> |
| 37 | <input type="checkbox" /> |
| 38 | SMS updates |
| 39 | </label> |
| 40 | <label class="checkbox-label"> |
| 41 | <input type="checkbox" /> |
| 42 | Weekly digest |
| 43 | </label> |
| 44 | </div> |
| 45 | </div> |
| 46 | <div class="field"> |
| 47 | <span class="label"> |
| 48 | Plan |
| 49 | </span> |
| 50 | <div class="radio-group"> |
| 51 | <label class="radio-label"> |
| 52 | <input type="radio" name="plan" checked /> |
| 53 | Starter |
| 54 | </label> |
| 55 | <label class="radio-label"> |
| 56 | <input type="radio" name="plan" /> |
| 57 | Pro |
| 58 | </label> |
| 59 | <label class="radio-label"> |
| 60 | <input type="radio" name="plan" /> |
| 61 | Enterprise |
| 62 | </label> |
| 63 | </div> |
| 64 | </div> |
| 65 | </div> |
| 1 | .form { |
| 2 | max-width:400px; |
| 3 | margin:32px auto; |
| 4 | font-family:system-ui, |
| 5 | sans-serif |
| 6 | } |
| 7 | .field { |
| 8 | margin-bottom:20px |
| 9 | } |
| 10 | .label { |
| 11 | display:block; |
| 12 | font-size:12px; |
| 13 | font-weight:600; |
| 14 | color:#A0A0A0; |
| 15 | margin-bottom:6px |
| 16 | } |
| 17 | .select { |
| 18 | width:100%; |
| 19 | padding:10px 14px; |
| 20 | padding-right:36px; |
| 21 | border-radius:8px; |
| 22 | font-size:13px; |
| 23 | font-family:inherit; |
| 24 | background:#0A0A0A; |
| 25 | border:1.5px solid #2A2A3E; |
| 26 | color:#E0E0E0; |
| 27 | outline:none; |
| 28 | appearance:none; |
| 29 | cursor:pointer; |
| 30 | transition:border-color .2s; |
| 31 | box-sizing:border-box; |
| 32 | background-image:url("data:image/svg+xml, |
| 33 | %3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23525252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); |
| 34 | background-repeat:no-repeat; |
| 35 | background-position:right 12px center |
| 36 | } |
| 37 | .select:focus { |
| 38 | border-color:#00FF41; |
| 39 | box-shadow:0 0 0 3px rgba(0, |
| 40 | 255, |
| 41 | 65, |
| 42 | .1) |
| 43 | } |
| 44 | .checkbox-group, |
| 45 | .radio-group { |
| 46 | display:flex; |
| 47 | flex-direction:column; |
| 48 | gap:10px |
| 49 | } |
| 50 | .checkbox-label, |
| 51 | .radio-label { |
| 52 | display:flex; |
| 53 | align-items:center; |
| 54 | gap:10px; |
| 55 | font-size:13px; |
| 56 | color:#A0A0A0; |
| 57 | cursor:pointer |
| 58 | } |
| 59 | .checkbox-label input[type="checkbox"], |
| 60 | .radio-label input[type="radio"] { |
| 61 | width:18px; |
| 62 | height:18px; |
| 63 | accent-color:#00FF41; |
| 64 | cursor:pointer; |
| 65 | flex-shrink:0 |
| 66 | } |
| 1 | const cbs=document.querySelectorAll('.checkbox-label input[type=checkbox]');const ct=document.getElementById('cb-count');cbs.forEach(cb=>{cb.addEventListener('change',()=>{const n=document.querySelectorAll('.checkbox-label input[type=checkbox]:checked').length;ct.textContent='('+n+' selected)'})}) |
| 1 | <div class="max-w-sm mx-auto my-8 p-6 rounded-xl bg-[#111] border border-[#222] font-sans"> |
| 2 | <div class="mb-5"> |
| 3 | <label for="tw-country" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 4 | Country |
| 5 | </label> |
| 6 | <div class="relative"> |
| 7 | <select id="tw-country" class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)] appearance-none cursor-pointer"> |
| 8 | <option> |
| 9 | United States |
| 10 | </option> |
| 11 | <option> |
| 12 | Canada |
| 13 | </option> |
| 14 | <option> |
| 15 | United Kingdom |
| 16 | </option> |
| 17 | <option> |
| 18 | Germany |
| 19 | </option> |
| 20 | <option> |
| 21 | Japan |
| 22 | </option> |
| 23 | </select> |
| 24 | <svg class="absolute right-3 top-1/2 -translate-y-1/2 w-3 h-3 text-[#525252] pointer-events-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 25 | <polyline points="6 9 12 15 18 9"/> |
| 26 | </svg> |
| 27 | </div> |
| 28 | </div> |
| 29 | <div class="mb-5"> |
| 30 | <span class="block text-xs font-semibold text-[#A0A0A0] mb-2"> |
| 31 | Preferences |
| 32 | <span id="tw-cb-count" class="text-[#525252] font-normal"> |
| 33 | (1 selected) |
| 34 | </span> |
| 35 | </span> |
| 36 | <div class="flex flex-col gap-2.5"> |
| 37 | <label class="flex items-center gap-2.5 text-[13px] text-[#A0A0A0] cursor-pointer"> |
| 38 | <input type="checkbox" checked class="w-[18px] h-[18px] accent-[#00FF41] cursor-pointer shrink-0" /> |
| 39 | Email notifications |
| 40 | </label> |
| 41 | <label class="flex items-center gap-2.5 text-[13px] text-[#A0A0A0] cursor-pointer"> |
| 42 | <input type="checkbox" class="w-[18px] h-[18px] accent-[#00FF41] cursor-pointer shrink-0" /> |
| 43 | SMS updates |
| 44 | </label> |
| 45 | <label class="flex items-center gap-2.5 text-[13px] text-[#A0A0A0] cursor-pointer"> |
| 46 | <input type="checkbox" class="w-[18px] h-[18px] accent-[#00FF41] cursor-pointer shrink-0" /> |
| 47 | Weekly digest |
| 48 | </label> |
| 49 | </div> |
| 50 | </div> |
| 51 | <div class="mb-2"> |
| 52 | <span class="block text-xs font-semibold text-[#A0A0A0] mb-2"> |
| 53 | Plan |
| 54 | </span> |
| 55 | <div class="flex flex-col gap-2.5"> |
| 56 | <label class="flex items-center gap-2.5 text-[13px] text-[#A0A0A0] cursor-pointer"> |
| 57 | <input type="radio" name="tw-plan" checked class="w-[18px] h-[18px] accent-[#00FF41] cursor-pointer shrink-0" /> |
| 58 | Starter |
| 59 | </label> |
| 60 | <label class="flex items-center gap-2.5 text-[13px] text-[#A0A0A0] cursor-pointer"> |
| 61 | <input type="radio" name="tw-plan" class="w-[18px] h-[18px] accent-[#00FF41] cursor-pointer shrink-0" /> |
| 62 | Pro |
| 63 | </label> |
| 64 | <label class="flex items-center gap-2.5 text-[13px] text-[#A0A0A0] cursor-pointer"> |
| 65 | <input type="radio" name="tw-plan" class="w-[18px] h-[18px] accent-[#00FF41] cursor-pointer shrink-0" /> |
| 66 | Enterprise |
| 67 | </label> |
| 68 | </div> |
| 69 | </div> |
| 70 | </div> |
| 1 | <div class="container py-4" style="max-width:400px"> |
| 2 | <div class="mb-3"> |
| 3 | <label for="bs-country" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 4 | Country |
| 5 | </label> |
| 6 | <select id="bs-country" class="form-select bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0]" style="font-size:13px"> |
| 7 | <option> |
| 8 | United States |
| 9 | </option> |
| 10 | <option> |
| 11 | Canada |
| 12 | </option> |
| 13 | <option> |
| 14 | United Kingdom |
| 15 | </option> |
| 16 | <option> |
| 17 | Germany |
| 18 | </option> |
| 19 | <option> |
| 20 | Japan |
| 21 | </option> |
| 22 | </select> |
| 23 | </div> |
| 24 | <div class="mb-3"> |
| 25 | <span class="form-label text-[#A0A0A0] d-block" style="font-size:12px;font-weight:600"> |
| 26 | Preferences |
| 27 | <span id="bs-cb-count" class="text-[#525252]" style="font-weight:400"> |
| 28 | (1 selected) |
| 29 | </span> |
| 30 | </span> |
| 31 | <div class="form-check"> |
| 32 | <input class="form-check-input" type="checkbox" value="" id="bs-cb1" checked style="accent-color:#00FF41"> |
| 33 | <label class="form-check-label text-[#A0A0A0]" for="bs-cb1" style="font-size:13px"> |
| 34 | Email notifications |
| 35 | </label> |
| 36 | </div> |
| 37 | <div class="form-check"> |
| 38 | <input class="form-check-input" type="checkbox" value="" id="bs-cb2" style="accent-color:#00FF41"> |
| 39 | <label class="form-check-label text-[#A0A0A0]" for="bs-cb2" style="font-size:13px"> |
| 40 | SMS updates |
| 41 | </label> |
| 42 | </div> |
| 43 | <div class="form-check"> |
| 44 | <input class="form-check-input" type="checkbox" value="" id="bs-cb3" style="accent-color:#00FF41"> |
| 45 | <label class="form-check-label text-[#A0A0A0]" for="bs-cb3" style="font-size:13px"> |
| 46 | Weekly digest |
| 47 | </label> |
| 48 | </div> |
| 49 | </div> |
| 50 | <div class="mb-2"> |
| 51 | <span class="form-label text-[#A0A0A0] d-block" style="font-size:12px;font-weight:600"> |
| 52 | Plan |
| 53 | </span> |
| 54 | <div class="form-check"> |
| 55 | <input class="form-check-input" type="radio" name="bs-plan" id="bs-plan1" checked style="accent-color:#00FF41"> |
| 56 | <label class="form-check-label text-[#A0A0A0]" for="bs-plan1" style="font-size:13px"> |
| 57 | Starter |
| 58 | </label> |
| 59 | </div> |
| 60 | <div class="form-check"> |
| 61 | <input class="form-check-input" type="radio" name="bs-plan" id="bs-plan2" style="accent-color:#00FF41"> |
| 62 | <label class="form-check-label text-[#A0A0A0]" for="bs-plan2" style="font-size:13px"> |
| 63 | Pro |
| 64 | </label> |
| 65 | </div> |
| 66 | <div class="form-check"> |
| 67 | <input class="form-check-input" type="radio" name="bs-plan" id="bs-plan3" style="accent-color:#00FF41"> |
| 68 | <label class="form-check-label text-[#A0A0A0]" for="bs-plan3" style="font-size:13px"> |
| 69 | Enterprise |
| 70 | </label> |
| 71 | </div> |
| 72 | </div> |
| 73 | </div> |
Communicate errors, success, and help text clearly. Pair visual indicators with aria-describedby and aria-invalid for screen readers.
| 1 | <div class="form"> |
| 2 | <div class="field"> |
| 3 | <label class="label" for="u2"> |
| 4 | Username |
| 5 | </label> |
| 6 | <input class="input valid" id="u2" type="text" value="johndoe" aria-invalid="false" aria-describedby="u2-help" /> |
| 7 | <span class="help ok" id="u2-help"> |
| 8 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 9 | <polyline points="20 6 9 17 4 12"/> |
| 10 | </svg> |
| 11 | Username available |
| 12 | </span> |
| 13 | </div> |
| 14 | <div class="field"> |
| 15 | <label class="label" for="p2"> |
| 16 | Password |
| 17 | </label> |
| 18 | <input class="input input-error" id="p2" type="password" value="123" aria-invalid="true" aria-describedby="p2-err" /> |
| 19 | <span class="help err" id="p2-err"> |
| 20 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 21 | <circle cx="12" cy="12" r="10"/> |
| 22 | <line x1="12" y1="8" x2="12" y2="12"/> |
| 23 | <line x1="12" y1="16" x2="12.01" y2="16"/> |
| 24 | </svg> |
| 25 | Must be at least 8 characters |
| 26 | </span> |
| 27 | </div> |
| 28 | <div class="field"> |
| 29 | <label class="label" for="d2"> |
| 30 | Bio |
| 31 | </label> |
| 32 | <textarea class="input" id="d2" rows="2" placeholder="Optional"> |
| 33 | </textarea> |
| 34 | <span class="help" id="d2-help"> |
| 35 | Max 160 characters |
| 36 | </span> |
| 37 | </div> |
| 38 | </div> |
| 1 | .form { |
| 2 | max-width:400px; |
| 3 | margin:32px auto; |
| 4 | font-family:system-ui, |
| 5 | sans-serif |
| 6 | } |
| 7 | .field { |
| 8 | margin-bottom:20px |
| 9 | } |
| 10 | .label { |
| 11 | display:block; |
| 12 | font-size:12px; |
| 13 | font-weight:600; |
| 14 | color:#A0A0A0; |
| 15 | margin-bottom:6px |
| 16 | } |
| 17 | .input { |
| 18 | width:100%; |
| 19 | padding:10px 14px; |
| 20 | border-radius:8px; |
| 21 | font-size:13px; |
| 22 | font-family:inherit; |
| 23 | background:#0A0A0A; |
| 24 | border:1.5px solid #2A2A3E; |
| 25 | color:#E0E0E0; |
| 26 | outline:none; |
| 27 | transition:border-color .2s, |
| 28 | box-shadow .2s; |
| 29 | box-sizing:border-box |
| 30 | } |
| 31 | .input:focus { |
| 32 | border-color:#00FF41; |
| 33 | box-shadow:0 0 0 3px rgba(0, |
| 34 | 255, |
| 35 | 65, |
| 36 | .1) |
| 37 | } |
| 38 | .input.valid { |
| 39 | border-color:#22C55E |
| 40 | } |
| 41 | .input.valid:focus { |
| 42 | box-shadow:0 0 0 3px rgba(34, |
| 43 | 197, |
| 44 | 94, |
| 45 | .1) |
| 46 | } |
| 47 | .input.input-error { |
| 48 | border-color:#EF4444 |
| 49 | } |
| 50 | .input.input-error:focus { |
| 51 | box-shadow:0 0 0 3px rgba(239, |
| 52 | 68, |
| 53 | 68, |
| 54 | .1) |
| 55 | } |
| 56 | .help { |
| 57 | font-size:11px; |
| 58 | color:#525252; |
| 59 | margin-top:4px; |
| 60 | display:flex; |
| 61 | align-items:center; |
| 62 | gap:4px |
| 63 | } |
| 64 | .help.ok { |
| 65 | color:#22C55E |
| 66 | } |
| 67 | .help.err { |
| 68 | color:#EF4444 |
| 69 | } |
| 70 | textarea.input { |
| 71 | resize:vertical; |
| 72 | font-family:inherit |
| 73 | } |
| 1 | <div class="max-w-sm mx-auto my-8 p-6 rounded-xl bg-[#111] border border-[#222] font-sans"> |
| 2 | <div class="mb-5"> |
| 3 | <label for="tw-u2" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 4 | Username |
| 5 | </label> |
| 6 | <input id="tw-u2" type="text" value="johndoe" aria-invalid="false" aria-describedby="tw-u2-help" class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#22C55E] text-[#E0E0E0] focus:outline-none focus:ring-[3px] focus:ring-[rgba(34,197,94,0.1)]" /> |
| 7 | <span id="tw-u2-help" class="text-[11px] text-[#22C55E] mt-1 flex items-center gap-1"> |
| 8 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 9 | <polyline points="20 6 9 17 4 12"/> |
| 10 | </svg> |
| 11 | Username available |
| 12 | </span> |
| 13 | </div> |
| 14 | <div class="mb-5"> |
| 15 | <label for="tw-p2" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 16 | Password |
| 17 | </label> |
| 18 | <input id="tw-p2" type="password" value="123" aria-invalid="true" aria-describedby="tw-p2-err" class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#EF4444] text-[#E0E0E0] focus:outline-none focus:ring-[3px] focus:ring-[rgba(239,68,68,0.1)]" /> |
| 19 | <span id="tw-p2-err" class="text-[11px] text-[#EF4444] mt-1 flex items-center gap-1"> |
| 20 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 21 | <circle cx="12" cy="12" r="10"/> |
| 22 | <line x1="12" y1="8" x2="12" y2="12"/> |
| 23 | <line x1="12" y1="16" x2="12.01" y2="16"/> |
| 24 | </svg> |
| 25 | Must be at least 8 characters |
| 26 | </span> |
| 27 | </div> |
| 28 | <div class="mb-2"> |
| 29 | <label for="tw-d2" class="block text-xs font-semibold text-[#A0A0A0] mb-1.5"> |
| 30 | Bio |
| 31 | </label> |
| 32 | <textarea id="tw-d2" rows="2" placeholder="Optional" class="w-full px-3.5 py-2.5 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)] resize-y"> |
| 33 | </textarea> |
| 34 | <span class="text-[11px] text-[#525252] mt-1 block"> |
| 35 | Max 160 characters |
| 36 | </span> |
| 37 | </div> |
| 38 | </div> |
| 1 | <div class="container py-4" style="max-width:400px"> |
| 2 | <div class="mb-3"> |
| 3 | <label for="bs-u2" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 4 | Username |
| 5 | </label> |
| 6 | <input id="bs-u2" type="text" value="johndoe" aria-invalid="false" class="form-control is-valid bg-[#0A0A0A] border-[#22C55E] text-[#E0E0E0]" style="font-size:13px" /> |
| 7 | <span class="form-text d-flex align-items-center gap-1" style="font-size:11px;color:#22C55E"> |
| 8 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 9 | <polyline points="20 6 9 17 4 12"/> |
| 10 | </svg> |
| 11 | Username available |
| 12 | </span> |
| 13 | </div> |
| 14 | <div class="mb-3"> |
| 15 | <label for="bs-p2" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 16 | Password |
| 17 | </label> |
| 18 | <input id="bs-p2" type="password" value="123" aria-invalid="true" class="form-control is-invalid bg-[#0A0A0A] border-[#EF4444] text-[#E0E0E0]" style="font-size:13px" /> |
| 19 | <span class="invalid-feedback d-flex align-items-center gap-1" style="font-size:11px"> |
| 20 | <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 21 | <circle cx="12" cy="12" r="10"/> |
| 22 | <line x1="12" y1="8" x2="12" y2="12"/> |
| 23 | <line x1="12" y1="16" x2="12.01" y2="16"/> |
| 24 | </svg> |
| 25 | Must be at least 8 characters |
| 26 | </span> |
| 27 | </div> |
| 28 | <div class="mb-2"> |
| 29 | <label for="bs-d2" class="form-label text-[#A0A0A0]" style="font-size:12px;font-weight:600"> |
| 30 | Bio |
| 31 | </label> |
| 32 | <textarea id="bs-d2" rows="2" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px;resize:vertical" placeholder="Optional"> |
| 33 | </textarea> |
| 34 | <span class="form-text" style="font-size:11px;color:#525252"> |
| 35 | Max 160 characters |
| 36 | </span> |
| 37 | </div> |
| 38 | </div> |
Compact fields where the label floats above the value on focus or when the input is not empty. Great for dense forms.
| 1 | <div class="form"> |
| 2 | <div class="field floating"> |
| 3 | <input class="input" id="fl-email" type="email" placeholder=" " /> |
| 4 | <label class="label" for="fl-email"> |
| 5 | Email address |
| 6 | </label> |
| 7 | </div> |
| 8 | <div class="field floating"> |
| 9 | <input class="input" id="fl-password" type="password" placeholder=" " /> |
| 10 | <label class="label" for="fl-password"> |
| 11 | Password |
| 12 | </label> |
| 13 | </div> |
| 14 | <button class="btn" style="width:100%"> |
| 15 | Continue |
| 16 | </button> |
| 17 | </div> |
| 1 | .form { |
| 2 | max-width:400px; |
| 3 | margin:32px auto; |
| 4 | font-family:system-ui, |
| 5 | sans-serif |
| 6 | } |
| 7 | .field.floating { |
| 8 | position:relative; |
| 9 | margin-bottom:20px |
| 10 | } |
| 11 | .field.floating .input { |
| 12 | width:100%; |
| 13 | padding:18px 14px 8px; |
| 14 | border-radius:8px; |
| 15 | font-size:13px; |
| 16 | font-family:inherit; |
| 17 | background:#0A0A0A; |
| 18 | border:1.5px solid #2A2A3E; |
| 19 | color:#E0E0E0; |
| 20 | outline:none; |
| 21 | transition:border-color .2s, |
| 22 | box-shadow .2s; |
| 23 | box-sizing:border-box |
| 24 | } |
| 25 | .field.floating .input:focus { |
| 26 | border-color:#00FF41; |
| 27 | box-shadow:0 0 0 3px rgba(0, |
| 28 | 255, |
| 29 | 65, |
| 30 | .1) |
| 31 | } |
| 32 | .field.floating .label { |
| 33 | position:absolute; |
| 34 | left:14px; |
| 35 | top:13px; |
| 36 | font-size:13px; |
| 37 | font-weight:500; |
| 38 | color:#525252; |
| 39 | pointer-events:none; |
| 40 | transition:all .2s ease; |
| 41 | background:transparent; |
| 42 | padding:0 2px |
| 43 | } |
| 44 | .field.floating .input:focus~.label, |
| 45 | .field.floating .input:not(:placeholder-shown)~.label { |
| 46 | top:4px; |
| 47 | font-size:10px; |
| 48 | color:#00FF41 |
| 49 | } |
| 50 | .btn { |
| 51 | width:100%; |
| 52 | padding:10px; |
| 53 | border-radius:8px; |
| 54 | font-size:13px; |
| 55 | font-weight:600; |
| 56 | font-family:inherit; |
| 57 | cursor:pointer; |
| 58 | background:#00FF41; |
| 59 | color:#0A0A0A; |
| 60 | border:none; |
| 61 | transition:all .2s |
| 62 | } |
| 63 | .btn:hover { |
| 64 | background:#00E63A |
| 65 | } |
| 1 | <div class="max-w-sm mx-auto my-8 p-6 rounded-xl bg-[#111] border border-[#222] font-sans"> |
| 2 | <div class="relative mb-5"> |
| 3 | <input id="tw-fl-email" type="email" placeholder=" " class="peer w-full px-3.5 pt-5 pb-2 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 4 | <label for="tw-fl-email" class="absolute left-3.5 top-3.5 text-[13px] text-[#525252] pointer-events-none transition-all peer-focus:top-1 peer-focus:text-[10px] peer-focus:text-[#00FF41] peer-[:not(:placeholder-shown)]:top-1 peer-[:not(:placeholder-shown)]:text-[10px] peer-[:not(:placeholder-shown)]:text-[#00FF41]"> |
| 5 | Email address |
| 6 | </label> |
| 7 | </div> |
| 8 | <div class="relative mb-5"> |
| 9 | <input id="tw-fl-password" type="password" placeholder=" " class="peer w-full px-3.5 pt-5 pb-2 rounded-lg text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 10 | <label for="tw-fl-password" class="absolute left-3.5 top-3.5 text-[13px] text-[#525252] pointer-events-none transition-all peer-focus:top-1 peer-focus:text-[10px] peer-focus:text-[#00FF41] peer-[:not(:placeholder-shown)]:top-1 peer-[:not(:placeholder-shown)]:text-[10px] peer-[:not(:placeholder-shown)]:text-[#00FF41]"> |
| 11 | Password |
| 12 | </label> |
| 13 | </div> |
| 14 | <button class="w-full px-6 py-2.5 rounded-lg text-[13px] font-semibold bg-[#00FF41] text-[#0A0A0A] hover:bg-[#00E63A] transition-colors"> |
| 15 | Continue |
| 16 | </button> |
| 17 | </div> |
| 1 | <div class="container py-4" style="max-width:400px"> |
| 2 | <div class="form-floating mb-3"> |
| 3 | <input type="email" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0]" id="bs-fl-email" placeholder="name@example.com" style="--bs-body-bg:#0A0A0A;--bs-body-color:#E0E0E0;font-size:13px"> |
| 4 | <label for="bs-fl-email" class="text-[#525252]" style="font-size:13px"> |
| 5 | Email address |
| 6 | </label> |
| 7 | </div> |
| 8 | <div class="form-floating mb-3"> |
| 9 | <input type="password" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0]" id="bs-fl-password" placeholder="Password" style="font-size:13px"> |
| 10 | <label for="bs-fl-password" class="text-[#525252]" style="font-size:13px"> |
| 11 | Password |
| 12 | </label> |
| 13 | </div> |
| 14 | <button class="btn w-100 fw-semibold" style="--bs-btn-bg:#00FF41;--bs-btn-color:#0A0A0A;--bs-btn-border-color:#00FF41;--bs-btn-hover-bg:#00E63A;font-size:13px"> |
| 15 | Continue |
| 16 | </button> |
| 17 | </div> |
A complete sign-up form with grid layout, inline fields, and validation-ready styling. This is a production-ready form card you can drop into any project.
| 1 | <div class="form-card"> |
| 2 | <h2 class="form-title"> |
| 3 | Create Account |
| 4 | </h2> |
| 5 | <p class="form-sub"> |
| 6 | Get started with a free account |
| 7 | </p> |
| 8 | <div class="row"> |
| 9 | <div class="field"> |
| 10 | <label class="label"> |
| 11 | First Name |
| 12 | </label> |
| 13 | <input class="input" placeholder="John" /> |
| 14 | </div> |
| 15 | <div class="field"> |
| 16 | <label class="label"> |
| 17 | Last Name |
| 18 | </label> |
| 19 | <input class="input" placeholder="Doe" /> |
| 20 | </div> |
| 21 | </div> |
| 22 | <div class="field"> |
| 23 | <label class="label"> |
| 24 | |
| 25 | </label> |
| 26 | <input class="input" type="email" placeholder="john@example.com" /> |
| 27 | </div> |
| 28 | <div class="row"> |
| 29 | <div class="field"> |
| 30 | <label class="label"> |
| 31 | Password |
| 32 | </label> |
| 33 | <div class="pw-wrap"> |
| 34 | <input class="input" id="pw1" type="password" placeholder="••••••••" /> |
| 35 | <button class="pw-toggle" data-for="pw1" aria-label="Toggle password"> |
| 36 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 37 | <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/> |
| 38 | <circle cx="12" cy="12" r="3"/> |
| 39 | </svg> |
| 40 | </button> |
| 41 | </div> |
| 42 | </div> |
| 43 | <div class="field"> |
| 44 | <label class="label"> |
| 45 | Confirm |
| 46 | </label> |
| 47 | <div class="pw-wrap"> |
| 48 | <input class="input" id="pw2" type="password" placeholder="••••••••" /> |
| 49 | <button class="pw-toggle" data-for="pw2" aria-label="Toggle password"> |
| 50 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 51 | <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/> |
| 52 | <circle cx="12" cy="12" r="3"/> |
| 53 | </svg> |
| 54 | </button> |
| 55 | </div> |
| 56 | </div> |
| 57 | </div> |
| 58 | <div class="field"> |
| 59 | <label class="checkbox-label" style="margin-top:4px"> |
| 60 | <input type="checkbox" checked /> |
| 61 | I agree to the |
| 62 | <a href="#" style="color:#00FF41"> |
| 63 | Terms |
| 64 | </a> |
| 65 | </label> |
| 66 | </div> |
| 67 | <button class="btn"> |
| 68 | Create Account |
| 69 | </button> |
| 70 | <hr class="divider" /> |
| 71 | <p class="terms"> |
| 72 | By signing up you agree to our |
| 73 | <a href="#"> |
| 74 | Terms of Service |
| 75 | </a> |
| 76 | </p> |
| 77 | </div> |
| 1 | .form-card { |
| 2 | max-width:480px; |
| 3 | margin:24px auto; |
| 4 | background:#111; |
| 5 | border:1px solid #222; |
| 6 | border-radius:12px; |
| 7 | padding:28px; |
| 8 | font-family:system-ui, |
| 9 | sans-serif |
| 10 | } |
| 11 | .form-title { |
| 12 | font-size:18px; |
| 13 | font-weight:700; |
| 14 | color:#E0E0E0; |
| 15 | margin:0 0 4px 0 |
| 16 | } |
| 17 | .form-sub { |
| 18 | font-size:12px; |
| 19 | color:#808080; |
| 20 | margin:0 0 24px 0 |
| 21 | } |
| 22 | .row { |
| 23 | display:grid; |
| 24 | grid-template-columns:1fr 1fr; |
| 25 | gap:12px; |
| 26 | margin-bottom:16px |
| 27 | } |
| 28 | .field { |
| 29 | margin-bottom:16px |
| 30 | } |
| 31 | .label { |
| 32 | display:block; |
| 33 | font-size:11px; |
| 34 | font-weight:600; |
| 35 | color:#A0A0A0; |
| 36 | margin-bottom:5px |
| 37 | } |
| 38 | .input { |
| 39 | width:100%; |
| 40 | padding:9px 12px; |
| 41 | border-radius:6px; |
| 42 | font-size:13px; |
| 43 | font-family:inherit; |
| 44 | background:#0A0A0A; |
| 45 | border:1.5px solid #2A2A3E; |
| 46 | color:#E0E0E0; |
| 47 | outline:none; |
| 48 | transition:border-color .2s; |
| 49 | box-sizing:border-box |
| 50 | } |
| 51 | .input:focus { |
| 52 | border-color:#00FF41; |
| 53 | box-shadow:0 0 0 3px rgba(0, |
| 54 | 255, |
| 55 | 65, |
| 56 | .1) |
| 57 | } |
| 58 | .input::placeholder { |
| 59 | color:#525252 |
| 60 | } |
| 61 | .pw-wrap { |
| 62 | position:relative |
| 63 | } |
| 64 | .pw-toggle { |
| 65 | position:absolute; |
| 66 | right:8px; |
| 67 | top:50%; |
| 68 | transform:translateY(-50%); |
| 69 | background:none; |
| 70 | border:none; |
| 71 | color:#525252; |
| 72 | cursor:pointer; |
| 73 | padding:4px; |
| 74 | display:flex; |
| 75 | transition:color .2s; |
| 76 | line-height:1 |
| 77 | } |
| 78 | .pw-toggle:hover { |
| 79 | color:#00FF41 |
| 80 | } |
| 81 | .btn { |
| 82 | width:100%; |
| 83 | padding:10px; |
| 84 | border-radius:8px; |
| 85 | font-size:13px; |
| 86 | font-weight:600; |
| 87 | font-family:inherit; |
| 88 | cursor:pointer; |
| 89 | background:#00FF41; |
| 90 | color:#0A0A0A; |
| 91 | border:none; |
| 92 | transition:all .2s; |
| 93 | margin-top:8px |
| 94 | } |
| 95 | .btn:hover { |
| 96 | background:#00E63A |
| 97 | } |
| 98 | .divider { |
| 99 | border:none; |
| 100 | border-top:1px solid #222; |
| 101 | margin:20px 0 |
| 102 | } |
| 103 | .terms { |
| 104 | font-size:11px; |
| 105 | color:#525252; |
| 106 | text-align:center; |
| 107 | margin-top:16px |
| 108 | } |
| 109 | .terms a { |
| 110 | color:#808080 |
| 111 | } |
| 112 | .checkbox-label { |
| 113 | display:flex; |
| 114 | align-items:center; |
| 115 | gap:10px; |
| 116 | font-size:12px; |
| 117 | color:#A0A0A0; |
| 118 | cursor:pointer |
| 119 | } |
| 120 | .checkbox-label input { |
| 121 | width:16px; |
| 122 | height:16px; |
| 123 | accent-color:#00FF41 |
| 124 | } |
| 1 | document.querySelectorAll('.pw-toggle').forEach(btn=>{btn.addEventListener('click',()=>{const inp=document.getElementById(btn.dataset.for);const isPw=inp.type==='password';inp.type=isPw?'text':'password';btn.querySelector('svg').innerHTML=isPw?'<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/>':'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>'})}) |
| 1 | <div class="max-w-md mx-auto my-6 p-7 rounded-xl bg-[#111] border border-[#222] font-sans"> |
| 2 | <h2 class="text-lg font-bold text-[#E0E0E0] mb-1"> |
| 3 | Create Account |
| 4 | </h2> |
| 5 | <p class="text-xs text-[#808080] mb-6"> |
| 6 | Get started with a free account |
| 7 | </p> |
| 8 | <div class="grid grid-cols-2 gap-3 mb-4"> |
| 9 | <div> |
| 10 | <label class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 11 | First Name |
| 12 | </label> |
| 13 | <input placeholder="John" class="w-full px-3 py-2 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 14 | </div> |
| 15 | <div> |
| 16 | <label class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 17 | Last Name |
| 18 | </label> |
| 19 | <input placeholder="Doe" class="w-full px-3 py-2 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 20 | </div> |
| 21 | </div> |
| 22 | <div class="mb-4"> |
| 23 | <label class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 24 | |
| 25 | </label> |
| 26 | <input type="email" placeholder="john@example.com" class="w-full px-3 py-2 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 27 | </div> |
| 28 | <div class="grid grid-cols-2 gap-3 mb-4"> |
| 29 | <div> |
| 30 | <label class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 31 | Password |
| 32 | </label> |
| 33 | <div class="relative"> |
| 34 | <input id="tw-pw1" type="password" placeholder="••••••••" class="w-full px-3 py-2 pr-9 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 35 | <button type="button" data-twfor="tw-pw1" aria-label="Toggle password" class="absolute right-2 top-1/2 -translate-y-1/2 p-1 bg-transparent border-0 text-[#525252] hover:text-[#00FF41] transition-colors"> |
| 36 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 37 | <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/> |
| 38 | <circle cx="12" cy="12" r="3"/> |
| 39 | </svg> |
| 40 | </button> |
| 41 | </div> |
| 42 | </div> |
| 43 | <div> |
| 44 | <label class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 45 | Confirm |
| 46 | </label> |
| 47 | <div class="relative"> |
| 48 | <input id="tw-pw2" type="password" placeholder="••••••••" class="w-full px-3 py-2 pr-9 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 49 | <button type="button" data-twfor="tw-pw2" aria-label="Toggle password" class="absolute right-2 top-1/2 -translate-y-1/2 p-1 bg-transparent border-0 text-[#525252] hover:text-[#00FF41] transition-colors"> |
| 50 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 51 | <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/> |
| 52 | <circle cx="12" cy="12" r="3"/> |
| 53 | </svg> |
| 54 | </button> |
| 55 | </div> |
| 56 | </div> |
| 57 | </div> |
| 58 | <label class="flex items-center gap-2.5 text-xs text-[#A0A0A0] cursor-pointer mb-4"> |
| 59 | <input type="checkbox" checked class="w-4 h-4 accent-[#00FF41]" /> |
| 60 | I agree to the |
| 61 | <a href="#" class="text-[#00FF41]"> |
| 62 | Terms |
| 63 | </a> |
| 64 | </label> |
| 65 | <button class="w-full px-4 py-2.5 rounded-lg text-[13px] font-semibold bg-[#00FF41] text-[#0A0A0A] hover:bg-[#00E63A] transition-colors"> |
| 66 | Create Account |
| 67 | </button> |
| 68 | <hr class="border-0 border-t border-[#222] my-5" /> |
| 69 | <p class="text-[11px] text-[#525252] text-center"> |
| 70 | By signing up you agree to our |
| 71 | <a href="#" class="text-[#808080]"> |
| 72 | Terms of Service |
| 73 | </a> |
| 74 | </p> |
| 75 | </div> |
| 1 | <div class="container py-4" style="max-width:480px"> |
| 2 | <div class="card bg-[#111] border-[#222]"> |
| 3 | <div class="card-body"> |
| 4 | <h2 class="card-title" style="color:#E0E0E0;font-size:18px"> |
| 5 | Create Account |
| 6 | </h2> |
| 7 | <p class="card-text" style="color:#808080;font-size:12px"> |
| 8 | Get started with a free account |
| 9 | </p> |
| 10 | <form class="mt-4"> |
| 11 | <div class="row g-3 mb-3"> |
| 12 | <div class="col-md-6"> |
| 13 | <label class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 14 | First Name |
| 15 | </label> |
| 16 | <input class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="John" /> |
| 17 | </div> |
| 18 | <div class="col-md-6"> |
| 19 | <label class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 20 | Last Name |
| 21 | </label> |
| 22 | <input class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="Doe" /> |
| 23 | </div> |
| 24 | </div> |
| 25 | <div class="mb-3"> |
| 26 | <label class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 27 | |
| 28 | </label> |
| 29 | <input type="email" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="john@example.com" /> |
| 30 | </div> |
| 31 | <div class="row g-3 mb-3"> |
| 32 | <div class="col-md-6"> |
| 33 | <label class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 34 | Password |
| 35 | </label> |
| 36 | <div class="position-relative"> |
| 37 | <input id="bs-pw1" type="password" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px;padding-right:36px" placeholder="••••••••" /> |
| 38 | <button type="button" class="btn btn-link position-absolute p-1 text-decoration-none" data-bsfor="bs-pw1" aria-label="Toggle password" style="right:8px;top:50%;transform:translateY(-50%);color:#525252"> |
| 39 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 40 | <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/> |
| 41 | <circle cx="12" cy="12" r="3"/> |
| 42 | </svg> |
| 43 | </button> |
| 44 | </div> |
| 45 | </div> |
| 46 | <div class="col-md-6"> |
| 47 | <label class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 48 | Confirm |
| 49 | </label> |
| 50 | <div class="position-relative"> |
| 51 | <input id="bs-pw2" type="password" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px;padding-right:36px" placeholder="••••••••" /> |
| 52 | <button type="button" class="btn btn-link position-absolute p-1 text-decoration-none" data-bsfor="bs-pw2" aria-label="Toggle password" style="right:8px;top:50%;transform:translateY(-50%);color:#525252"> |
| 53 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> |
| 54 | <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/> |
| 55 | <circle cx="12" cy="12" r="3"/> |
| 56 | </svg> |
| 57 | </button> |
| 58 | </div> |
| 59 | </div> |
| 60 | </div> |
| 61 | <div class="form-check mb-3"> |
| 62 | <input class="form-check-input" type="checkbox" value="" id="bs-terms" checked style="accent-color:#00FF41"> |
| 63 | <label class="form-check-label text-[#A0A0A0]" for="bs-terms" style="font-size:12px"> |
| 64 | I agree to the |
| 65 | <a href="#" style="color:#00FF41"> |
| 66 | Terms |
| 67 | </a> |
| 68 | </label> |
| 69 | </div> |
| 70 | <button type="submit" class="btn w-100 fw-semibold" style="--bs-btn-bg:#00FF41;--bs-btn-color:#0A0A0A;--bs-btn-border-color:#00FF41;--bs-btn-hover-bg:#00E63A;font-size:13px"> |
| 71 | Create Account |
| 72 | </button> |
| 73 | <hr style="border-color:#222;margin:20px 0" /> |
| 74 | <p class="text-center" style="font-size:11px;color:#525252"> |
| 75 | By signing up you agree to our |
| 76 | <a href="#" style="color:#808080"> |
| 77 | Terms of Service |
| 78 | </a> |
| 79 | </p> |
| 80 | </form> |
| 81 | </div> |
| 82 | </div> |
| 83 | </div> |
A focused login card with email, password, remember-me toggle, and a forgot-password link. Keep it simple and scannable.
| 1 | <div class="form-card" style="max-width:380px"> |
| 2 | <h2 class="form-title"> |
| 3 | Welcome back |
| 4 | </h2> |
| 5 | <p class="form-sub"> |
| 6 | Sign in to your account |
| 7 | </p> |
| 8 | <div class="field"> |
| 9 | <label class="label" for="lg-email"> |
| 10 | |
| 11 | </label> |
| 12 | <input class="input" id="lg-email" type="email" placeholder="you@example.com" /> |
| 13 | </div> |
| 14 | <div class="field"> |
| 15 | <label class="label" for="lg-password"> |
| 16 | Password |
| 17 | </label> |
| 18 | <input class="input" id="lg-password" type="password" placeholder="••••••••" /> |
| 19 | </div> |
| 20 | <div class="row-between"> |
| 21 | <label class="checkbox-label"> |
| 22 | <input type="checkbox" /> |
| 23 | Remember me |
| 24 | </label> |
| 25 | <a href="#" class="link"> |
| 26 | Forgot password? |
| 27 | </a> |
| 28 | </div> |
| 29 | <button class="btn"> |
| 30 | Sign In |
| 31 | </button> |
| 32 | <p class="footer-text"> |
| 33 | Don't have an account? |
| 34 | <a href="#" class="link"> |
| 35 | Sign up |
| 36 | </a> |
| 37 | </p> |
| 38 | </div> |
| 1 | .form-card { |
| 2 | max-width:380px; |
| 3 | margin:24px auto; |
| 4 | background:#111; |
| 5 | border:1px solid #222; |
| 6 | border-radius:12px; |
| 7 | padding:28px; |
| 8 | font-family:system-ui, |
| 9 | sans-serif |
| 10 | } |
| 11 | .form-title { |
| 12 | font-size:18px; |
| 13 | font-weight:700; |
| 14 | color:#E0E0E0; |
| 15 | margin:0 0 4px 0 |
| 16 | } |
| 17 | .form-sub { |
| 18 | font-size:12px; |
| 19 | color:#808080; |
| 20 | margin:0 0 24px 0 |
| 21 | } |
| 22 | .field { |
| 23 | margin-bottom:16px |
| 24 | } |
| 25 | .label { |
| 26 | display:block; |
| 27 | font-size:11px; |
| 28 | font-weight:600; |
| 29 | color:#A0A0A0; |
| 30 | margin-bottom:5px |
| 31 | } |
| 32 | .input { |
| 33 | width:100%; |
| 34 | padding:10px 12px; |
| 35 | border-radius:6px; |
| 36 | font-size:13px; |
| 37 | font-family:inherit; |
| 38 | background:#0A0A0A; |
| 39 | border:1.5px solid #2A2A3E; |
| 40 | color:#E0E0E0; |
| 41 | outline:none; |
| 42 | transition:border-color .2s; |
| 43 | box-sizing:border-box |
| 44 | } |
| 45 | .input:focus { |
| 46 | border-color:#00FF41; |
| 47 | box-shadow:0 0 0 3px rgba(0, |
| 48 | 255, |
| 49 | 65, |
| 50 | .1) |
| 51 | } |
| 52 | .input::placeholder { |
| 53 | color:#525252 |
| 54 | } |
| 55 | .row-between { |
| 56 | display:flex; |
| 57 | align-items:center; |
| 58 | justify-content:space-between; |
| 59 | margin-bottom:20px; |
| 60 | font-size:12px |
| 61 | } |
| 62 | .checkbox-label { |
| 63 | display:flex; |
| 64 | align-items:center; |
| 65 | gap:8px; |
| 66 | color:#A0A0A0; |
| 67 | cursor:pointer |
| 68 | } |
| 69 | .checkbox-label input { |
| 70 | width:16px; |
| 71 | height:16px; |
| 72 | accent-color:#00FF41 |
| 73 | } |
| 74 | .link { |
| 75 | color:#00FF41; |
| 76 | text-decoration:none; |
| 77 | font-size:12px |
| 78 | } |
| 79 | .link:hover { |
| 80 | text-decoration:underline |
| 81 | } |
| 82 | .btn { |
| 83 | width:100%; |
| 84 | padding:10px; |
| 85 | border-radius:8px; |
| 86 | font-size:13px; |
| 87 | font-weight:600; |
| 88 | font-family:inherit; |
| 89 | cursor:pointer; |
| 90 | background:#00FF41; |
| 91 | color:#0A0A0A; |
| 92 | border:none; |
| 93 | transition:all .2s |
| 94 | } |
| 95 | .btn:hover { |
| 96 | background:#00E63A |
| 97 | } |
| 98 | .footer-text { |
| 99 | font-size:11px; |
| 100 | color:#525252; |
| 101 | text-align:center; |
| 102 | margin-top:18px; |
| 103 | margin-bottom:0 |
| 104 | } |
| 105 | .footer-text a { |
| 106 | color:#00FF41 |
| 107 | } |
| 1 | <div class="max-w-sm mx-auto my-6 p-7 rounded-xl bg-[#111] border border-[#222] font-sans"> |
| 2 | <h2 class="text-lg font-bold text-[#E0E0E0] mb-1"> |
| 3 | Welcome back |
| 4 | </h2> |
| 5 | <p class="text-xs text-[#808080] mb-6"> |
| 6 | Sign in to your account |
| 7 | </p> |
| 8 | <div class="mb-4"> |
| 9 | <label for="tw-lg-email" class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 10 | |
| 11 | </label> |
| 12 | <input id="tw-lg-email" type="email" placeholder="you@example.com" class="w-full px-3 py-2 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 13 | </div> |
| 14 | <div class="mb-4"> |
| 15 | <label for="tw-lg-password" class="block text-[11px] font-semibold text-[#A0A0A0] mb-1"> |
| 16 | Password |
| 17 | </label> |
| 18 | <input id="tw-lg-password" type="password" placeholder="••••••••" class="w-full px-3 py-2 rounded-md text-[13px] bg-[#0A0A0A] border-[1.5px] border-[#2A2A3E] text-[#E0E0E0] placeholder:text-[#525252] focus:border-[#00FF41] focus:outline-none focus:ring-[3px] focus:ring-[rgba(0,255,65,0.1)]" /> |
| 19 | </div> |
| 20 | <div class="flex items-center justify-between mb-5 text-xs"> |
| 21 | <label class="flex items-center gap-2 text-[#A0A0A0] cursor-pointer"> |
| 22 | <input type="checkbox" class="w-4 h-4 accent-[#00FF41]" /> |
| 23 | Remember me |
| 24 | </label> |
| 25 | <a href="#" class="text-[#00FF41] hover:underline"> |
| 26 | Forgot password? |
| 27 | </a> |
| 28 | </div> |
| 29 | <button class="w-full px-4 py-2.5 rounded-lg text-[13px] font-semibold bg-[#00FF41] text-[#0A0A0A] hover:bg-[#00E63A] transition-colors"> |
| 30 | Sign In |
| 31 | </button> |
| 32 | <p class="text-[11px] text-[#525252] text-center mt-5 mb-0"> |
| 33 | Don't have an account? |
| 34 | <a href="#" class="text-[#00FF41] hover:underline"> |
| 35 | Sign up |
| 36 | </a> |
| 37 | </p> |
| 38 | </div> |
| 1 | <div class="container py-4" style="max-width:380px"> |
| 2 | <div class="card bg-[#111] border-[#222]"> |
| 3 | <div class="card-body"> |
| 4 | <h2 class="card-title" style="color:#E0E0E0;font-size:18px"> |
| 5 | Welcome back |
| 6 | </h2> |
| 7 | <p class="card-text" style="color:#808080;font-size:12px"> |
| 8 | Sign in to your account |
| 9 | </p> |
| 10 | <form class="mt-4"> |
| 11 | <div class="mb-3"> |
| 12 | <label for="bs-lg-email" class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 13 | |
| 14 | </label> |
| 15 | <input id="bs-lg-email" type="email" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="you@example.com" /> |
| 16 | </div> |
| 17 | <div class="mb-3"> |
| 18 | <label for="bs-lg-password" class="form-label text-[#A0A0A0]" style="font-size:11px;font-weight:600"> |
| 19 | Password |
| 20 | </label> |
| 21 | <input id="bs-lg-password" type="password" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="••••••••" /> |
| 22 | </div> |
| 23 | <div class="d-flex align-items-center justify-content-between mb-4"> |
| 24 | <div class="form-check"> |
| 25 | <input class="form-check-input" type="checkbox" value="" id="bs-remember" style="accent-color:#00FF41"> |
| 26 | <label class="form-check-label text-[#A0A0A0]" for="bs-remember" style="font-size:12px"> |
| 27 | Remember me |
| 28 | </label> |
| 29 | </div> |
| 30 | <a href="#" style="font-size:12px;color:#00FF41;text-decoration:none"> |
| 31 | Forgot password? |
| 32 | </a> |
| 33 | </div> |
| 34 | <button type="submit" class="btn w-100 fw-semibold" style="--bs-btn-bg:#00FF41;--bs-btn-color:#0A0A0A;--bs-btn-border-color:#00FF41;--bs-btn-hover-bg:#00E63A;font-size:13px"> |
| 35 | Sign In |
| 36 | </button> |
| 37 | <p class="text-center mt-3 mb-0" style="font-size:11px;color:#525252"> |
| 38 | Don't have an account? |
| 39 | <a href="#" style="color:#00FF41;text-decoration:none"> |
| 40 | Sign up |
| 41 | </a> |
| 42 | </p> |
| 43 | </form> |
| 44 | </div> |
| 45 | </div> |
| 46 | </div> |
A compact single-row form ideal for newsletter signups, search bars, or command inputs. Uses flexbox to keep the button attached to the input.
| 1 | <div class="inline-wrap"> |
| 2 | <input class="inline-input" type="email" placeholder="Enter your email" aria-label="Email" /> |
| 3 | <button class="inline-btn"> |
| 4 | Subscribe |
| 5 | </button> |
| 6 | </div> |
| 1 | .inline-wrap { |
| 2 | max-width:480px; |
| 3 | margin:40px auto; |
| 4 | display:flex; |
| 5 | align-items:stretch; |
| 6 | border-radius:8px; |
| 7 | overflow:hidden; |
| 8 | border:1.5px solid #2A2A3E; |
| 9 | background:#0A0A0A; |
| 10 | font-family:system-ui, |
| 11 | sans-serif |
| 12 | } |
| 13 | .inline-input { |
| 14 | flex:1; |
| 15 | border:none; |
| 16 | padding:12px 16px; |
| 17 | font-size:13px; |
| 18 | font-family:inherit; |
| 19 | background:transparent; |
| 20 | color:#E0E0E0; |
| 21 | outline:none |
| 22 | } |
| 23 | .inline-input::placeholder { |
| 24 | color:#525252 |
| 25 | } |
| 26 | .inline-btn { |
| 27 | padding:12px 22px; |
| 28 | border:none; |
| 29 | background:#00FF41; |
| 30 | color:#0A0A0A; |
| 31 | font-size:13px; |
| 32 | font-weight:600; |
| 33 | cursor:pointer; |
| 34 | transition:background .2s |
| 35 | } |
| 36 | .inline-btn:hover { |
| 37 | background:#00E63A |
| 38 | } |
| 1 | <div class="max-w-lg mx-auto my-10 flex items-stretch rounded-lg overflow-hidden border-[1.5px] border-[#2A2A3E] bg-[#0A0A0A] font-sans"> |
| 2 | <input type="email" placeholder="Enter your email" aria-label="Email" class="flex-1 px-4 py-3 text-[13px] bg-transparent text-[#E0E0E0] placeholder:text-[#525252] border-0 focus:outline-none" /> |
| 3 | <button class="px-6 py-3 bg-[#00FF41] text-[#0A0A0A] text-[13px] font-semibold hover:bg-[#00E63A] transition-colors"> |
| 4 | Subscribe |
| 5 | </button> |
| 6 | </div> |
| 1 | <div class="container py-4" style="max-width:480px"> |
| 2 | <div class="input-group"> |
| 3 | <input type="email" class="form-control bg-[#0A0A0A] border-[#2A2A3E] text-[#E0E0E0] placeholder-[#525252]" style="font-size:13px" placeholder="Enter your email" aria-label="Email"> |
| 4 | <button class="btn fw-semibold" style="--bs-btn-bg:#00FF41;--bs-btn-color:#0A0A0A;--bs-btn-border-color:#00FF41;--bs-btn-hover-bg:#00E63A;font-size:13px" type="button"> |
| 5 | Subscribe |
| 6 | </button> |
| 7 | </div> |
| 8 | </div> |
A drag-and-drop style file input using a hidden native input and a styled label. The native control remains accessible and keyboard focusable.
| 1 | <div class="upload-wrap"> |
| 2 | <input class="upload-input" id="file" type="file" /> |
| 3 | <label class="upload-label" for="file"> |
| 4 | <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> |
| 5 | <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/> |
| 6 | <polyline points="17 8 12 3 7 8"/> |
| 7 | <line x1="12" y1="3" x2="12" y2="15"/> |
| 8 | </svg> |
| 9 | <span class="upload-title"> |
| 10 | Click or drag file to upload |
| 11 | </span> |
| 12 | <span class="upload-hint"> |
| 13 | SVG, PNG, JPG up to 2MB |
| 14 | </span> |
| 15 | </label> |
| 16 | </div> |
| 1 | .upload-wrap { |
| 2 | max-width:400px; |
| 3 | margin:24px auto; |
| 4 | font-family:system-ui, |
| 5 | sans-serif |
| 6 | } |
| 7 | .upload-input { |
| 8 | position:absolute; |
| 9 | opacity:0; |
| 10 | width:1px; |
| 11 | height:1px |
| 12 | } |
| 13 | .upload-label { |
| 14 | display:flex; |
| 15 | flex-direction:column; |
| 16 | align-items:center; |
| 17 | gap:10px; |
| 18 | padding:32px 24px; |
| 19 | border-radius:12px; |
| 20 | border:2px dashed #2A2A3E; |
| 21 | background:#0A0A0A; |
| 22 | color:#A0A0A0; |
| 23 | cursor:pointer; |
| 24 | transition:all .2s |
| 25 | } |
| 26 | .upload-label:hover, |
| 27 | .upload-input:focus+.upload-label { |
| 28 | border-color:#00FF41; |
| 29 | background:#111; |
| 30 | color:#E0E0E0 |
| 31 | } |
| 32 | .upload-label svg { |
| 33 | color:#525252; |
| 34 | transition:color .2s |
| 35 | } |
| 36 | .upload-label:hover svg, |
| 37 | .upload-input:focus+.upload-label svg { |
| 38 | color:#00FF41 |
| 39 | } |
| 40 | .upload-title { |
| 41 | font-size:13px; |
| 42 | font-weight:600 |
| 43 | } |
| 44 | .upload-hint { |
| 45 | font-size:11px; |
| 46 | color:#525252 |
| 47 | } |
| 1 | <div class="max-w-sm mx-auto my-6 font-sans"> |
| 2 | <input id="tw-file" type="file" class="absolute opacity-0 w-px h-px" /> |
| 3 | <label for="tw-file" class="flex flex-col items-center gap-2.5 px-6 py-8 rounded-xl border-2 border-dashed border-[#2A2A3E] bg-[#0A0A0A] text-[#A0A0A0] cursor-pointer transition-colors hover:border-[#00FF41] hover:bg-[#111] hover:text-[#E0E0E0] has-[:focus]:border-[#00FF41]"> |
| 4 | <svg class="w-8 h-8 text-[#525252] group-hover:text-[#00FF41]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> |
| 5 | <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/> |
| 6 | <polyline points="17 8 12 3 7 8"/> |
| 7 | <line x1="12" y1="3" x2="12" y2="15"/> |
| 8 | </svg> |
| 9 | <span class="text-[13px] font-semibold"> |
| 10 | Click or drag file to upload |
| 11 | </span> |
| 12 | <span class="text-[11px] text-[#525252]"> |
| 13 | SVG, PNG, JPG up to 2MB |
| 14 | </span> |
| 15 | </label> |
| 16 | </div> |
| 1 | <div class="container py-4" style="max-width:400px"> |
| 2 | <input id="bs-file" type="file" style="position:absolute;opacity:0;width:1px;height:1px"> |
| 3 | <label for="bs-file" class="d-flex flex-column align-items-center gap-2 p-4 rounded-3 border-2 border-dashed text-center" style="border-color:#2A2A3E;background:#0A0A0A;color:#A0A0A0;cursor:pointer;transition:all .2s" onmouseover="this.style.borderColor='#00FF41';this.style.background='#111';this.style.color='#E0E0E0'" onmouseout="this.style.borderColor='#2A2A3E';this.style.background='#0A0A0A';this.style.color='#A0A0A0'"> |
| 4 | <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> |
| 5 | <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/> |
| 6 | <polyline points="17 8 12 3 7 8"/> |
| 7 | <line x1="12" y1="3" x2="12" y2="15"/> |
| 8 | </svg> |
| 9 | <span style="font-size:13px;font-weight:600"> |
| 10 | Click or drag file to upload |
| 11 | </span> |
| 12 | <span style="font-size:11px;color:#525252"> |
| 13 | SVG, PNG, JPG up to 2MB |
| 14 | </span> |
| 15 | </label> |
| 16 | </div> |
Accessible forms are usable forms. Labels, focus states, error announcements, and logical tab order reduce friction for keyboard and screen-reader users.
- Associate every input with a <label> using htmlFor / for or by nesting the input inside the label.
- Use aria-invalid and aria-describedby to link inputs to their error messages.
- Ensure focus indicators are visible — never remove outline without replacing it with a ring or border change.
- Mark required fields visually and programmatically with the required attribute.
- Group related controls like radios and checkboxes with <fieldset> and <legend>.
- Keep error messages specific and actionable; announce them with role="alert" when they appear dynamically.
Community
Get help on Slack, Discord or VIP
Stuck on a guide? Join the community and ask.