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

Random Hex Color (semi-golfed)

  1. document.body.innerHTML += 'click anywhere...'
  2.  
  3. onclick = () =>
  4.   document.body.style.background = 
  5.     `#${Math.random().toString(16).substr(-6)}`

I golfed this snippet slightly for no reason in particular. I recently posted a nice readable way to make random hsl colors. This snippet generates a random hexidecimal color.

How it works:

  1. Math.random() // random number between 0 and 1
  2.  
  3. .toString(16) // convert to hex string (something like "0.2d6bcee4198d4")
  4.  
  5. .substr(-6) // grab the last 6 characters

Here is a non-golfed version:

  1. const instructionsEl = document.createElement('p');
  2. instructionsEl.innerHTML = 'click anywhere...';
  3. document.body.appendChild(instructionsEl);
  4.  
  5. const randomHexColor = () => 
  6.   `#${Math.random().toString(16).substr(-6)}`;
  7.  
  8. document.addEventListener('click', () => {
  9.   document.body.style.background = randomHexColor();
  10. });
// codegolf // color // css // golfed // hex // javascript

Easy Random Color

  1.  
  2. document.body.innerHTML += 'click to randomize background color';
  3.  
  4. document.addEventListener('click', () => { 
  5.   const hue = Math.random() * 360;
  6.   document.body.style.background = `hsl(${hue}deg, 50%, 50%)`;
  7. });

One way to generate a random color is to randomize the hue argument of the css hsl. This value is in degrees 0-360 (colorwheel). The other arguments can be randomized as well if you need random saturation and lightness… like this:

  1.  
  2. document.body.innerHTML += 'click to randomize background color';
  3.  
  4. document.addEventListener('click', () => { 
  5.   const hue = Math.random() * 360;
  6.   const saturation = Math.random() * 100;
  7.   const lightness = Math.random() * 100;
  8.   document.body.style.background = `hsl(${hue}deg, ${saturation}%, ${lightness}%)`;
  9. });
// css // dom // graphics // javascript

ClassName Behaviors

  1. const ui = document.body.appendChild(
  2.   document.createElement('div')
  3. );
  4.  
  5. ui.innerHTML = `
  6.   <button class="blue circle redBorder moveDown">click</button>
  7.   <button class="red circle sayHi">click</button>  
  8.   <button class="green circle noBorder moveDown sayHi randomBgColor">click</button>
  9.  
  10.   <style>
  11.     * { -webkit-user-select: none; user-select: none; }
  12.     body, html {
  13.       width: 100%; height: 100%;
  14.     }
  15.     button { 
  16.       position: relative;
  17.       top: 0;
  18.       margin: .5em; 
  19.       cursor: pointer; 
  20.       color: white;
  21.       transition: all 200ms ease-out;
  22.       text-shadow: 1px 2px 1px black;
  23.     }
  24.     .circle {
  25.       width: 50px;
  26.       height: 50px;
  27.       border-radius: 500px;
  28.     }
  29.     .blue {
  30.       background: #275ba1;
  31.     }
  32.     .red {
  33.       background: red;
  34.     }
  35.     .green {
  36.       background: green;
  37.     }
  38.     .redBorder {
  39.       border: 2px solid red;
  40.     }
  41.     .noBorder {
  42.       border: none;
  43.     }
  44.   </style>
  45. `;
  46.  
  47. const actions = {
  48.   moveDown(e) {
  49.     e.target.style.top = `${parseFloat(e.target.style.top || 0) + 30}px`;
  50.   },
  51.   sayHi(e) {
  52.     e.target.innerHTML = [
  53.       'hi', 'hello', 'hey', 'aloha', 'what\'s up'
  54.     ][
  55.       Math.floor(Math.random() * 5)
  56.     ];
  57.     e.target.style.transform = `
  58.       rotate(${Math.random() * 40 - 20}deg) 
  59.       scale(${Math.random() * .3 + 1})`
  60.   },
  61.   randomBgColor(e) {
  62.     const col = `hsl(${Math.random() * 360}deg, 50%, 50%)`
  63.     e.target.style.background = col;
  64.   }
  65. };
  66.  
  67. document.body.addEventListener('click', e => {
  68.   // combine as many actions as we want
  69.   [...e.target.classList].forEach(cls => { 
  70.     const action = actions[cls];
  71.     if (action != null) action(e);
  72.   });
  73. });

This snippet takes the ideas from yesterdays post and goes one level further. This associates behavior with class names, so the class names can be combined to mix and match behavior.

In this case, combining classes like this green circle noBorder moveDown sayHi randomBgColor will cause the element in question to “move down”, “say hi” and randomize its background color when it is clicked. Click the “Try it out” to get a better idea.

// animation // css // dom // events // javascript // tricks // ui

console.log Hijack

  1. const log = console.log;
  2. const consoleUI = document.body.appendChild(
  3.   document.createElement('div')
  4. );
  5. document.body.style.margin = 0;
  6. Object.assign(consoleUI.style, {
  7.   position: 'fixed',
  8.   bottom: 0,
  9.   width: '100%',
  10.   height: '30%',
  11.   maxHeight: '450px',
  12.   minHeight: '200px',
  13.   background: 'rgb(68, 68, 81)',
  14.   overflow: 'scroll'
  15. });
  16. function consoleRow(str) {
  17.   const row = document.createElement('div');
  18.   consoleUI.prepend(row);
  19.   row.innerText = str;
  20.   Object.assign(row.style, {
  21.     padding: '.5em',
  22.     fontFamily: 'sans-serif',
  23.     color: 'white',
  24.     borderBottom: '1px solid rgba(255, 255, 255, .1)',
  25.     whiteSpace: 'pre-wrap'
  26.   });
  27. }
  28.  
  29. console.log = (...args) => {
  30.   const formatted = args.map(val => {
  31.     return typeof val === 'object' ? 
  32.       JSON.stringify(val, null, 2) : val;
  33.   });
  34.   consoleRow(formatted.join(' '));
  35.   log.apply(console, args);
  36. };
  37.  
  38. // test it out
  39.  
  40. console.log(1, 2, 3, 4);
  41. console.log(new Date());
  42.  
  43. const someObject = {
  44.   test: 123,
  45.   testing: { x: 1, y: 2, z: 3 }
  46. };
  47. console.log(someObject);
  48.  
  49. console.log(3, 2, 1, 0);

I’m thinking about adding a little fake console to the Snippet Zone Quick Editor – just whipped this up as a proof of concept – something like this should work…

// css // hacks // javascript // meta // strings // tricks // ui

Range Slider and Progress Bar

  1. const NUM = 8;
  2. const NUM_M_1 = NUM - 1;
  3. const ui = document.createElement('div')
  4. ui.innerHTML = `
  5.   <div class="ui">
  6.     <div class="progress" data-ref>
  7.       <div class="progressFill" data-ref></div>
  8.     </div>
  9.     <div class="text" data-ref>
  10.     0% of 100%
  11.     </div>
  12.  
  13.     <div class="dots" data-ref>
  14.     ${
  15.       `<div></div>`.repeat(NUM)
  16.     }
  17.     </div>
  18.  
  19.     <label>
  20.       drag the slider...
  21.       <input class="slider" type="range" min="0" max="100" step="1" value="0" data-ref/>
  22.     </label>
  23.   </div>
  24.   <style>
  25.     body {
  26.       font-family: sans-serif;
  27.     }
  28.     .progress, .dots {
  29.       position: relative;
  30.       width: 80%;
  31.       margin: 0 auto;
  32.       height: 30px;
  33.       border: 1px solid black;
  34.     }
  35.     .progressFill {
  36.       height: 100%;
  37.       width: 0;
  38.       background: red;
  39.     }
  40.     .text {
  41.       padding: 1em;
  42.       background: #ccc;
  43.       margin: .5em;
  44.       font-weight: bold;
  45.     }
  46.     label {
  47.       display: block;
  48.       margin: 1em;
  49.     }
  50.     .slider {
  51.       cursor: pointer;
  52.     }
  53.     .dots {
  54.       border: none;
  55.     }
  56.     .dots div {
  57.       height: 100%;
  58.       width: ${100 / NUM}%;
  59.       float: left;
  60.       transition: background 400ms ease-out;
  61.       background: transparent;
  62.       border-radius: 500px;
  63.       box-shadow: inset 0 0px 0 3px blue;
  64.     }
  65.     .dots div:nth-child(1) {
  66.       background: red;
  67.     }
  68.  
  69.   </style>
  70. `;
  71. document.body.appendChild(ui);
  72.  
  73. // select everything with a `data-ref`
  74. const els = {};
  75. ;[...document.querySelectorAll('[data-ref]')]
  76.   .forEach(el => {
  77.     els[el.classList[0]] = el;
  78.   });
  79.  
  80. function update(e) {
  81.  
  82.   // normal prog bar
  83.   const val = e.target.value;
  84.   els.progressFill.style.width = `${val}%`;
  85.   els.text.innerHTML = `
  86.     ${val}% of 100%
  87.   `;
  88.  
  89.   // segmented dot prog bar
  90.   const idx = Math.floor(val / (100 / NUM));
  91.   if (idx < NUM) { 
  92.     for (let i = 0; i < NUM; i++) {
  93.       els.dots.children[i]
  94.         .style.background = i <= idx ? 'red' : 'white'
  95.     }
  96.   }
  97. }
  98.  
  99. els.slider.addEventListener('input', update);
  100. els.slider.addEventListener('change', update);

Drag slider and watch two progress bars and a text readout update. There are some interesting vanilla tricks in this one.

This trick and a variety of variations on it is pretty powerful:

  1. const els = {};
  2. [...document.querySelectorAll('[data-ref]')].forEach(el => {
  3.   els[el.classList[0]] = el;
  4. });
// css // dom // graphics // javascript // math // strings // tricks // ui
snippet.zone ~ 2021-24 /// {s/z}