<svg 
  viewBox="0 0 1000 1000" 
  width="1000" 
  height="1000" 
  role="img"
>
  <title>
    A geometric pattern composed of nested circles and squiggly lines.
    Inspired by Legends of Zelda: Tears of the Kingdom
  </title>

  <g class="pattern">
    <!-- 
      Our graphics code goes here 
    -->
  </g>
</svg>

<button>Randomize</button>
html, body {
  display: grid;
  place-items: center;
  min-height: 100%;
  background-color: #eee;
}

svg {
  background: #fff;
  max-width: 90vw;
  max-height: 85vh;
  width: auto;
  height: auto;
}

.filled-circle {
  fill: #fff;
}

.stroked-circle {
  fill: none;
  stroke: #999;
  stroke-width: 10;
}


:root {
  --hue: 200;
}

button {
  /* Text Colors */
  --text-saturation: 90%;
  --text-lightness: 40%;
  
  --text-saturation-hover: calc(var(--text-saturation) + 10%);
  --text-lightness-hover: calc(var(--text-lightness) - 5%); ;
  
  --text-saturation-active: var(--text-saturation-hover);
  --text-lightness-active: calc(var(--text-lightness) - 10%); ;
  
  --text-saturation-disabled: calc(var(--text-saturation) - 60%);
  --text-lightness-disabled: calc(var(--text-lightness) + 10%);
  
  /* Background Colors */
  --background-saturation: 0%;
  --background-lightness: 100%;
  
  --background-saturation-hover: calc(var(--background-saturation) + 80%);
  --background-lightness-hover: calc(var(--background-lightness) - 5%);
  
  --background-saturation-active: var(--background-saturation-hover);
  --background-lightness-active: calc(var(--background-lightness) - 10%);
  
  --background-saturation-disabled: calc(var(--background-saturation) + 30%);
  --background-lightness-disabled: calc(var(--background-lightness) - 10%);
  
  /* Border Colors */
  --border-saturation: 90%;
  --border-lightness: 60%;
  
  --border-saturation-hover: calc(var(--border-saturation) + 10%);
  --border-lightness-hover: calc(var(--border-lightness) - 10%);
  
  --border-saturation-active: var(--border-saturation-hover);
  --border-lightness-active: calc(var(--border-lightness) - 20%);
  
  --border-saturation-disabled: calc(var(--border-saturation) - 60%);
  --border-lightness-disabled: calc(var(--border-lightness) + 20%);
  
  /* Focus shadow styles */
  --shadow-saturation-focus: 100%;
  --shadow-lightness-focus: 85%;
  
  /* Color Styles */
  color: hsl(var(--hue), var(--text-saturation), var(--text-lightness));
  background-color: hsl(var(--hue), var(--background-saturation), var(--background-lightness)); 
  border:0.1em solid hsl(var(--hue), var(--border-saturation), var(--border-lightness)); 
  
  /* Misc. Styles */
  border-radius: 0.25em;
  cursor: pointer;
  display: inline-block;
  font-size: 1em;
  padding: 0.5em 1em;
  transition-property: box-shadow, background-color, border-color, color;
  transition-timing-function: ease-out;
  transition-duration: 0.2s;
}

button:hover {
  color: hsl(
    var(--hue), 
    var(--text-saturation-hover), 
    var(--text-lightness-hover)
  );
  
  background-color: hsl(
    var(--hue), 
    var(--background-saturation-hover), 
    var(--background-lightness-hover)
  );
  
  border-color: hsl(
    var(--hue), 
    var(--border-saturation-hover), 
    var(--border-lightness-hover)
  );
}

button:active {
  color: hsl(
    var(--hue), 
    var(--text-saturation-active), 
    var(--text-lightness-active)
  );
  
  background-color: hsl(
    var(--hue), 
    var(--background-saturation-active), 
    var(--background-lightness-active)
  );
  
  border-color: hsl(
    var(--hue), 
    var(--border-saturation-active), 
    var(--border-lightness-active)
  );
}

button:focus {
  outline: none;
  box-shadow: 0 0 0 0.25em hsl(
    var(--hue), 
    var(--shadow-saturation-focus),
    var(--shadow-lightness-focus)
  );
}
import { randomInt } from 'https://unpkg.com/randomness-helpers@0.0.1/dist/index.js';

function circle({ x, y, r, className }) {
  return `
    <circle 
      cx="${x}" 
      cy="${y}" 
      r="${r}" 
      class="${className}"
    />
  `;
}

function circleGroup({x, y, r }) {
  // We'll store all our circles in an array.
  const circles = [];

  // First, draw a circle with a white background but no border.
  // This will hide any elements behind the circle.
  circles.push(circle({ x, y, r, className: 'filled-circle' }));

  // Decide how much space to put between our circles.
  const gap = 20;

  // Draw a number of circles, making each one smaller than the last
  // until we hit a radius of 0.
  let circleSize = r;
  while(circleSize > 0) {
    circles.push(circle({ x, y, r: circleSize, className: 'stroked-circle' }));
    circleSize -= gap;
  }

  // Return all our circles as a single string;
  return circles.join('');
}

const patternEl =  document.querySelector('.pattern');

function draw() {
   const circleGroups = [];
  for (let i = 0; i < randomInt(10, 30); i++) {
    circleGroups.push(circleGroup({
      x: randomInt(0, 1000),
      y: randomInt(0, 1000),
      r: randomInt(50, 300)
    }))
  }
  
  patternEl.innerHTML = circleGroups.join('');
}

draw();

document.querySelector('button').addEventListener('click', draw);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.