Meegroeiend tekstvak met teller New
Auto-growing textarea with a character counter that turns from grey to amber and red at the limit; past the limit it counts the excess and keeps the button disabled instead of silently cutting text. Uses field-sizing:content (fallback: small JS height sync) and announces thresholds via aria-live.
Demo
Welke ruimtes, ongeveer hoeveel m² en wanneer het klaar moet zijn.
How to use it
- Paste the HTML where the forms & inputs should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Meegroeiend tekstvak met teller · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="ttv"><div class="ttv__in">
<div class="ttv__demo" role="group" aria-label="Demo: kies een staat"><span class="ttv__demo-l">Demo</span><button type="button" data-d="bijna">Bijna vol</button><button type="button" data-d="te">Te lang</button><button type="button" data-d="leeg">Leeg</button></div>
<div class="ttv__card">
<label class="ttv__l" for="ttv-t">Omschrijf de klus</label>
<p class="ttv__help" id="ttv-h">Welke ruimtes, ongeveer hoeveel m² en wanneer het klaar moet zijn.</p>
<textarea class="ttv__t" id="ttv-t" rows="2" aria-describedby="ttv-h ttv-c" placeholder="Bijvoorbeeld: woonkamer en gang schilderen, plafond en muren, ongeveer 60 m²"></textarea>
<div class="ttv__meta"><span class="ttv__bar" aria-hidden="true"><i></i></span><span class="ttv__c" id="ttv-c">0 / 280</span></div>
<div class="ttv__act"><button class="ttv__btn" type="button" disabled>Vraag offerte aan</button></div>
<p class="ttv__sr" aria-live="polite"></p>
</div></div></div>
</div>/* Meegroeiend tekstvak met teller · NedDev · eigen werk. */
.ttv [hidden]{display:none!important}
.ttv{position:absolute;inset:0;overflow:auto;display:flex;padding:14px;box-sizing:border-box;background:#f4f3f1;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;scrollbar-width:thin}
.ttv *,.ttv *::before,.ttv *::after{box-sizing:border-box}
.ttv__in{margin:auto;width:100%;max-width:520px}
.ttv__demo{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:8px;font:500 10px 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase}
.ttv__demo-l{color:#5a5a5a}
.ttv__demo button{font:inherit;letter-spacing:inherit;text-transform:inherit;padding:5px 9px;border:1px solid rgba(10,10,10,.25);background:#fff;color:#0a0a0a;border-radius:100px;cursor:pointer;transition:border-color .15s}
.ttv__demo button:hover{border-color:#0a0a0a}
.ttv__card{background:#fff;border:1px solid rgba(10,10,10,.12);border-radius:6px;padding:14px}
.ttv__l{display:block;font-size:14px;font-weight:700}
.ttv__help{margin:2px 0 8px;font-size:12.5px;color:#5a5a5a;line-height:1.4}
.ttv__t{display:block;width:100%;font:400 14px/1.5 'Switzer',system-ui,sans-serif;color:#0a0a0a;background:#fff;border:1px solid #8c8c8c;border-radius:4px;padding:9px 11px;resize:none;min-height:64px;max-height:150px;overflow-y:auto;transition:border-color .15s,box-shadow .15s}
@supports (field-sizing:content){.ttv__t{field-sizing:content}}
.ttv__t:hover{border-color:#0a0a0a}
.ttv__t:focus-visible{outline:none;border-color:#0a0a0a;box-shadow:0 0 0 3px rgba(245,72,15,.35)}
.ttv__t::placeholder{color:#757575}
.ttv[data-s="over"] .ttv__t{border-color:#B42318}
.ttv__meta{display:flex;align-items:center;gap:10px;margin-top:6px}
.ttv__bar{flex:1;height:3px;background:#e7e4df;border-radius:2px;overflow:hidden}
.ttv__bar i{display:block;height:100%;width:0;background:#0a0a0a;transition:width .15s,background .15s}
.ttv__c{flex:none;font:500 11.5px 'JetBrains Mono',monospace;color:#5a5a5a;transition:color .15s}
.ttv[data-s="bijna"] .ttv__c{color:#8A4B00}.ttv[data-s="bijna"] .ttv__bar i{background:#F5480F}
.ttv[data-s="vol"] .ttv__c,.ttv[data-s="over"] .ttv__c{color:#B42318;font-weight:700}.ttv[data-s="vol"] .ttv__bar i,.ttv[data-s="over"] .ttv__bar i{background:#B42318}
.ttv__act{margin-top:10px}
.ttv__btn{font:600 13.5px 'Switzer',system-ui,sans-serif;padding:9px 16px;border-radius:4px;border:1px solid #0a0a0a;background:#0a0a0a;color:#fff;cursor:pointer;transition:background .15s,color .15s,border-color .15s}
.ttv__btn:hover:not(:disabled){background:#F5480F;border-color:#F5480F;color:#0a0a0a}
.ttv__btn:disabled{background:#e4e2de;border-color:#e4e2de;color:#5a5a5a;cursor:not-allowed}
.ttv__btn:focus-visible,.ttv__demo button:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.ttv__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:0}
@media (prefers-reduced-motion:reduce){.ttv *{transition:none!important}}// Meegroeiend tekstvak met teller · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.ttv')||root;
var sfx='-'+Math.random().toString(36).slice(2,7);['ttv-t','ttv-h','ttv-c'].forEach(function(o){var el=root.querySelector('#'+o);if(el)el.id=o+sfx;});
var t=root.querySelector('.ttv__t'),c=root.querySelector('.ttv__c'),fill=root.querySelector('.ttv__bar i'),btn=root.querySelector('.ttv__btn'),sr=root.querySelector('.ttv__sr'),MAX=280,last='';
root.querySelector('.ttv__l').setAttribute('for',t.id);t.setAttribute('aria-describedby',root.querySelector('.ttv__help').id+' '+c.id);
var fit=!(window.CSS&&CSS.supports&&CSS.supports('field-sizing','content'));
function grow(){if(!fit)return;t.style.height='auto';t.style.height=Math.min(t.scrollHeight+2,150)+'px';}
function upd(){var n=t.value.length,s=n>MAX?'over':n===MAX?'vol':n>=MAX*.9?'bijna':'ok';root.setAttribute('data-s',s);
fill.style.width=Math.min(100,n/MAX*100)+'%';c.textContent=n>MAX?(n-MAX)+(n-MAX===1?' teken':' tekens')+' te veel':n+' / '+MAX;
btn.disabled=!t.value.trim()||n>MAX;btn.textContent='Vraag offerte aan';
if(n>MAX)t.setAttribute('aria-invalid','true');else t.removeAttribute('aria-invalid');
var msg=s==='bijna'?'Nog '+(MAX-n)+' tekens':s==='vol'?'Limiet bereikt':s==='over'?'Te lang, haal '+(n-MAX)+' tekens weg':'';if(msg!==last&&(s!=='bijna'||last.indexOf('Nog')<0||(MAX-n)%10===0)){sr.textContent=msg;last=msg;}if(s==='ok')last='';grow();}
t.addEventListener('input',upd);
btn.addEventListener('click',function(){btn.textContent='Aanvraag verstuurd';btn.disabled=true;sr.textContent='Je aanvraag is verstuurd';});
var TXT='Woonkamer en gang laten schilderen, plafond en muren, samen ongeveer 60 m². De kozijnen aan de binnenkant mogen ook mee. We zijn vanaf 3 november twee weken weg, het liefst gebeurt het in die periode. Parkeren kan voor de deur. Er staat een piano in de kamer die niet weg kan, die dekken we graag samen af. Graag een prijs inclusief materiaal.';
root.querySelector('.ttv__demo').addEventListener('click',function(e){var b=e.target.closest('button');if(!b)return;var d=b.dataset.d;
t.value=d==='leeg'?'':d==='bijna'?TXT.slice(0,262):TXT.slice(0,293);upd();});
upd();
}
init(document.querySelector('.jouw-container'));
More forms & inputs
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →