Create dynamic cells for CSS grid using JavaScript

I have been manually generating grid cells in a specific pattern by copying and adjusting <div> elements. Although this method works, I am interested in creating an algorithm that can automatically generate the desired layout. The left box in the example below illustrates the dynamic calculation I am aiming for.

function createGridCells(){
let cells = '';
  for(let a = 1; a <= 10; a++){
    for(let b = 1; b <= a; b++){
        cells += `<div style="background:#fd8362; grid-area: ${a % b} / ${a % b} / ${a % b} / ${a % b}">
        ${b}
      </div>`
    }
  }
  return cells;
}

document.getElementById("grid-body-algorithm").innerHTML = createGridCells();
#grid-body,
#grid-body-algorithm {
    float:left;
    margin-right:30px;
    box-shadow: 0 0 10px rgba(0, 0, 0, .2);
    text-align: center;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    grid-template-rows: repeat(5, 1fr);
    justify-content: center;
    align-content: end;
    border-radius: 5px;
    width:150px;
    height:150px;
    color:#444444;
    padding:1px;
}

#grid-body > *,
#grid-body-algorithm > *{
  border:1px solid white;
}
<div id="grid-body">
  <div style="background:#fd8362; grid-area: 1 / 1 / 1 / 1">1</div>

  <div style="background:#ffad97; grid-area: 2 / 1 / 2 / 1">1</div>
  <div style="background:#ffad97; grid-area: 1 / 2 / 1 / 2">2</div>

  <div style="background:#ffded6; grid-area: 3 / 1 / 3 / 1">1</div>
  <div style="background:#ffded6; grid-area: 2 / 2 / 2 / 2">2</div>
  <div style="background:#ffded6; grid-area: 1 / 3 / 1 / 3">3</div>

  <div style="background:#fff0ec; grid-area: 4 / 1 / 4 / 1">1</div>
  <div style="background:#fff0ec; grid-area: 3 / 2 / 3 / 2">2</div>
  <div style="background:#fff0ec; grid-area: 2 / 3 / 2 / 3">3</div>
  <div style="background:#fff0ec; grid-area: 1 / 4 / 2 / 4">4</div>
</div>

<div id="grid-body-algorithm">
  
</div>

Answer №1

By examining the desired output, it is evident that the color of a cell is determined by the taxicab distance from the top-left corner, while the column number dictates the text content of the cell.

When implementing the inner loop, it is important to set a maximum limit on the taxicab distance. This limit can be customized as a parameter in your function. In this specific example, the maximum distance is set at 3 (which means cells up to 3 taxicab steps away from the top-left cell are considered).

Moreover, the color intensity seems to decrease with an increase in taxicab distance. To achieve this effect, adjustments can be made to the alpha component of the background color using the RGBA model. The alpha value ranges between 0 and 1.

Instead of generating HTML directly, I chose to create a document fragment for more controlled manipulation of cell attributes using JavaScript syntax, resulting in a more object-oriented approach.

The CSS styles provided have not been altered in this implementation.

In addition to the existing code, I have introduced an input field that enables users to specify the maximum taxicab distance:

function calcCells(maxDistance) {
  const fragment = document.createDocumentFragment();
  for (let row = 1; row <= 5; row++) {
    // row + col - 2 represents the taxicab distance from the top-left corner
    for (let col = 1, distance = row - 1; distance <= maxDistance && col <= 5; col++, distance++) { 
        const cell = document.createElement("div");
        // Adjust background transparency based on the calculated alpha value
        cell.style.background = `rgba(240,120,80,${1 - (distance + 0.5) / (maxDistance + 1)})`;
        cell.style.gridArea = [row, col, row, col].join(" / ");
        cell.textContent = col;
        fragment.appendChild(cell);
    }
  }
  return fragment;
}

const inputDistance = document.querySelector("input");
const outputGrid = document.getElementById("grid-body-algorithm");

function refresh() {
    const maxDistance = +inputDistance.value;
    outputGrid.innerHTML = ""; // Clear previous content
    outputGrid.appendChild(calcCells(maxDistance));
}

inputDistance.addEventListener("click", refresh);
refresh();
#grid-body,
#grid-body-algorithm {
    float:left;
    margin-right:30px;
    box-shadow: 0 0 10px rgba(0, 0, 0, .2);
    text-align: center;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    grid-template-rows: repeat(5, 1fr);
    justify-content: center;
    align-content: end;
    border-radius: 5px;
    width:150px;
    height:150px;
    color:#444444;
    padding:1px;
}

#grid-body > *,
#grid-body-algorithm > *{
  border:1px solid white;
}
<div id="grid-body-algorithm"></div>
distance: <input type="number" value="3" min="0" max="8">

Answer №2

If you want to ensure that the DOM structure is fully loaded before accessing elements, consider using an eventListener or the defer attribute.

Avoid using innerHTML to create elements as it can be slow and poses a risk of XSS Injection. Instead, opt for methods like appendChild or insertAdjacentHTML.

Using CSS for styling rather than inline styles is recommended for cleaner code. Additionally, utilizing SASS can further streamline your styling process.

When creating grid elements dynamically, remember to use separate variables for rows and columns in your loops. The first loop should handle rows while the second loop manages columns:

window.addEventListener('DOMContentLoaded', function() {
  for (let i = 1, n = 5; i < 5; i++) {
    for (let j = 1; j < n; j++) {
      document.querySelector('#grid-body-algorithm').insertAdjacentHTML('beforeend', `
        <div data-row="${i}" data-col="${j}">${j}</div>`
      );
    }
    n--;
  }
})
#grid-body-algorithm {
  width: 150px;
  height: 150px;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-template-rows: repeat(5, 1fr);
  padding: 2px;
  gap: 2px;
  border: 1px solid black;
}

[data-row="1"] { grid-row: 1 / 2; }
[data-row="2"] { grid-row: 2 / 3; }
[data-row="3"] { grid-row: 3 / 4; }
[data-row="4"] { grid-row: 4 / 5; }
[data-row="5"] { grid-row: 5 / 6; }

[data-row="1"][data-col="1"] { background: #fd8362; }
[data-row="1"][data-col="2"],
[data-row="2"][data-col="1"] { background: #ffad97; }
[data-row="1"][data-col="3"],
[data-row="2"][data-col="2"],
[data-row="3"][data-col="1"] { background: #ffded6; }
[data-row="1"][data-col="4"],
[data-row="2"][data-col="3"],
[data-row="3"][data-col="2"],
[data-row="4"][data-col="1"] { background: #fff0ec; }
<div id="grid-body-algorithm"></div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to execute a GET request using the Fetch API on Django REST Framework results in receiving an HTTP 304 error code

When attempting a GET request with the Fetch API (Node Fetch) module against a Django REST API, I am encountering a 304 error. I am unsure of how to resolve this issue as it seems to be related to requesting the same data repeatedly. Is there no way around ...

Adding HTML content inside an iFrame at a specific cursor position in Internet Explorer

Does anyone know a method to insert HTML into an iFrame specifically for IE? I have been using execCommand insertHtml in Chrome and Firefox, but it doesn't seem to work in IE. I was able to paste HTML into a content editable div using pasteHTML, howe ...

Ways to specify the styles for tr, td, and label elements within a material table

Hey there! Currently, I'm working with material table in react. I came across this page: https://material-table.com/#/docs/features/styling, where it mentions that we can use cellStyle, headerStyle. But what if I want to add more detailed styles to e ...

How to trigger a submit action on a different page from an iframe using PHP

Is there a way to submit the iframe page using the modal's submit button in Page1.php to trigger the submit button of Page2.php? I need help executing this efficiently. The purpose of having the submit button in a modal is to perform multiple functio ...

Do HTML buttons without values get sent in a form submission?

When you have a button with the following code: <button class="button yellow" type="submit" name="button">Log in</button> and you submit it, what exactly gets sent to the server for this specific button that has a name attribute but no value ...

Create a custom overlay for an image that is centered horizontally and does not have a fixed width

I'm working with this HTML setup: <div class="container"> <img class="image" /> <div class="overlay"> <div class="insides">more content here</div> </div> &l ...

The URL is not being updated despite changes in document.location hash

I have created a script that toggles (show/hide) between different DIVs on the page (highlighted below in the various boxes =). However, I am facing an issue with updating the URL string when switching between different DIVs. For instance, if I navigate t ...

Searching for the precise draggable grid line position in rulerguides.js - tips and tricks!

Currently, I am utilizing rulerguides.js in my project. I have customized it for a specific div to display rulers and grid lines. You can refer to this FIDDLE. The rulers are functioning properly, but the draggable grid lines are being calculated based on ...

Issue arises during initialization with Slick.js

I recently attempted to implement the slick.js function on my webpage by following the guidelines provided on . I copied the "center mode" function as my Jquery function, but unfortunately, the arrows/buttons and nav-docs were not generated in my slideshow ...

Loop through options in Vue.js and set a specific option as selected

When iterating through a list of objects, I am struggling to set the status of each object as selected by default. <template> <table class="table is-striped"> <thead> <tr> <th> ...

Tips for eliminating repeated values in a textbox

<script> $("#filter").on("shown.bs.popover",function(){ $(".popover-content input[type=checkbox]").on("click",function(){ if(this.checked) { this.setAttribute("checked","checked"); } else { ...

Refresh the React state at regular intervals

constructor(){ super(); this.state={ numbers : [1,2,3,4,1,2,3,4,1,3,1,4,12,2,3,2] }; } componentDidMount(){setInterval(this.updateNumbers(),5000);} updateNumbers() { console.log(this.props.newData); let numbers = this.state.nu ...

A full-width CSS menu featuring dropdowns beneath each entry for easy navigation

Check out the JSFiddle here I've created a full-width CSS menu that spans the entire screen, but I'm struggling to figure out how to make the corresponding subnav items appear below their parent items. Is it even possible to achieve this design ...

Make jQuery fire an event when the "enter" key is pressed

I'm trying to create an event that will trigger when the "enter" key is pressed. I've been using this code, but for some reason it's not working and I can't figure out why. After searching everywhere, I came across this snippet that see ...

Tips for configuring CakePHP to trigger the second submit button when the enter key is pressed

My form includes two submit buttons: "cancel" and "find." While both buttons work correctly when clicked, pressing the enter key always triggers the submission of "cancel." I don't want to change the button order in the form. To address this issue, I ...

Discover the secret to instantly displaying comments after submission without refreshing the page in VueJS

Is there a way to display the comment instantly after clicking on the submit button, without having to refresh the page? Currently, the comment is saved to the database but only appears after refreshing. I'm looking for a solution or syntax that can h ...

Automatically execute a function when the number input changes, but only if no further changes are detected after a certain period of time

I am implementing angularjs with an input field for numbers. I want to trigger an action automatically after a certain amount of time, but only if no further changes have been made to the number within that time frame (let's say 2 seconds). In my exa ...

Code snippet for calculating the size of an HTML page using JavaScript/jQuery

Does anyone know of a way to calculate and display the size/weight (in KB) of an HTML page, similar to what is done here: Page size: 403.86KB This would include all resources such as text, images, and scripts. I came across a Pelican plugin that does th ...

sending data from a callback to an express router

As I embark on learning node.js, I've encountered a challenging issue. In my passportAuth.js file, I create a user and have a callback to ensure the user is created successfully. The code snippet looks something like this: req.tmpPassport = {}; var ...

Change web page in JavaScript using post data

Is there a method to utilize JavaScript for navigating to a new URL while including POST parameters? I am aware that with GET requests, you can simply add a parameter string to the URL using window.location.replace(). Is there a way to achieve this with ...