<section class="section">
  <svg class="svg"></svg>
  <div class="block">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Accusamus cum maxime recusandae. Porro repellendus illum nam deserunt at magni, ad quae sint molestiae voluptas fuga aperiam odit esse labore consectetur!</div>
</section>
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background:
    linear-gradient(to right, #0001 1px, transparent 1px) 0 0 / 8px 8px,
    linear-gradient(to bottom, #0001 1px, transparent 1px) 0 0 / 8px 8px;
}

.section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  height: 100vh;
  min-height: 500px;
}

.svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.svg circle {
  fill: gray;
  fill-opacity: 0.5;
}

.block {
  width: 50%;
  max-width: 250px;
  margin-left: 50px;
  padding: 15px;
  background-color: #0f07;
}
const lerp = (v0, v1, t) => v0 * (1 - t) + v1 * t;
const SVG_NS = "http://www.w3.org/2000/svg";

const svg = document.querySelector(".svg");
const block = document.querySelector(".block");
const blockRect = block.getBoundingClientRect();

const shiftCoef = 0.75;
const cellWidth = 48;
const cellHeight = 48;
const radius = 12;

function isIntersectRects(r1, r2) {
  return !(
    r2.x > r1.x + r1.width ||
    r2.x + r2.width < r1.x ||
    r2.y > r1.y + r1.height ||
    r2.y + r2.height < r1.y
  );
}

function createSubdivRange(fromTo, size) {
  const { from = 0, to } = fromTo;
  const step = (to - from) / Math.round((to - from) / size);
  const out = [];
  
  for (let position = from; position <= to; position += step) {
    out.push({ position, size: step });
  }
  
  return out;
}

const cols = createSubdivRange({ from: 0, to: svg.clientWidth }, cellWidth);
const rows = createSubdivRange({ from: 0, to: svg.clientHeight }, cellHeight);

for (let ci = 0; ci < cols.length; ci++) {
  for (let ri = 0; ri < rows.length; ri++) {
    const { position: x, size: width } = cols[ci];
    const { position: y, size: height } = rows[ri];

    const dx = (width / 2 - radius) * shiftCoef;
    const dy = (height / 2 - radius) * shiftCoef;
    const cx = x + width / 2 + lerp(-dx, dx, Math.random());
    const cy = y + height / 2 + lerp(-dy, dy, Math.random());

    const isIntersects = isIntersectRects(blockRect, {
      x: cx - radius,
      y: cy - radius,
      width: radius * 2,
      height: radius * 2
    });

    if (!isIntersects) {
      const circle = document.createElementNS(SVG_NS, "circle");
      circle.setAttributeNS(null, "cx", cx);
      circle.setAttributeNS(null, "cy", cy);
      circle.setAttributeNS(null, "r", radius);
      svg.appendChild(circle);
    }
  }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.