Search code examples
javascripthtmlcsscss-gridresponsive

How to create a HTML grid of circles that responsively fills the viewport?


My goal is to create a responsive dot grid. Following the header, I want to fill the rest of the page with a dot grid that's evenly distributed with evenly proportioned circles. The ideal result would look like the image below:

enter image description here

What is the direction to build this grid out, taking into account the variable height of the header, and filling the rest of the screen with a grid, with circles that are sized proportionately to the viewport width?

The current status of my project is this:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dot Grid</title>
</head>

<style>
    .header {
        height: 3vw;
        width: 100%;
    }

    .header h2 {
        width: 100%;
        height: 100%;
        text-align: center;
    }

    .dot-grid {
        width: 100%;
        background-color: white;
        overflow: hidden;
    }

    .container-box {
        width: 100%;
        height: 100%;
        padding: 2px 0;
    }

    .dots-wrapper {
        display: grid;
        position: relative;
        grid-template-columns: repeat(16, 1fr);
        grid-template-rows: repeat(3, 1fr);
        grid-column-gap: 10px;
        width: 100%;
        padding: 0 10px;
        overflow: hidden;
    }

    .dots-wrapper .grid-container {
        width: 100%;
        list-style: none;
    }

    .grid-container .circle-group {
        display: flex;
        width: 100%;
        padding: 0;
        margin-top: 0;
        justify-content: center;
    }

    .dots-wrapper div.grid-container:last-child {
        margin-bottom: 0;
    }

    .circle-group .circle {
        width: 1.95vw;
        height: 1.95vw;
        border: 1px solid darkgray;
        border-radius: 40px;
        list-style: none;
        margin: 0 0.1vw;
    }
</style>

<body>
    <header class="header">
        <h2>Dot Grid Header</h2>
    </header>
    <div class="dot-grid">
        <div class="container-box">
            <div class="dots-wrapper">

                <div class="grid-container">

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>

                    <ul class="circle-group" style="margin-bottom: 5px;">
                        <li class="circle"></li>
                        <li class="circle"></li>
                        <li class="circle"></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</body>

</html>


Solution

  • I do not advise you to do this, but to answer your question directly, here is a simple example of generating adaptive circles according to your requirements:

    createCircles();
    window.onresize = createCircles;
    
    function createCircles() {
      const columns = 16;
      const cellCircles = 3;
    
      const circles = document.querySelector('.circles');
      circles.innerHTML = '';
      const cellWidht = circles.offsetWidth / columns;
      const cellHeight = cellWidht / cellCircles;
      const rows = Math.floor(circles.offsetHeight / cellHeight);
      let html = '';
      let cell = '<div class="cell">';
      for (let i = 0; i < cellCircles; i++ ){
        cell += '<i></i>';
      }
      cell += '</div>';
      for (let i = 0; i < columns * rows; i++) {
        html += cell;
      }
    
      circles.innerHTML = html;
    }
    * {
      box-sizing: border-box;
      margin:  0;
    }
    
    body {
      min-height:100vh;
      display:grid;
      grid-template-rows:auto 1fr;
      padding: 4px;
    }
    
    .circles {
      display: grid;
      grid-template-columns: repeat(16, 1fr);
      min-height: 0;
      grid-gap: 4px 8px;
    }
    
    .cell {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-gap: 2px;
    }
    
    .cell i {
      aspect-ratio: 1;
      border: solid 1px #ccc;
      border-radius: 50%;
    }
    <h1>Title</h1>
    <div class="circles"></div>