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

Bring Node to Top

  1. myEl.parentNode.appendChild(myEl);

This will make an element the top most of all of its siblings…

  1. document.body.innerHTML += `
  2. <div>
  3.   <button>one</button>
  4.   <button>two</button>
  5.   <button>three</button>
  6.   <button>four</button>
  7. </div>
  8. <style>
  9.   button { display: block; cursor: pointer; }
  10. </style>
  11. `;
  12. document.addEventListener('click', e => {
  13.   if (e.target.tagName === 'BUTTON') {
  14.     e.target.parentNode.appendChild(e.target);
  15.   }
  16. });

Clicking on any button will bring it to the top most position within its parent.

// dom // javascript // tricks // ui

Responsive Radial Gradient Animation

  1. function rect(x1, y1, x2, y2, col, blur=.1) {
  2.   const dx = x1 - x2;
  3.   const dy = y1 - y2;
  4.   const dist = Math.sqrt(dx * dx + dy * dy);
  5.   return `radial-gradient(circle at ${x1}% ${y1}%, ${col} 0, ${col} ${dist}%, transparent ${dist +
  6.     blur}%)`;
  7. }
  8.  
  9. const NUM = 8; 
  10.  
  11. let rects = [];
  12. const colors = ['rgba(0, 0, 0, 0.2)', 'white', 'black'];
  13.  
  14. let x = 0;
  15. let y = 0;
  16. let t = 8;
  17. function loop() { 
  18.   rects = [];
  19.  
  20.   for (let i = 0; i < NUM; i++) { 
  21.     x = 50 + 30 * Math.sin(t + i / 2);
  22.     y = 50 + 30 * Math.cos(t * 1.5 * i / 10);
  23.     rects.push(rect(x, y, x + 5, y + 5, 'rgba(255, 255, 255, 1)', 1));
  24.     rects.push(rect(x, y, x + 5, y + 5, 'rgba(0, 0, 0, 0.4)', 
  25.       8 + 6 * Math.cos(y / 10)));
  26.   }
  27.   t += .04;
  28.   document.body.style.backgroundImage = rects.join(', ');
  29.   window.requestAnimationFrame(loop);
  30. }
  31. loop()
  32.  
  33. document.body.innerHTML += `
  34.   <style>
  35.     body, html {
  36.       height: 100%;
  37.       background: #ccc;
  38.       margin: 0;
  39.       background-repeat: no-repeat;
  40.       width: 100%;
  41.     }
  42.   </style>
  43. `;

Animated variation on yesterdays post – many animating circles with no divs or canvas, just radial-gradients…

// animation // css // dom // graphics // hacks // javascript // math

Responsive Radial Gradient Background

  1. function rect(x1, y1, x2, y2, col) {
  2.   const dx = x1 - x2;
  3.   const dy = y1 - y2;
  4.   const dist = Math.sqrt(dx * dx + dy * dy);
  5.   return `radial-gradient(circle at ${x1}% ${y1}%, ${col} 0, ${col} ${dist}%, transparent ${dist +
  6.     0.1}%)`;
  7. }
  8.  
  9. const NUM = 90;
  10. const MAX_SIZE = 20;
  11.  
  12. const rects = [];
  13. const colors = ['rgba(0, 0, 0, 0.2)', 'white', 'black'];
  14.  
  15. for (let i = 0; i < NUM; i++) {
  16.   const x1 = Math.random() * 100; // %
  17.   const y1 = Math.random() * 100;
  18.   const size = Math.random() * Math.random() * MAX_SIZE;
  19.   const idx = Math.random() < 0.3 ? 1 + Math.round(Math.random()) : 0;
  20.   col = colors[idx];
  21.   rects.push(rect(x1, y1, x1 + size,  y1 + size, col));
  22. }
  23.  
  24. document.body.style.backgroundImage = rects.join(', ');
  25.  
  26. document.body.innerHTML += `
  27.   <style>
  28.     body, html {
  29.       height: 100%;
  30.       background-repeat: no-repeat;
  31.     }
  32.   </style>
  33. `;

Many circles with no divs or canvas, just radial-gradients…

Interesting Color Picker

  1. document.addEventListener('touchmove', e => e.preventDefault(), {
  2.   passive: false
  3. });
  4.  
  5. document.body.innerHTML += `
  6. <style>
  7.   * {
  8.     -moz-user-select: none;
  9.     -webkit-user-select: none;
  10.     -ms-user-select: none;
  11.     user-select: none;
  12.   }
  13.   body {
  14.     background: #333;
  15.   }
  16.   .select-box {
  17.     border: 1px solid white;
  18.     outline: 1px solid black;
  19.   }
  20.   .swatch {
  21.     border: none;
  22.     outline: none;
  23.   }
  24. </style>
  25. `;
  26.  
  27. const col = document.body.appendChild(document.createElement('div'));
  28. Object.assign(col.style, {
  29.   position: 'absolute',
  30.   left: 0,
  31.   top: 0,
  32.   width: '100%',
  33.   height: '200px',
  34.   background:
  35.     `linear-gradient(0, black 0%, transparent 50%, transparent 50%, white 100%), 
  36.      linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)`
  37. });
  38.  
  39. const swatches = document.body.appendChild(document.createElement('div'));
  40. Object.assign(swatches.style, {
  41.   position: 'absolute',
  42.   top: '200px',
  43.   left: 0,
  44.   width: '100%'
  45. });
  46.  
  47. function box(x, y, cls = 'select-box', parent = document.body) {
  48.   const box = parent.appendChild(document.createElement`div`);
  49.   box.classList.add(cls);
  50.   Object.assign(box.style, {
  51.     position: 'absolute',
  52.     left: `${x}%`,
  53.     top: `${y}px`,
  54.     width: '40px',
  55.     height: '40px',
  56.     background: 'none',
  57.     transform: 'translate(-50%, -50%)',
  58.     cursor: 'pointer',
  59.  
  60.     color: 'white'
  61.   });
  62.   return box;
  63. }
  64.  
  65. function touch(e) {
  66.   let x = e.clientX;
  67.   let y = e.clientY;
  68.   if (e.touches != null && e.touches.length > 0) {
  69.     x = e.touches[0].clientX;
  70.     y = e.touches[0].clientY;
  71.   }
  72.   return { x, y };
  73. }
  74.  
  75. document.addEventListener('touchstart', onDown);
  76. document.addEventListener('touchmove', onMove);
  77. document.addEventListener('touchend', onUp);
  78. document.addEventListener('mousedown', onDown);
  79. document.addEventListener('mousemove', onMove);
  80. document.addEventListener('mouseup', onUp);
  81.  
  82. let down = false;
  83. let currBox;
  84. let currSwatch;
  85. let swatchHeight = 30;
  86. let id = 0;
  87.  
  88. function toHSL(x, y) {
  89.   let deg = x * 360;
  90.   return `hsl(${deg}deg, 100%, ${100 - y / 2}%)`;
  91. }
  92.  
  93. function onDown(e) {
  94.   let { x, y } = touch(e);
  95.   down = true;
  96.   let hPercent = x / innerWidth;
  97.   let color = toHSL(hPercent, y);
  98.   if (e.target.classList.contains('swatch')) {
  99.     e.target.style.outline = '2px solid red';
  100.     e.target.style.zIndex = 999;
  101.     down = false;
  102.     setTimeout(() => {
  103.       if (confirm('Would you like to remove this swatch?')) {
  104.         currBox = document.querySelector(
  105.           `.select-box[data-id="${e.target.dataset.id}"]`
  106.         );
  107.  
  108.         if (currBox != null) {
  109.           currBox.parentNode.removeChild(currBox);
  110.           e.target.parentNode.removeChild(e.target);
  111.         }
  112.       } else {
  113.         e.target.style.outline = null;
  114.         e.target.style.zIndex = null;
  115.       }
  116.     }, 250);
  117.   } else if (e.target.classList.contains('select-box')) {
  118.     currBox = e.target;
  119.     c = document.querySelector(`.swatch[data-id="${currBox.dataset.id}"]`);
  120.   } else {
  121.     currBox = box(hPercent * 100, y);
  122.     currBox.dataset.id = id++;
  123.     currSwatch = box(0, 0, 'swatch', swatches);
  124.     currSwatch.dataset.id = currBox.dataset.id;
  125.     Object.assign(currSwatch.style, {
  126.       width: '100%',
  127.       position: 'relative',
  128.       height: `${swatchHeight}px`,
  129.       transform: 'none',
  130.       background: color
  131.     });
  132.   }
  133. }
  134.  
  135. function onMove(e) {
  136.   if (down) {
  137.     let { x, y } = touch(e);
  138.     let hPercent = x / innerWidth;
  139.     let color = toHSL(hPercent, y);
  140.     Object.assign(currBox.style, {
  141.       left: `${hPercent * 100}%`,
  142.       top: `${y}px`
  143.     });
  144.     currSwatch.style.background = color;
  145.   }
  146. }
  147.  
  148. function onUp(e) {
  149.   down = false;
  150.   currBox = null;
  151. }

Click anywhere on the spectrum to add a color… color boxes can be dragged, color swatches can be deleted by clicking on them…

Just something that popped into my head awhile back so figured I’d do a speed-coded prototype. I’d like to revisit this and add more to it.

Animate to Target

  1. function box(x, y, col = 'red', cursor){
  2.   const box = document.body.appendChild(
  3.     document.createElement`div`
  4.   )
  5.   box.classList.add(col + '-box')
  6.   Object.assign(box.style, {
  7.     position: 'absolute', 
  8.     left: `${x}%`,
  9.     top: `${y}%`,
  10.     width: '30px',
  11.     height: '30px',
  12.     background: col,
  13.     cursor: cursor || 'pointer',
  14.     color: 'white'
  15.   })
  16.   return box
  17. }
  18.  
  19. const NUM = 10;
  20. for (let i = 0; i < NUM; i++) 
  21.   box(
  22.     Math.random() * 100, 
  23.     Math.random() * 100)
  24.  
  25.  
  26. let destX = destY = x = y = 0;
  27. const blue = box(destX, destY, 'blue', 'default')
  28. const info = box(0, 30, 'gray')
  29. info.innerHTML = 'click the red boxes'
  30. Object.assign(info.style, {
  31.   width: '100%', 
  32.   padding: '.5em',
  33.   fontFamily: 'sans-serif'
  34. })
  35.  
  36. document.addEventListener('click', e => {
  37.   const curr = e.target
  38.   if (curr.classList.contains('red-box')) {
  39.     destX = curr.offsetLeft
  40.     destY = curr.offsetTop
  41.     curr.style.background = 'black'
  42.     setTimeout(() => curr.style.background = 'red', 700)
  43.     if (info.parentNode != null) { 
  44.       info.parentNode.removeChild(info);
  45.     }
  46.   }
  47. })
  48.  
  49. function loop() {
  50.   x += (destX - x) / 12
  51.   y += (destY - y) / 12
  52.   blue.style.transform = `translate3d(${x}px, ${y}px, 0)`
  53.   requestAnimationFrame(loop)
  54. }
  55. loop()

Click a red box, watch the blue box animate…

snippet.zone ~ 2021-24 /// {s/z}