JSFiddle - React, Tailwind, and code Playground

by fxi

HTML

<link rel="stylesheet" href="https://unpkg.com/@highlightjs/[email protected]/styles/default.min.css">
<script src="https://unpkg.com/@highlightjs/[email protected]/highlight.min.js"></script>
<!-- 
bgcolor = deprecated way of setting background.Value x is undocumented
onload = eval JS code
-->

<body bgcolor=x onload=''>
  <!--
Our "canvas". id will be available as a global variable. 
-->
  <div class=quine>
    <pre id=p></pre>
  </div>


  <div class="explain"> 
  <p>There is three main tricks here :
    <ol>
      <li> Store the function as string and loop on characters for the "self printing" part </li> 
      <li> Encode binary value as an integer, ex.
         <pre>
        (30583).toString(2)
        '111011101110111' (Top row of 2022) </pre></li> 
      <li> Use "fontcolor" to convert string to html with color, ex "s" -> '&lt;font color="undefined"&gt; s &lt;/font&gt; '</li>
    </ol>
    <pre><code class="language-js">
  setInterval(           // Repeat funtion each n [ms] ( set at the end )
  f=                     // Save callback in variable &quot;f&quot;
  H                      // Use the H argument as the first letter of the greeting
  /*appy New Year*/      // Use comment to display the rest of the greeting
  =&gt;{                 // Arrow function
  for(                   // Loop
                         // - INIT
  i=0,                   // Start at 0
  w=19,                  // Width of the message
  b=30583,               // Save the top row of 2022 ( binary )
  t++,                   // Increment time ( for scroll )
  o=``,                  // Reset output HTML
  l=f+o;                 // Save the function as string
                         // - END CONDITION
  i&lt;l.length;         // Continue the loop until the end of the string
                         // - INCREMENT
  o+=(                   // Append each token to the string
  l[i++]+(i%w?``:`\n`)   // Add character and new line each 19 characters ( w value )
  ).fontcolor(          ...

CSS

body {
  font-family: Helvetica, Arial, sans-serif;
}

.quine {
  padding:50px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 50px;
  outline: 1px solid #f0f;
  background-color: #333;
}
.explain {
   padding:50px;
}

JavaScript

hljs.highlightAll();

setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,b=30583,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!([b,17492,30551,4433,b][i/w+t&7]&1<<i%w-3)&&H));p.innerHTML=o/**/},t=500);

// better, but characters are not all monospaced, prduce unreguar lines
//setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!(H.charCodeAt(i/w+t&7)&1<<i%w-3)&&p.x));p.innerHTML=o},t=6e2,`睷䑔睗ᅑ睷`)

// Smarter, but encoded 2022 not included
//setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!(H.charCodeAt(i/w+t&7)&1<<i%w-3)&&p.x));p.innerHTML=o},t=6e2,`睷䑔睗ᅑ睷`)

// Compromise : char numbers
//setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,b=30583,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!([b,17492,30551,4433,b][i/w+t&7]&1<<i%w-3)&&H));p.innerHTML=o/**/},t=500)