Meegroeiend tekstvak met teller Nieuw
Tekstvak dat meegroeit met de tekst en een tekenteller die van grijs naar oranje en rood gaat bij de limiet; boven de limiet telt hij de tekens te veel en blijft de knop uit, in plaats van tekst stil af te kappen. Gebruikt field-sizing:content (fallback: kleine JS die de hoogte zet) en meldt drempels via aria-live.
Demo
Welke ruimtes, ongeveer hoeveel m² en wanneer het klaar moet zijn.
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- 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'));
Meer uit formulieren & invoer
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →