Puttin' the eek back in geek

CSS3 C64, a Commodore 64 demo in your browser

December 15, 2013

I wanted to see how far I could get to “emulating” a Commodore 64 without using JavaScript. Turns out you can build a sweet little C64 demo with just some plain old HTML, CSS, an image and a handful of fonts — and not a single byte of JavaScript 1. The following thingy is a little something I worked on during the train ride to work: CSS3 C64.

The logo was created with Christian Heilmann’s C64 charset logo generator. The two fonts were scavaged online. One is the default C64 font, the second one is from Giana Sisters.

This is the HTML the page runs on:

 1 <!doctype html>
 2 <html>
 3 <head>
 4     <title>CSS3 C64 by Pixelambacht</title>
 5     <link href="css.css" rel="stylesheet">
 6 
 7     <script src="prefixfree.min.js"></script>
 8 </head>
 9 <body>
10 
11   <textarea class="spacebar" required autofocus spellcheck="false"></textarea>
12 
13   <section class="bluescreen">
14     <ul class="loading">
15       <li>
16       <li>
17       <li>
18       <li>
19       <li>
20     </ul>
21   </section>
22 
23   <section class="introscreen">
24     <div class="logo"></div>
25     <ul class="presents">
26       <li>
27       <li>
28     </ul>
29     <ul class="starfield">
30       <li>
31       <li>
32       <li>
33       <li>
34       <li>
35       <li><br>
36       <li>
37       <li>
38       <li>
39       <li>
40       <li>
41       <li><br>
42       <li>
43       <li>
44       <li>
45       <li>
46       <li>
47       <li><br>
48     </ul>
49     <p class="scrolltext"></p>
50   </section>
51 
52   <a href="http://pixelambacht.nl/2013/css3-c64/" class="credits">CSS3 C64 By Pixelambacht </a>
53 
54 </body>
55 </html>

The CSS is not really earth-shattering clever and not necessarily the best way to achieve these animations, but it takes care of all the effects:

  1 /* http://meyerweb.com/eric/tools/css/reset/
  2    v2.0 | 20110126
  3    License: none (public domain)
  4 */
  5 html, body, div, span, applet, object, iframe,
  6 h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  7 a, abbr, acronym, address, big, cite, code,
  8 del, dfn, em, img, ins, kbd, q, s, samp,
  9 small, strike, strong, sub, sup, tt, var,
 10 b, u, i, center,
 11 dl, dt, dd, ol, ul, li,
 12 fieldset, form, label, legend,
 13 table, caption, tbody, tfoot, thead, tr, th, td,
 14 article, aside, canvas, details, embed,
 15 figure, figcaption, footer, header, hgroup,
 16 menu, nav, output, ruby, section, summary,
 17 time, mark, audio, video {
 18   margin: 0;
 19   padding: 0;
 20   border: 0;
 21   font-size: 100%;
 22   font: inherit;
 23   vertical-align: baseline;
 24 }
 25 /* HTML5 display-role reset for older browsers */
 26 article, aside, details, figcaption, figure,
 27 footer, header, hgroup, menu, nav, section {
 28   display: block;
 29 }
 30 body {
 31   line-height: 1;
 32 }
 33 ol, ul {
 34   list-style: none;
 35 }
 36 blockquote, q {
 37   quotes: none;
 38 }
 39 blockquote:before, blockquote:after,
 40 q:before, q:after {
 41   content: '';
 42   content: none;
 43 }
 44 table {
 45   border-collapse: collapse;
 46   border-spacing: 0;
 47 }
 48 *, *:before, *:after {
 49   -moz-box-sizing: border-box; box-sizing: border-box; box-sizing: border-box;
 50 }
 51 
 52 html, body {
 53   height: 100%;
 54   background: #333;
 55 }
 56 .credits {
 57   text-decoration: none;
 58   font: normal 8px "C64 User Mono";
 59   color: #777;
 60   position: absolute;
 61   right: 1em;
 62   bottom: 1em;
 63 }
 64 .credits:hover {
 65   color: #aaa;
 66 }
 67 
 68 /**
 69  * Fonts
 70  */
 71 @font-face {
 72    font-family: "C64 User Mono";
 73    src: url("C64_User_Mono_v1.0-STYLE.eot");
 74    src: url("C64_User_Mono_v1.0-STYLE.eot?#iefix") format("embedded-opentype"),
 75         url("C64_User_Mono_v1.0-STYLE.woff") format("woff"),
 76         url("C64_User_Mono_v1.0-STYLE.ttf") format("truetype");
 77   font-weight: normal;
 78   font-style: normal;
 79 }
 80 @font-face {
 81   font-family: "Giana";
 82   src: url("giana.eot");
 83   src: url("giana.eot?#iefix") format("embedded-opentype"),
 84        url("giana.woff") format("woff"),
 85        url("giana.ttf") format("truetype");
 86   font-weight: normal;
 87   font-style: normal;
 88 }
 89 
 90 /**
 91  * The blue C64 screen
 92  */
 93 .spacebar,
 94 section {
 95   position: absolute;
 96   top: 50%;
 97   left: 50%;
 98   width: 640px;
 99   height: 400px;
100 
101   margin-top: -200px;
102   margin-left: -320px;
103 
104   color: #6076c5;
105   font: normal 16px "C64 User Mono";
106   text-transform: uppercase;
107 
108   z-index: 1;
109 }
110 /* Border of the sceen */
111 section:before {
112   position: absolute;
113   left: -64px;
114   right: -64px;
115   top: -74px;
116   bottom: -74px;
117   content: "";
118   background: #6076c5;
119   z-index: -1;
120 }
121 /* Inside screen */
122 section:after {
123   position: absolute;
124   left: 0;
125   right: 0;
126   top: 0;
127   bottom: 0;
128   content: "";
129   background: #20398d;
130   z-index: -1;
131 }
132 
133 /**
134  * Blue screen animations
135  */
136 @keyframes cursor {
137   0% {
138     background: #20398d;
139   }
140   50% {
141     background: #6076c5;
142   }
143 }
144 @keyframes line_one {
145   from {
146     height: auto;
147     text-indent: 0;
148   }
149   to {
150     height: auto;
151     width: 23em; /* Number of chars + one for cursor */
152     text-indent: 0;
153   }
154 }
155 @keyframes line_two {
156   to {
157     width: 100%;
158     height: 100%;
159   }
160 }
161 @keyframes line_three {
162   from {
163     height: 100%;
164     text-indent: 0;
165   }
166   to {
167     height: 100%;
168     width: 4em; /* Number of chars + one for cursor */
169     text-indent: 0;
170   }
171 }
172 @keyframes decrunch {
173   /* Firefox and IE10 won't animate linear-gradients, so we fall back to full border color change */
174   20% {
175     background: #b8b8b8;
176     background-image: linear-gradient(to bottom, #ffffff 5%,#000000 5%,#000000 10%,#b8b8b8 10%,#b8b8b8 16%,#5090d0 16%,#5090d0 23%,#98ff98 23%,#98ff98 28%,#808080 28%,#808080 33%,#484848 33%,#484848 40%,#c87870 40%,#c87870 46%,#472b1b 46%,#472b1b 51%,#a04800 51%,#a04800 57%,#f0e858 57%,#f0e858 62%,#181090 62%,#181090 69%,#50b818 69%,#50b818 78%,#a838a0 78%,#a838a0 86%,#68d0a8 86%,#68d0a8 95%,#882000 95%);
177   }
178   40% {
179     background: #484848;
180     background-image: linear-gradient(to bottom, #882000 10%,#68d0a8 10%,#68d0a8 12%,#a838a0 12%,#a838a0 18%,#50b818 18%,#50b818 27%,#181090 27%,#181090 38%,#f0e858 38%,#f0e858 41%,#a04800 41%,#a04800 56%,#472b1b 56%,#472b1b 61%,#c87870 61%,#c87870 66%,#484848 66%,#484848 68%,#808080 68%,#808080 75%,#98ff98 75%,#98ff98 77%,#5090d0 77%,#5090d0 92%,#b8b8b8 92%,#b8b8b8 94%,#000000 94%,#000000 97%,#ffffff 97%);
181   }
182   60% {
183     background: #c87870;
184     background-image: linear-gradient(to bottom, #ffffff 5%,#c87870 5%,#c87870 14%,#484848 14%,#484848 22%,#808080 22%,#808080 31%,#98ff98 31%,#98ff98 38%,#5090d0 38%,#5090d0 43%,#b8b8b8 43%,#b8b8b8 49%,#000000 49%,#000000 54%,#68d0a8 54%,#68d0a8 60%,#a838a0 60%,#a838a0 67%,#50b818 67%,#50b818 72%,#181090 72%,#181090 77%,#f0e858 77%,#f0e858 84%,#a04800 84%,#a04800 90%,#472b1b 90%,#472b1b 95%,#882000 95%);
185   }
186   80% {
187     background: #68d0a8;
188     background-image: linear-gradient(to bottom, #882000 5%,#68d0a8 5%,#68d0a8 14%,#a838a0 14%,#a838a0 22%,#50b818 22%,#50b818 31%,#181090 31%,#181090 38%,#f0e858 38%,#f0e858 43%,#a04800 43%,#a04800 49%,#472b1b 49%,#472b1b 54%,#c87870 54%,#c87870 60%,#484848 60%,#484848 67%,#808080 67%,#808080 72%,#98ff98 72%,#98ff98 77%,#5090d0 77%,#5090d0 84%,#b8b8b8 84%,#b8b8b8 90%,#000000 90%,#000000 95%,#ffffff 95%);
189   }
190   100% {
191     background: #50b818;
192     background-image: linear-gradient(to bottom, #ffffff 3%,#000000 3%,#000000 6%,#b8b8b8 6%,#b8b8b8 8%,#5090d0 8%,#5090d0 23%,#98ff98 23%,#98ff98 25%,#808080 25%,#808080 32%,#484848 32%,#484848 34%,#c87870 34%,#c87870 39%,#472b1b 39%,#472b1b 44%,#a04800 44%,#a04800 59%,#f0e858 59%,#f0e858 62%,#181090 62%,#181090 73%,#50b818 73%,#50b818 82%,#a838a0 82%,#a838a0 88%,#68d0a8 88%,#68d0a8 90%,#882000 90%);
193   }
194 }
195 
196 /**
197  * All the typing stuff on the blue screen
198  */
199 .loading {
200   line-height: 1;
201 }
202 .loading li {
203   padding-right: 1em;
204   width: 0;
205   height: 0;
206   overflow: hidden;
207   display: inline-block;
208   position: relative;
209   float: left;
210   clear: left;
211 }
212 .loading li:first-child {
213   height: auto;
214   width: auto;
215 }
216 .loading li:before {
217   white-space: pre;
218 }
219 .spacebar:before,
220 .loading li:first-child:before {
221 
222   content: "\0a     **** commodore 64 basic v2 ****\
223     \0a\0a  64k ram system  38911 basic bytes free\
224     \0a\0aready.";
225 
226 }
227 .loading li:nth-child(2):before {
228   content: "load\"pixelambacht\",8,1";
229 }
230 .loading li:nth-child(3):before {
231   content: "\0asearching for pixelambacht\0aloading";
232 }
233 .loading li:nth-child(4):before {
234   content: "ready.";
235 }
236 .loading li:nth-child(5):before {
237   content: "run";
238 }
239 .loading li:nth-child(2) {
240   width: 1em;
241   height: auto;
242   text-indent: 1em;
243   animation-name: line_one;
244   animation-delay: 2s;
245   animation-duration: 3s;
246   animation-iteration-count: 1;
247   animation-timing-function: steps(22);
248   animation-fill-mode: forwards;
249 }
250 .loading li:nth-child(2):after {
251   width: 1em;
252   height: 1em;
253   background: rgba(0,0,0,0);
254   content: "";
255   position: absolute;
256   top: 0;
257   right: 0;
258   animation-name: cursor;
259   animation-duration: 1s;
260   animation-iteration-count: 7; /* must be even, so we end on invisible cursor */
261   animation-timing-function: steps(1);
262   animation-fill-mode: forwards;
263 }
264 .loading li:nth-child(3) {
265   animation-delay: 7s;
266   animation-duration: 1s;
267   animation-name: line_two;
268   animation-iteration-count: 1;
269   animation-timing-function: steps(1, start);
270   animation-fill-mode: forwards;
271 }
272 .loading li:nth-child(4) {
273   animation-delay: 11s;
274   animation-duration: 1s;
275   animation-name: line_two;
276   animation-iteration-count: 1;
277   animation-timing-function: steps(1, start);
278   animation-fill-mode: forwards;
279 }
280 .loading li:nth-child(5) {
281   width: 1em;
282   height: auto;
283   text-indent: 1em;
284   animation-delay: 12s;
285   animation-duration: 1s;
286   animation-name: line_three;
287   animation-iteration-count: 1;
288   animation-timing-function: steps(3, start);
289   animation-fill-mode: forwards;
290 }
291 .loading li:nth-child(5):after {
292   width: 1em;
293   height: 1em;
294   background: rgba(0,0,0,0);
295   content: "";
296   position: absolute;
297   top: 0;
298   right: 0;
299   animation-name: cursor;
300   animation-duration: 1s;
301   animation-delay: 10.5s;
302   animation-iteration-count: 3; /* must be even, so we end on invisible cursor */
303   animation-timing-function: steps(1);
304   animation-fill-mode: forwards;
305 }
306 
307 /**
308  * Decrunching
309  */
310 section.bluescreen:before {
311   animation-name: decrunch;
312   animation-delay: 15s;
313   animation-duration: 0.25s;
314   animation-iteration-count: 14;
315   animation-timing-function: steps(1);
316 }
317 
318 /**
319  * Intro screen animations
320  */
321 @keyframes startintro {
322   to {
323     visibility: visible;
324   }
325 }
326 @keyframes logoswing {
327   50% {
328     left: -162px;
329   }
330 }
331 @keyframes rasterswing {
332   50% {
333     top: 168px;
334   }
335 }
336 @keyframes rasterindex {
337   50% {
338     z-index: 10;
339   }
340 }
341 @keyframes textflash {
342   0% { color: #000000; }
343   1% { color: #20398d; }
344   2% { color: #6076c5; }
345   3% { color: #86bec5; }
346   4% { color: #ffffff; }
347   5% { color: #86bec5; }
348   6% { color: #6076c5; }
349   7% { color: #20398d; }
350   8% { color: #000000; }
351   26% { color: #873b31; }
352   27% { color: #ba7369; }
353   28% { color: #dce78c; }
354   29% { color: #ffffff; }
355   30% { color: #dce78c; }
356   31% { color: #ba7369; }
357   32% { color: #873b31; }
358   33% { color: #000000; }
359   51% { color: #555555; }
360   52% { color: #808080; }
361   53% { color: #ababab; }
362   54% { color: #ffffff; }
363   55% { color: #ababab; }
364   56% { color: #808080; }
365   57% { color: #555555; }
366   58% { color: #000000; }
367   76% { color: #625000; }
368   77% { color: #74ab54; }
369   78% { color: #b7eb9b; }
370   79% { color: #ffffff; }
371   80% { color: #b7eb9b; }
372   81% { color: #74ab54; }
373   82% { color: #625000; }
374   83% { color: #000000; }
375 }
376 @keyframes starscroll {
377   to {
378     left: -40em;
379   }
380 }
381 @keyframes scroller {
382   to {
383     text-indent: -220em; /* Should match text length */
384   }
385 }
386 @keyframes scrollerbounce {
387   from, to  {
388     animation-timing-function: ease-out;
389   }
390   50% {
391     line-height: 1em;
392     animation-timing-function: ease-in;
393   }
394 }
395 
396 /**
397  * The intro screem
398  */
399 section.introscreen {
400   animation-name: startintro;
401   animation-delay: 19s; /* Blue screen animation takes 19s */
402   animation-fill-mode: forwards;
403   animation-duration: 1s; /* Doesn't matter */
404 
405   visibility: hidden;
406   background: #000;
407   border-color: #000;
408 
409   font: normal 16px "Giana";
410   text-transform: uppercase;
411 
412 }
413 section.introscreen:before,
414 section.introscreen:after {
415   background: #000;
416 }
417 
418 /**
419  * The swinging Pixelambacht logo
420  */
421 div.logo {
422   position: absolute;
423   top: 64px;
424   left: 0;
425   right: 0;
426   text-align: center;
427   margin: 0 auto;
428   height: 96px;
429   color: #6076c5;
430   overflow: hidden;
431 }
432 div.logo:before {
433   content: url(pixelambacht-logo.png);
434   position: absolute;
435   left: 40px;
436 
437   animation-name: logoswing;
438   animation-duration: 3s;
439   animation-iteration-count: infinite;
440   animation-timing-function: cubic-bezier(0.420, 0.000, 0.580, 1.000);
441   animation-fill-mode: forwards;
442 
443   z-index: 9;
444 }
445 
446 /**
447  * The swinging raster bar
448  */
449 section.introscreen:after {
450   height: 100px;
451   left: -64px;
452   right: -64px;
453   z-index: 8;
454   position: absolute;
455 
456   animation-name: rasterswing, rasterindex;
457   animation-duration: 4s, 4s;
458   animation-iteration-count: infinite, infinite;
459   animation-timing-function: cubic-bezier(0.420, 0.000, 0.580, 1.000), steps(1);
460   animation-fill-mode: forwards;
461 
462   background: linear-gradient(to bottom, #873b31 0%,#000000 2%,#873b31 2%,#873b31 4%,#873b31 4%,#873b31 6%,#ba7369 6%,#ba7369 8%,#873b31 8%,#873b31 10%,#ba7369 10%,#ba7369 12%,#ba7369 12%,#ba7369 14%,#dce78c 14%,#dce78c 16%,#ba7369 16%,#ba7369 18%,#dce78c 18%,#dce78c 20%,#dce78c 20%,#dce78c 22%,#ffffff 22%,#ffffff 24%,#dce78c 24%,#dce78c 26%,#ffffff 26%,#ffffff 28%,#ffffff 28%,#ffffff 30%,#dce78c 30%,#dce78c 32%,#ffffff 32%,#ffffff 34%,#dce78c 34%,#dce78c 36%,#dce78c 36%,#dce78c 38%,#ba7369 38%,#ba7369 40%,#dce78c 40%,#dce78c 42%,#ba7369 42%,#ba7369 44%,#ba7369 44%,#ba7369 46%,#873b31 46%,#873b31 48%,#ba7369 48%,#ba7369 50%,#873b31 50%,#873b31 52%,#873b31 52%,#873b31 54%,#000000 54%,#000000 56%,#873b31 56%,#873b31 58%,rgba(0,0,0,0) 58%,rgba(0,0,0,0) 100%);
463 }
464 
465 /**
466  * Credits block
467  */
468 ul.presents {
469   z-index: 10;
470   color: #000000;
471   position: absolute;
472   top: 228px;
473   left: -64px;
474   right: -64px;
475   text-align: center;
476   padding: 34px 0; /* Making it 100px high */
477 
478   background: linear-gradient(to bottom, #20398d 0%,#000000 2%,#20398d 2%,#20398d 4%,#20398d 4%,#20398d 6%,#6076c5 6%,#6076c5 8%,#20398d 8%,#20398d 10%,#6076c5 10%,#6076c5 12%,#6076c5 12%,#6076c5 14%,#86bec5 14%,#86bec5 16%,#6076c5 16%,#6076c5 18%,#86bec5 18%,#86bec5 20%,#86bec5 20%,#86bec5 22%,#ffffff 22%,#ffffff 24%,#86bec5 24%,#86bec5 26%,#ffffff 26%,#ffffff 74%,#86bec5 74%,#86bec5 76%,#ffffff 76%,#ffffff 78%,#86bec5 78%,#86bec5 80%,#86bec5 80%,#86bec5 82%,#6076c5 82%,#6076c5 84%,#86bec5 84%,#86bec5 86%,#6076c5 86%,#6076c5 88%,#6076c5 88%,#6076c5 90%,#20398d 90%,#20398d 92%,#6076c5 92%,#6076c5 94%,#20398d 94%,#20398d 96%,#20398d 96%,#20398d 98%,#000000 98%,#000000 100%); /* W3C */
479 }
480 ul.presents li:first-child:before {
481   content: "c64 in css3";
482   animation-name: textflash;
483   animation-duration: 10s;
484   animation-iteration-count: infinite;
485   animation-timing-function: steps(1);
486 }
487 ul.presents li:last-child:before {
488   content: "coded by pixelambacht";
489   animation-name: textflash;
490   animation-duration: 10s;
491   animation-delay: 0.5s;
492   animation-iteration-count: infinite;
493   animation-timing-function: steps(1);
494 }
495 
496 /**
497  * Flashing startfield behind the scrolltext
498  */
499 .starfield {
500   position: relative;
501   position: absolute;
502   bottom: 0;
503   left: 0;
504   overflow: hidden;
505   height: 4em;
506   width: 40em;
507 }
508 .starfield li {
509   position: relative;
510   display: inline;
511   left: 0;
512 }
513 .starfield li:before {
514   content: ".";
515 }
516 /* Create an exact copy of each star */
517 .starfield li:after {
518   content: ".";
519   position: absolute;
520   top: 0;
521   left: 40em;
522 }
523 .starfield li {
524   animation-name: starscroll;
525   animation-duration: 5s;
526   animation-timing-function: linear;
527   animation-iteration-count: infinite;
528   animation-fill-mode: forwards;
529 }
530 .starfield li:before,
531 .starfield li:after {
532   animation-name: textflash;
533   animation-iteration-count: infinite;
534   animation-timing-function: steps(1);
535   animation-duration: 6.5s;
536   padding-left: 3em;
537 }
538 .starfield li:nth-child(2n):before,
539 .starfield li:nth-child(2n):after {
540   padding-left: 4em;
541 }
542 .starfield li:nth-child(3n):before,
543 .starfield li:nth-child(3n):after {
544   padding-left: 7em;
545 }
546 .starfield li:nth-child(4n):before,
547 .starfield li:nth-child(4n):after {
548   padding-left: 2em;}
549 
550 /* Flash each star at a different time */
551 .starfield li:nth-child(1):before,
552 .starfield li:nth-child(1):after {
553   animation-delay: -1s;
554 }
555 .starfield li:nth-child(2):before,
556 .starfield li:nth-child(2):after {
557   animation-delay: -1.5s;
558 }
559 .starfield li:nth-child(3):before,
560 .starfield li:nth-child(3):after {
561   animation-delay: -2s;
562 }
563 .starfield li:nth-child(4):before,
564 .starfield li:nth-child(4):after {
565   animation-delay: -2.5s;
566 }
567 .starfield li:nth-child(5):before,
568 .starfield li:nth-child(5):after {
569   animation-delay: -3s;
570 }
571 .starfield li:nth-child(6):before,
572 .starfield li:nth-child(6):after {
573   animation-delay: -3.5s;
574 }
575 .starfield li:nth-child(7):before,
576 .starfield li:nth-child(7):after {
577   animation-delay: -4s;
578 }
579 .starfield li:nth-child(8):before,
580 .starfield li:nth-child(8):after {
581   animation-delay: -4.5s;
582 }
583 .starfield li:nth-child(9):before,
584 .starfield li:nth-child(9):after {
585   animation-delay: -5s;
586 }
587 .starfield li:nth-child(10):before,
588 .starfield li:nth-child(10):after {
589   animation-delay: -5.5s;
590 }
591 .starfield li:nth-child(11):before,
592 .starfield li:nth-child(11):after {
593   animation-delay: -6s;
594 }
595 .starfield li:nth-child(12):before,
596 .starfield li:nth-child(12):after {
597   animation-delay: -6.5s;
598 }
599 .starfield li:nth-child(13):before,
600 .starfield li:nth-child(13):after {
601   animation-delay: -7s;
602 }
603 .starfield li:nth-child(14):before,
604 .starfield li:nth-child(14):after {
605   animation-delay: -7.5s;
606 }
607 .starfield li:nth-child(15):before,
608 .starfield li:nth-child(15):after {
609   animation-delay: -8s;
610 }
611 .starfield li:nth-child(16):before,
612 .starfield li:nth-child(16):after {
613   animation-delay: -8.5s;
614 }
615 .starfield li:nth-child(17):before,
616 .starfield li:nth-child(17):after {
617   animation-delay: -9s;
618 }
619 .starfield li:nth-child(18):before,
620 .starfield li:nth-child(18):after {
621   animation-delay: -9.5s;
622 }
623 .starfield li:nth-child(19):before,
624 .starfield li:nth-child(19):after {
625   animation-delay: -10s;
626 }
627 .starfield li:nth-child(20):before,
628 .starfield li:nth-child(20):after {
629   animation-delay: -10.5s;
630 }
631 .starfield li:nth-child(21):before,
632 .starfield li:nth-child(21):after {
633   animation-delay: -11s;
634 }
635 
636 /**
637  * And finally the meat of a C64 cracktro... the scrolltext
638  */
639 p.scrolltext {
640   /* Bounce-animation needs to be separate from the scroll animation, otherwise the
641      change in timing-functions will be applied to both animations */
642   line-height: 7em;
643 
644   animation-name: scrollerbounce;
645   animation-delay: 20s; /* Blue screen animation takes 19s, wait another second */
646   animation-duration: 1s;
647   animation-iteration-count: infinite;
648 }
649 p.scrolltext:before {
650   content: "welcome to my little c64 intro entirely done in css! no javascript was used \
651     for these effects... greetz to all the elite! press space to reset, and have fun \
652     typing some basic! pixelambacht signing off...";
653   position: absolute;
654   bottom: 0;
655   left: 0;
656   width: 40em;
657   overflow: hidden;
658   white-space: nowrap;
659   text-indent: 40em;
660   height: 60px;
661   color: #fff;
662 
663   animation-name: scroller;
664   animation-delay: 20s; /* Blue screen animation takes 19s, wait another second */
665   animation-duration: 16s;
666   animation-iteration-count: infinite;
667   animation-timing-function: linear;
668 }
669 
670 /**
671  * Act like a real C64 once space bar has been pressed
672  */
673 .spacebar:valid + section li + li {
674   display: none;
675 }
676 .spacebar:valid + section,
677 .spacebar:valid + section:before,
678 .spacebar:valid + section + section {
679   animation-name: none;
680 }
681 .spacebar:valid + section + section {
682   /* This selector doesn't work in Chrome, although it's valid :( */
683   visibility: hidden;
684 }
685 .spacebar {
686   background: transparent;
687   outline: none;
688   padding: 0;
689   border: none;
690   resize: none;
691 }
692 .spacebar:valid {
693   z-index: 20;
694   margin-top: -104px;
695   text-indent: -1em; /* Hide that first space */
696   height: 19em;
697   overflow: hidden;
698 }

This demo works on the latest Chrome and Firefox, works reasonably well in IE11 and not very well in Opera.

Check the code on Github or LOAD”PIXELAMBACHT”,8,1 and have some fun!

  1. I actually use Prefixfree to take care of all the browser-specific prefixes.