)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

HTML Fraction

  1. <style>
  2.   .frac {
  3.     display: inline-block;
  4.     position: relative;
  5.     vertical-align: middle;
  6.     letter-spacing: 0.001em;
  7.     text-align: center;
  8.   }
  9.   .frac > span {
  10.     display: block;
  11.     padding: 0.1em;
  12.   }
  13.   .frac span.bottom {
  14.     border-top: thin solid black;
  15.   }
  16.   .frac span.symbol {
  17.     display: none;
  18.   } 
  19. </style>
  20.  
  21. <div class="frac">
  22.   <span>1</span>
  23.   <span class="symbol">/</span>
  24.   <span class="bottom">2</span>
  25. </div>
  26.  
  27. &#xb7; 
  28. <div class="frac">
  29.   <span>3</span>
  30.   <span class="symbol">/</span>
  31.   <span class="bottom">4</span>
  32. </div>

I saw this trick on stackoverflow by user lokesh. It will display:

1 / 2
·
3 / 4
// css // html

SVG Drawing Program

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  6.  
  7.     <title>Drawing</title>
  8.     <style>
  9.       body,
  10.       html {
  11.         user-select: none;
  12.         height: 100%;
  13.         margin: 0;
  14.         font-family: sans-serif;
  15.         background: white;
  16.       }
  17.  
  18.       body {
  19.         position: fixed;
  20.         top: 0;
  21.       }
  22.  
  23.       .ui {
  24.         position: fixed;
  25.         display: flex;
  26.         bottom: 0;
  27.         width: 100%;
  28.         margin-bottom: .2em;
  29.       }
  30.  
  31.       .ui .tool {
  32.         font-size: 2em;
  33.         flex: 1;
  34.         text-align: center;
  35.       }
  36.  
  37.       .tool span {
  38.         cursor: pointer;
  39.         display: inline-block;
  40.         transform: scale(0.7);
  41.         transition: transform 250ms ease-out;
  42.       }
  43.  
  44.       .tool span.selected {
  45.         transform: scale(1);
  46.       }
  47.  
  48.       svg {
  49.         overflow: visible;
  50.         height: 100%;
  51.         width: 100%;
  52.         margin: 0;
  53.         padding: 0;
  54.       }
  55.  
  56.       input[type=color] {
  57.         position: absolute;
  58.         left: 0;
  59.         top: 0;
  60.         height: 100%;
  61.         opacity: 0;
  62.         cursor: pointer;
  63.       }
  64.  
  65.       .message {
  66.         position: fixed;
  67.         left: 0;
  68.         top: 0;
  69.         padding: 1em;
  70.         width: 100%;
  71.         text-align: center;
  72.         font-size: 1.2em;
  73.         transition: opacity 250ms ease-out;
  74.         pointer-events: none;
  75.       }
  76.  
  77.       .message.hide {
  78.         opacity: 0;
  79.       }
  80.     </style>
  81.   </head>
  82.   <body>
  83.  
  84.     <svg class="paper" width="100%" height="100%">
  85.       <style>
  86.         path {
  87.           stroke-linecap: round;
  88.           stroke-linejoin: round;
  89.           fill: none;
  90.         }
  91.       </style>
  92.     </svg>
  93.     <div class="ui">
  94.       <div class="tool"><span class="pencil" class="pencil icon selected">&#9999;&#65039;</span></div>
  95.       <div class="tool"><span class="brush icon">&#128396;&#65039;</span></div>
  96.       <div class="tool"><span class="colors icon">&#x1f3a8;
  97.         <input class="color" type="color"></span></div>
  98.     </div>
  99.     <div class="message">
  100.       click/tap and drag to draw
  101.     </div>
  102.  
  103.     <script>
  104.       (() => { 
  105.         // no scrolling on mobile
  106.         document.addEventListener('touchmove', e => e.preventDefault(), {
  107.           passive: false
  108.         });
  109.  
  110.         function touchify(e) {
  111.           const touch = [];
  112.           touch.x = touch.y = 0;
  113.  
  114.           if (e.touches != null && e.touches.length > 0) {
  115.             touch.x = e.touches[0].clientX;
  116.             touch.y = e.touches[0].clientY;
  117.             for (let i = 0; i < e.touches.length; i++) {
  118.               touch[i] = e.touches[i];
  119.             }
  120.           } else {
  121.             touch.x = e.clientX;
  122.             touch.y = e.clientY;
  123.             touch[0] = { clientX: e.clientX, clientY: e.clientY };
  124.           }
  125.           return touch;
  126.         }
  127.  
  128.         const els = {};
  129.  
  130.         [...document.querySelectorAll('[class]')].forEach(el => {
  131.           els[el.classList[0]] = el;
  132.         });
  133.  
  134.         const { paper, pencil, color, brush, message } = els;
  135.  
  136.         let lastSelected = pencil;
  137.         let strokeWidth = 1;
  138.         let downCount;
  139.         let down;
  140.         let currPath;
  141.         let pathPoints;
  142.  
  143.         const onDown = e => {
  144.           down = true;
  145.           downCount = 0;
  146.           pathPoints = [];
  147.         };
  148.  
  149.         const onMove = e => {
  150.           const touch = touchify(e);
  151.  
  152.           if (down) {
  153.             downCount++;
  154.  
  155.             if (downCount === 1) {
  156.               currPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  157.               currPath.setAttribute('stroke', color.value);
  158.               currPath.setAttribute('stroke-width', strokeWidth);
  159.               currPath.setAttribute('d', `M ${touch.x} ${touch.y}`);
  160.               pathPoints.push([touch.x, touch.y]);
  161.               paper.appendChild(currPath);
  162.             } else {
  163.               let path = `M ${pathPoints[0][0]} ${pathPoints[0][1]} L `;
  164.               pathPoints.push([touch.x, touch.y]);
  165.               for (let i = 1; i < pathPoints.length; i++) {
  166.                 path += `${pathPoints[i][0]} ${pathPoints[i][1]} `;
  167.               }
  168.               currPath.setAttribute('d', path);
  169.             }
  170.  
  171.             if (downCount === 10) {
  172.               message.classList.add('hide');
  173.             }
  174.           }
  175.         };
  176.  
  177.         const onUp = e => {
  178.           down = false;
  179.         };
  180.  
  181.         const onClick = e => {
  182.           if (e.target.classList.contains('pencil')) {
  183.             strokeWidth = 1;
  184.           } else if (e.target.classList.contains('brush')) {
  185.             strokeWidth = 10;
  186.           }
  187.           if (e.target.classList.contains('icon')) {
  188.             if (lastSelected) lastSelected.classList.remove('selected');
  189.             e.target.classList.add('selected');
  190.             lastSelected = e.target;
  191.           }
  192.         };
  193.  
  194.         document.addEventListener('mousedown', onDown);
  195.         document.addEventListener('touchstart', onDown);
  196.  
  197.         document.addEventListener('mousemove', onMove);
  198.         document.addEventListener('touchmove', onMove);
  199.  
  200.         document.addEventListener('mouseup', onUp);
  201.         document.addEventListener('touchend', onUp);
  202.  
  203.         document.addEventListener('click', onClick);
  204.         document.addEventListener('touchend', onClick);
  205.       })();
  206.     </script>
  207.   </body>
  208. </html>

SVG based drawing program.

// css // javascript // svg // ui

Snippet Zone Code Highlighter

I wrote a naive syntax highlighter a few weeks ago. Here it is rendering the code for itself. :

This is not a perfect highlighter, but it was fun to create and I will definitely use it in the Snippet Zone Github repository once I get that set up.

There is some css that goes with the highlighter, it’s pretty boring, but here it is anyway:

  1. .hh {
  2.   white-space: pre-wrap;
  3.   font-family: monaco, monospace;
  4.   line-height: 1.5;
  5.   font-size: .8em;
  6.   background: rgb(3, 21, 36);
  7.   color: rgba(156, 221, 254, 1);
  8.   padding: 1em;
  9. }
  10.  
  11. .hh b {
  12.   font-weight: normal;
  13. }
  14.  
  15. .hh i {
  16.   color: #1ad6ae;
  17. }
  18.  
  19. .hh u {
  20.   color: rgb(255, 195, 252);
  21.   text-decoration: none;
  22. }
  23.  
  24. .num {
  25.   color: #b5cea8;
  26. }
  27.  
  28. .str, .str b  {
  29.   color: #ce9178;
  30. }
  31.  
  32. .par {
  33.   color: white;
  34.   font-weight: bold;
  35. }
  36.  
  37. .brk {
  38.   color: white;
  39.   font-weight: bold;
  40. }
  41.  
  42. .o {
  43.   color: rgb(0, 151, 221);
  44. }
  45.  
  46. .obj {
  47.   color: rgb(52, 206, 47);
  48.   font-weight: bold !important;
  49. }
  50.  
  51. .w {
  52.   color: #1ad6ae;
  53.   font-style: italic;
  54. }
  55.  
  56. .k {
  57.   color: aqua;
  58. }
  59.  
  60. .cmt {
  61.   color: gray !important;
  62. }
  63. .cmt b {
  64.   color: gray !important;
  65. }

I have no idea why I used such bad class names there 😛

// css // dom // javascript // meta // strings // ui

Complementary HSL

  1. const a = document.body.appendChild(document.createElement('div')),
  2.       b = document.body.appendChild(document.createElement('div'));
  3. let degA = degB = 0;
  4.  
  5. const size = {
  6.   width: '100px',
  7.   height: '100px'
  8. };
  9. Object.assign(a.style, size);
  10. Object.assign(b.style, size);
  11.  
  12. function loop() {
  13.   degA += 1;
  14.   degB = degA + 180;
  15.   a.style.background = `hsl(${degA}deg, 100%, 50%)`;
  16.   b.style.background = `hsl(${degB}deg, 100%, 50%)`;
  17.   requestAnimationFrame(loop);
  18. }
  19. loop();

In HSL a hue difference of 180 degrees between two values will create a set of complimentary colors.

// animation // color // css // dom // javascript // tricks // ui

Make a Grid

  1. const cellSize = 25;
  2. const cols = 10;
  3. const rows = 20;
  4.  
  5. function makeDot(x, y) {
  6.   const dot = document.body.appendChild(
  7.     document.createElement('div')
  8.   );
  9.  
  10.   dot.classList.add('cell');
  11.  
  12.   Object.assign(dot.style, {
  13.     position: 'absolute',
  14.     left: `${x}px`,
  15.     top: `${y}px`,
  16.     width: `${cellSize}px`,
  17.     height: `${cellSize}px`,
  18.     outline: '1px solid black',
  19.     cursor: 'pointer',
  20.     background: 'gray'
  21.   });
  22.  
  23.   return dot;
  24. }
  25.  
  26. for (let y = 0; y < rows; y++) {
  27.   for (let x = 0; x < cols; x++) {
  28.     makeDot(x * cellSize, y * cellSize);
  29.   }
  30. }
  31.  
  32. // make a cell red when it is rolled over
  33. document.addEventListener('mouseover', e => {
  34.   if (e.target.classList.contains('cell')) {
  35.     e.target.style.background = 'red';
  36.   }
  37. });

Here is a simple example for arranging divs in a grid.

// css // dom // javascript // math // tricks // ui
snippet.zone ~ 2021-24 /// {s/z}