0

I want to create a 19 * 19 grid. Every grid square is 50px. In this grid the odd columns should have the red background, and even columns should have a green background. How to obtain this?

Here is the code I have written - with a CodePen example linked, below - with this code the grid is like in chess I don't want it to be like that.

body {
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background-color: rgba(255, 255, 255, 0.5);
  font-family: Arial, sans-serif;
}

.colored-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  /*     grid-template-rows: repeat(193, 50px); */
  column-gap: 5px;
  height: auto;
  width: 100px;
  /* To accommodate 2 columns of 50px each */
}

.grid-cell {
  width: 50px;
  height: 50px;
  box-sizing: border-box;
}

.grid-cell:nth-child(odd) {
  background-color: red;
}

.grid-cell:nth-child(even) {
  background-color: green;
}
<div class="colored-grid">
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
  <div class='grid-cell'></div>
</div>

https://codepen.io/viy_bal/pen/GRwLBBr

This is the output I want, I edited this question - Those all are squares in the grid, those are not grid-gaps

enter image description here

balaji
  • 1
  • 2
  • I've taken the liberty of copying the relevant code from the CodePen demo to a running snippet in your question; here on [SO] we require the relevant - [mcve] - code to be included in the question, an external link is appreciated, but it doesn't replace the need to have code in the question. In future, please do this yourself when writing the question. – David Thomas Aug 08 '23 at 07:41
  • Ok, I'll do it for upcoming questions – balaji Aug 08 '23 at 09:12

5 Answers5

0

Adding a wrapper for every row seems to be a good way to do this. In that case the grid's html should look somewhat like this:

<div class="colored-grid">
    <div class="wrapper">
      <div class='grid-cell'></div>
      <div class='grid-cell'></div>
      <div class='grid-cell'></div>
      <div class='grid-cell'></div>
      <div class='grid-cell'></div>
    </div>
    <div class="wrapper">
      <div class='grid-cell'></div>
      <div class='grid-cell'></div>
      <div class='grid-cell'></div>
      ...
    </div>
  </div>

Add display: contents to the wrapper's class and the rest of your code will do the job.

Here's the link helped me to find the solution.

Also, here's the codepen I've edited from yours.

ngtrthinh
  • 25
  • 7
0

To create a grid of 19 by 19 you can use js to create the cells.

HTML:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>Colored Grid</title>
</head>

<body>
    <div class="colored-grid">
        <!-- The grid will be generated using JS -->
    </div>




    <script src="script.js"></script>

</body>

** CSS **

body {
    margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: rgba(255, 255, 255, 0.5);
    font-family: Arial, sans-serif;
}

.colored-grid {
    display: grid;
    grid-template-columns: repeat(19, 50px);
    grid-template-rows: repeat(19, 50px);
    /* 19 columns of 50px each */
    gap: 5px;
    /* Gap between columns */
    height: auto;
    width: auto;
}

/* Apply red background to odd columns and green background to even columns */
.colored-grid>.even {
    background-color: red;
}

.colored-grid>.odd {
    background-color: green;
}

.grid-column {
    display: contents;
    /* To allow grid items to span entire column */
}

** JS **

   document.addEventListener("DOMContentLoaded", function () {
  const coloredGrid = document.querySelector(".colored-grid");

  // Create a 19x19 grid
  for (let row = 0; row < 19; row++) {
    for (let col = 0; col < 19; col++) {
      const cell = document.createElement("div");
      cell.classList.add("grid-cell");

      // Apply red background to odd columns and green background to even columns
      if (col % 2 === 0) {
        cell.classList.add("even");
      } else {
        cell.classList.add("odd");
      }

      coloredGrid.appendChild(cell);
    }
  }
});
SHresTho12
  • 24
  • 6
0

Glad to help you!

I've saw your code in codePen, it can't be solved with only even and odd in css, what you need is coloring column, using nth-child(odd)/nth-child(even) you will only get staggered grid just like what you said --- chess.

Solution:

Here is HTML:

<div class="colored-grid" id="GridContainer"></div>

Firstly, creating 19 * 19 grids with JavaScript, adding class name according to the result of calculating during loop.

const TOTAL = 19 * 19
const GridContainer = document.getElementById('GridContainer')
for(let i = 0; i < TOTAL; i ++) {
  const GridCell = document.createElement('div')
  GridCell.className = 'grid-cell'  // adding a basic class name
  const colorClassName = (i % 19) % 2 ? 'green' : 'red'
  GridCell.classList.add(colorClassName)
  GridContainer.appendChild(GridCell)
}

CSS:

body {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.colored-grid {
  display: grid;
  grid-template-rows: repeat(19, 1fr);
  grid-template-columns: repeat(19, 1fr);
  gap: 6px;
}

.grid-cell {
  width: 50px;
  height: 50px;
}

.green { background-color: #2d802d; }
.red { background-color: #9e2121; }

In every row, the odd is red and the even is green, so you can simply judge the x % 2 to determine its background color. And we get 19 grids in every row, so if we want to keep their rule identical, put another limit:

(i % 19)

In this way we can keep every row same.effect

You can visit code here -> My Answer

  • yep, this is the one I want. I updated the output in my question - you can see it in the image description. If I change the modulo condition can I get my updated output? – balaji Aug 08 '23 at 09:18
0

One approach – with explanatory comments in the code – is below; though I do think this should be possible with only CSS, but I can't think how, as yet.

// some simple utilities to reduce typing;
// caching a reference to the document:
let D = document,
  // an alias for document.createElement(), with the option to provide
  // properties for the created element:
  create = (tag, props) => Object.assign(D.createElement(tag), props),
  // an alias for both document.querySelector() - by default - and
  // Element.querySelector(), if an Element node is passed as the
  // context argument:
  get = (selector, context = D) => context.querySelector(selector),

  // caching a reference to the element in which the grid should
  // be appended:
  gridParent = get('.colored-grid[data-size]');

// defining a function to create the grid, taking one argument,
// the element in which the created elements are to be placed:
let createGrid = (source) => {

  // if there is no HTMLElement passed to the function we
  // return false and quit the function:
  if (!source || 1 !== source.nodeType) {
    return false;
  }

  // while the source element has any firstChild (this includes
  // text-nodes, comment nodes, and elements:
  while (source.firstChild) {
    // we use parentNode.removeChild to remove that firstChild;
    // had the childNodes been only elements, we could have
    // used HTMLElement.remove(), but that would (probably) have
    // left an accumulation of text-nodes behind in the DOM (which
    // I personally find messy, as inconsequential as it may be):
    source.removeChild(source.firstChild);
  }

  // using destructuring assignment to declare the variables
  // 'sz' and 'c', as aliases for 'size' and 'color' from
  // the source.dataset Object, as the variables need to
  // be modified for use in the function and I prefer to
  // use the 'meaningful' names once they're ready for use:
  let {
    size: sz,
    colors: c
  } = source.dataset,
    // here we create the 'size' variable, after using
    // parseInt() to convert the 'sz' string to a base-10
    // integer:
    size = parseInt(sz, 10),
    // and declare the 'colors' variable after creating an
    // array of colors from the supplied dataset-attribute;
    // first splitting the string on commas:
    colors = c.split(/,/)
    // using Array.prototype.filter() to retain
    // only those Array entries that:
    .filter(
      // both have an entry, have a non-zero length 
      // and which is not composed of just white-space:
      (color) => color && color.trim().length > 0
    )
    // we then use Array.prototype.map() to create a
    // new Array based on the filtered Array (which
    // retains or discards Array-elements, but doesn't
    // modify the Array elements):
    .map(
      // here we use String.prototype.trim() to
      // remove leading and trailing white-space:
      (color) => color.trim()
    ),
    // creating a document-fragment in order that all
    // created elements are appended to the document at
    // once, minimising reflows and repaints:
    fragment = D.createDocumentFragment();

  // to enable the size to be used in CSS, we use
  // CSSStyleDeclaration.setProperty() to set a '--size'
  // property, initialised to the value of the size integer:
  source.style.setProperty(`--size`, size);
  // we use Array.from() to create an Array from the provided
  // Object, which sets the length equal to the square of the
  // size integer (using Math.pow(<integer>,<power>) to do
  // so, but size * size would work equally well):
  Array.from({
      length: Math.pow(size, 2)
    })
    // iterating over the created Array, which passes in
    // a reference to the current Array-element (which is
    // undefined), and the index of the current Array-
    // element in the created Array:
    // within the Arrow function, we create a <div> element,
    // set its classList property using a template-literal,
    // to add the classes of 'grid-cell', 'row-n' (where n
    // is the row-number), 'row-odd' or 'row-even',
    // 'column-n' (where n is an integer, and reflects the
    // column-number), and column-odd or column-even:
    .forEach((_, i) => fragment.append(create('div', {
      classList: `grid-cell row-${ Math.floor(i/size) + 1}
                  row-${ 0 === Math.floor(i/size)%2 ? 'even' : 'odd'}
                  column-${ Math.floor(i%size) + 1}
                  column-${ 0 === Math.floor(i%size) + 1 ? 'odd' : 'even' }`,
      // we also set the --backgroundColor CSS custom property, which
      // cycles through the Array of colors passed via the data-colors
      // attribute:
      style: `--backgroundColor: ${ colors[(i%size)%colors.length] }`
      // the created element (on each iteration of the forEach()) is
      // appended to the document fragment using the initial fragment.append()
    })));

  // appending the fragment to the source, using Element.append():
  source.append(fragment);

};

// calling the function, passing in the gridParent element:
createGrid(gridParent);

// the below is largely irrelevant, it's just to enable some editing:
// here we use an Array literal along with spread syntax to create an
// Array of the child elements of the <fieldset> element; we then use
// Array.prototype.forEach() to iterate over those child-elements:
[...get('fieldset').children].forEach(
  // passing a reference to the current child element to the function:
  (child) => {
    // caching a reference to the <input> element within the
    // current child element:
    let input = get('input', child);

    // setting the value of the <input> to be equal to
    // the data-[input.name] attribute-value of the
    // gridParent element; so the value of the <input>
    // is equal to the current attribute-values on page-
    // load:
    input.value = gridParent.dataset[input.name];

    // binding the anonymous function as the event-handler
    // for the 'input' event:
    input.addEventListener('input', (evt) => {
      // using destructuring assignment to set
      // the variable 'target' to be equal to the
      // 'target' property-value of the Event (evt)
      // Object:
      let {
        target
      } = evt, {
        name,
        value
      } = target;

      // setting the gridParent's dataset[input.name]
      // attribute value to be equal to the value of the
      // <input>:
      gridParent.dataset[name] = value;
      createGrid(gridParent);
    });
  });
*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  margin: 0;
  display: flex;
  flex-flow: column nowrap;
  gap: 1rem;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  /* using syntax from level 4 of the
     CSS Colors Module: */
  background-color: rgb(255 255 255 / 0.5);
  font-family: Arial, sans-serif;
}

form {
  backdrop-filter: blur(3px) brightness(300%) hue-rotate(25deg);
  background-color: #fff7;
  position: sticky;
  top: 0;
}

fieldset {
  display: flex;
  gap: 1rem;
  justify-content: space-between;
}

label {
  display: grid;
  gap: 0.5rem;
  padding: 0.5rem;
}

.colored-grid {
  counter-reset: cell;
  display: grid;
  gap: 5px;
  height: auto;
  grid-auto-rows: 50px;
  grid-template-columns: repeat(var(--size), 50px);
}

.grid-cell {
  background-color: var(--backgroundColor);
  counter-increment: cell;
}


/*
.grid-cell:nth-child(odd) {
  background-color: red;
}

.grid-cell:nth-child(even) {
  background-color: green;
}
*/

.even {
  background-color: red;
}

.odd {
  background-color: green;
}
<form action="#" method="post">
  <fieldset>
    <label>
      <span class="labelText">Number of grid-cells:</span>
      <input type="number" min="1" max="20" step="1" name="size"></label>
    <label>
      <span class="labelText">grid-column colours:</span>
      <input type="text" name="colors"></label>
  </fieldset>
</form>

<!--
  data-size: an integer, to define the number of cells on each axis,
  data-colors: a comma-separated list of colors to cycle through:
-->
<div class="colored-grid" data-size="10" data-colors="red, green"></div>

JS Fiddle demo.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
0

It can be achieved using css grid layout and :nth-child() selector.

.box {
  display: grid;
  height: 400px;
  width: 400px;
  gap: 10px;
  padding: 10px;
  grid-template-columns: repeat(3, auto);
}

.box > div {
  background-color: red;
}
.box > div:nth-child(2n) {
  background-color: green;
}
<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

You can add more child divs and change the number of columns inside grid-template-columns property which is 3 in this example.