Home > Enterprise >  how to prevent grid from changing size
how to prevent grid from changing size

Time:08-28

I made grid 16x16 with borders for each cell, then i added a button to toggle on/off borders of those cells, but it also changes overall size of my grid. how do i prevent this?

in the future i want to implement "change size" button that will increase numbers of cells but not change grid size. I'm sure i need to define grid size somehow but i don know how. Whatever i try either messes up grid size or cell size or both

here is my code

const grid = document.getElementById('grid');
const size = document.getElementById('size');
const eraser = document.getElementById('eraser');
const color = document.getElementById('color');
const gridBorder = document.getElementById('grid-borders');

// grid
function makeGrid(number) {
  grid.style.gridTemplateColumns = `repeat(${number}, 1fr)`;
  grid.style.gridTemplateRows = `repeat(${number}, 1fr)`;
  for (let i = 0; i < number * number; i  ) {
    let cell = document.createElement('div');
    grid.appendChild(cell).setAttribute('id', 'box');
  }
}
makeGrid(16);

// drawing on hover
color.addEventListener('click', function () {
  grid.addEventListener('mouseover', function (e) {
    e.target.style.backgroundColor = 'black';
  });
});

// erase functionality
eraser.addEventListener('click', function () {
  grid.addEventListener('mouseover', function (e) {
    e.target.style.backgroundColor = 'white';
  });
});

// gird borders
const allBoxes = document.querySelectorAll('#box');
gridBorder.addEventListener('click', function () {
  for (let i = 0; i < allBoxes.length; i  ) {
    if (allBoxes[i].style.border === '1px solid black') {
      allBoxes[i].style.border = 'none';
    } else {
      allBoxes[i].style.border = '1px solid black';
    }
  }
});
body {
  height: 100vh;
}

#grid {
  display: grid;
  justify-content: center;
  border: 1px solid #ccc;
}

#box {
  padding: 1em;
  border: 1px solid black;
}

#title {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 230px;
}

#container {
  display: flex;
  height: 60%;
  width: 1204px;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 20px;
}

#menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Etch-a-Sketch</title>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js" defer></script>
  </head>
  <body>
    <div id="title">
      <h1>Etch-a-Sketch</h1>
    </div>
    <main id="container">
      <div id="menu">
        <button id="size">Canvas Size</button>
        <button id="color">Color</button>
        <button id="eraser">Eraser</button>
        <button id="grid-borders">Grid Borders</button>
      </div>
      <div id="grid"></div>
    </main>
  </body>
</html>

CodePudding user response:

Instead of using an actual border around grid items, use grid-gap prop along with background-color of the grid itself:

#grid {
  ...
  grid-gap: 1px;
  background-color: black;
}

Refer to the documentation for more info.

CodePudding user response:

You can use outline instead of border. Change your CSS box definition and remove the border there as it will be used to query your box class.

NOTE: I added a box and border class initially when creating your boxes as querying multiple elements should be targeted using a class and not a unique ID.

Now that you have the class targeted, you can simple toggle classes with the click event and use css to add/remove -> toggle the outlines state using its corresponding toggled class style.

I also added a conditional to check which event is being fired in your hover state listener, this will prevent the grid from being toggled so only its children, then boxes are toggled.

Let me know if you have any issues with the code or if this isn't working for your needs and I can either remove this answer or edit to tailor any other issues you may be having.

const grid = document.getElementById('grid');
const size = document.getElementById('size');
const eraser = document.getElementById('eraser');
const color = document.getElementById('color');
const gridBorder = document.getElementById('grid-borders');

// grid
function makeGrid(number) {
  grid.style.gridTemplateColumns = `repeat(${number}, 1fr)`;
  grid.style.gridTemplateRows = `repeat(${number}, 1fr)`;
  for (let i = 0; i < number * number; i  ) {
    let cell = document.createElement('div');
    grid.appendChild(cell).id = 'box';
    // added class border and box
    cell.classList.add('border'); //--> border will be used to toggle outline in css
    cell.classList.add('box') //--> box used to query all the dynamically created box elements
  }
}

makeGrid(16);

// drawing on hover
color.addEventListener('click', function() {
  grid.addEventListener('mouseover', function(e) {
    // make sure event.target is not the grid itself
    e.target !== grid ? e.target.style.backgroundColor = 'black' : null;
  });
});

// erase functionality
eraser.addEventListener('click', function() {
  grid.addEventListener('mouseover', function(e) {
    // make sure event.target is not the grid itself
    e.target !== grid ? e.target.style.backgroundColor = 'white' : null;
  });
});

// grid borders
const allBoxes = document.querySelectorAll('.box');
gridBorder.addEventListener('click', function() {
  // added a forEach method to toggle classes in order to track click state and style using css styling
  allBoxes.forEach(box => {
    box.classList.toggle('no-border');
    box.classList.toggle('border');
  })

});
body {
  height: 100vh;
}

#grid {
  display: grid;
  justify-content: center;
  border: 1px solid #ccc;
}

.box {
  /* removed the initial outline &/or border property here so it can be added and removed (toggled) using JS el.classList.toggle */
  padding: 1em;
}

#title {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 230px;
}

#container {
  display: flex;
  height: 60%;
  width: 1204px;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 20px;
}

#menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
}


/* added the following classes to be toggled using JS depending on state of gridBorders button */

.border {
  outline: 1px solid black;
}

.no-border {
  outline: none;
}

.black-bg {
  background: black;
}

.white-bg {
  background: white;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Etch-a-Sketch</title>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js" defer></script>
</head>

<body>
  <div id="title">
    <h1>Etch-a-Sketch</h1>
  </div>
  <main id="container">
    <div id="menu">
      <button id="size">Canvas Size</button>
      <button id="color">Color</button>
      <button id="eraser">Eraser</button>
      <button id="grid-borders">Grid Borders</button>
    </div>
    <div id="grid"></div>
  </main>
</body>

</html>

  • Related