Terminal die zichzelf typt New
Terminal window where commands type themselves letter by letter and output appears line by line: build, tests and publishing of a bakery website. Starts only when it scrolls into view, has a pause, resume and replay button and a full text version for screen readers. With reduced motion everything appears at once. For developer tools, SaaS landing pages and technical explainers.
vermeer $ git pull 3 bestanden bijgewerkt: herfstmenu vermeer $ npm run build 42 pagina's gebouwd in 3,1 s Foto's verkleind: 18,4 MB naar 2,7 MB vermeer $ npm test 128 tests geslaagd, 0 mislukt vermeer $ ./publiceer.sh Back-up gemaakt om 09:41 17 bestanden geüpload (1,2 MB) Live op bakkerij-vermeer.voorbeeld.nl
How to use it
- Paste the HTML where the numbers & charts 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.
<!-- Terminal die zichzelf typt · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="trm">
<div class="trm__bar"><p class="trm__name">bakkerij-vermeer · website publiceren</p><button type="button" class="trm__btn">Pauze</button></div>
<div class="trm__body" aria-hidden="true"><div class="trm__lines"></div></div>
<pre class="trm__sr">vermeer $ git pull
3 bestanden bijgewerkt: herfstmenu
vermeer $ npm run build
42 pagina's gebouwd in 3,1 s
Foto's verkleind: 18,4 MB naar 2,7 MB
vermeer $ npm test
128 tests geslaagd, 0 mislukt
vermeer $ ./publiceer.sh
Back-up gemaakt om 09:41
17 bestanden geüpload (1,2 MB)
Live op bakkerij-vermeer.voorbeeld.nl</pre>
</div>
</div>/* Terminal die zichzelf typt · NedDev · eigen werk. */
.trm{position:absolute;inset:12px;box-sizing:border-box;background:#0a0a0a;color:#ecebe8;border-radius:8px;display:flex;flex-direction:column;overflow:hidden;font-family:'Switzer',sans-serif}
.trm__bar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 8px 6px 12px;border-bottom:1px solid #2a2a29}
.trm__name{margin:0;font-size:12px;color:#a9a7a2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.trm__btn{flex:none;min-height:26px;min-width:64px;padding:0 10px;border:1px solid #4a4947;border-radius:4px;background:transparent;color:#fff;font:600 12px 'Switzer',sans-serif;cursor:pointer;transition:background-color .15s,border-color .15s}
.trm__btn:hover{background:#262625;border-color:#6b6a66}
.trm__btn:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.trm__body{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;justify-content:flex-end;padding:8px 12px 10px;-webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 28px);mask-image:linear-gradient(to bottom,transparent 0,#000 28px)}
.trm__lines{font:12px/1.6 'JetBrains Mono',ui-monospace,'SFMono-Regular',Menlo,monospace;white-space:pre-wrap;word-break:break-word}
.trm__l{margin:0;min-height:1.6em}
.trm__p{color:#F5480F}
.trm__o{color:#a9a7a2}
.trm__ok{color:#ecebe8}
.trm__ok::before{content:'✓ ';color:#F5480F}
.trm__caret{display:inline-block;width:.6em;height:1.15em;margin-left:1px;vertical-align:-.2em;background:#F5480F;animation:trm-blink 1s steps(1) infinite}
@keyframes trm-blink{50%{opacity:0}}
.trm__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:pre;margin:0}
@media(prefers-reduced-motion:reduce){.trm__caret{animation:none}.trm__btn{display:none}}// Terminal die zichzelf typt · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.trm');if(!w)return;
var box=w.querySelector('.trm__lines'),btn=w.querySelector('.trm__btn');
var S=[{c:'git pull'},{o:'3 bestanden bijgewerkt: herfstmenu'},{c:'npm run build'},{o:"42 pagina's gebouwd in 3,1 s",ok:1},{o:"Foto's verkleind: 18,4 MB naar 2,7 MB",ok:1},{c:'npm test'},{o:'128 tests geslaagd, 0 mislukt',ok:1},{c:'./publiceer.sh'},{o:'Back-up gemaakt om 09:41'},{o:'17 bestanden geüpload (1,2 MB)'},{o:'Live op bakkerij-vermeer.voorbeeld.nl',ok:1}];
var i=0,ch=0,cur=null,state='idle',timer=null;
function line(cls){var p=document.createElement('p');p.className='trm__l '+cls;box.appendChild(p);while(box.children.length>14)box.removeChild(box.firstChild);return p;}
function prompt(p){p.innerHTML='<span class="trm__p">vermeer $</span> <span class="trm__in"></span>';}
function caret(p){var c=document.createElement('span');c.className='trm__caret';p.appendChild(c);}
function setBtn(){btn.textContent=state==='play'?'Pauze':state==='pause'?'Verder':'Opnieuw';btn.setAttribute('aria-label',state==='play'?'Animatie pauzeren':state==='pause'?'Animatie hervatten':'Animatie opnieuw afspelen');}
function finish(){var p=line('');prompt(p);caret(p);state='done';setBtn();}
function step(){timer=null;if(state!=='play')return;if(i>=S.length){finish();return;}var s=S[i];
if(s.c!==undefined){if(!cur){cur=line('');prompt(cur);caret(cur);ch=0;}var inp=cur.querySelector('.trm__in');
if(ch<s.c.length){inp.textContent=s.c.slice(0,++ch);timer=setTimeout(step,45+Math.random()*75);return;}
var cr=cur.querySelector('.trm__caret');if(cr)cr.remove();cur=null;i++;timer=setTimeout(step,420);return;}
var l=line('trm__o'+(s.ok?' trm__ok':''));l.textContent=s.o;i++;timer=setTimeout(step,S[i]&&S[i].c!==undefined?650:160);}
function all(){box.textContent='';S.forEach(function(s){var p=line(s.c!==undefined?'':'trm__o'+(s.ok?' trm__ok':''));if(s.c!==undefined){prompt(p);p.querySelector('.trm__in').textContent=s.c;}else p.textContent=s.o;});var p=line('');prompt(p);state='done';setBtn();}
function start(){box.textContent='';i=0;ch=0;cur=null;state='play';setBtn();step();}
btn.addEventListener('click',function(){if(state==='play'){state='pause';clearTimeout(timer);timer=null;}else if(state==='pause'){state='play';step();}else start();setBtn();});
if(matchMedia('(prefers-reduced-motion:reduce)').matches){all();return;}
var p0=line('');prompt(p0);caret(p0);
if(!('IntersectionObserver' in window)){start();return;}
var io=new IntersectionObserver(function(es){if(es[0].isIntersecting){io.disconnect();start();}},{threshold:.4});io.observe(w);
}
init(document.querySelector('.jouw-container'));
More numbers & charts
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 →