11

Is there a way to dynamically detect in javascript which grid column and row an element is in, in a CSS grid?

I have a grid that I set up with three breakpoints so that it either has 4, 3, or 2 columns.

What I want to do is if a user clicks in a cell, dynamically overlay a new element in the cell immediately to the right of the cell that was clicked, except if it's in the right-most column, in which case the overlay element will go in the cell to the left.

I know I can use grid-column and grid-row to specify the cell I want to put the new thing in, but in order to be able to use that, I need to know the column and row of the cell that was clicked.

How can I dynamically determine that?

Art
  • 2,836
  • 4
  • 17
  • 34
Dylan Cristy
  • 916
  • 11
  • 29
  • Does this answer your question? https://stackoverflow.com/questions/55108800/is-there-a-way-to-directly-access-the-actual-grid-coordinates-of-an-auto-placed – clickbait Mar 22 '22 at 03:20
  • Does this answer your question? https://stackoverflow.com/questions/51327802/how-to-get-the-grid-coordinates-of-an-element-using-javascript – clickbait Mar 22 '22 at 03:20

1 Answers1

8

Here. Bind it to a click, but you can have access to this function any way you like. Click on block to see if it is last columns or not. The function accepts current grid-template-columns so it will work on any breakpoint.

//Add click event for any child div of div = grid
$(document).ready(function() {
  $('.grid').on('click', 'div', function(e) {  
    GetGridElementsPosition($(this).index(), $(this)); //Pass in the index of the clicked div
  });
});

function GetGridElementsPosition(index, element) {

  //Get the css attribute grid-template-columns from the css of class grid
  //split on whitespace and get the length, this will give you how many columns
  const colCount = $('.grid').css('grid-template-columns').split(' ').length;
  const colPosition = index % colCount;
  const rowPosition = Math.floor(index / colCount);
  
  /* determine if it is a last column */
  if (colPosition==(colCount-1)) {
    $(element).html('row:'+rowPosition+'. col:'+colPosition+'. Last column');
  } else {
    $(element).html('row:'+rowPosition+'. col:'+colPosition+'. Not last column');
  }

}
.grid {
  display: grid;
  grid-template-columns: repeat( 3, 1fr );
  grid-row-gap: 1em;
  grid-column-gap: 1em;
}

.grid div {
  height: 2em;
  background: blue;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="grid">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>
focus.style
  • 6,612
  • 4
  • 26
  • 38
  • Interesting, did this solution helps you? – focus.style May 27 '20 at 23:42
  • I ended up not actually having to do what I was describing, I set up the grid items to do a "card flip" kind of animation to keep the additional element in the same grid cell as what was clicked. But the key `$('.grid').css('grid-template-columns').split(' ').length` was _exactly_ what I was looking for. – Dylan Cristy Jun 16 '20 at 16:13
  • This is a good try at an answer, but unfortunately it won't handle anything more complex, like cells that span multiple columns, `auto-fit`, `minmax`, etc. AFAIK, there is no convenient way to get the resulting row/col indices that the browser computes for an element. – V. Rubinetti Mar 25 '22 at 19:20
  • Unfortunately this only works if all cells are the same size (as V. Rubinetti points out) – Ilia Sidorenko Jul 29 '22 at 11:01