3

When elements are laid out using flexbox, I'd like to know what their top and left is relative to the window.

Is this possible?

Using window.getComputedStyle returns auto for both top and left properties.

const cells = document.querySelectorAll('.cell')

cells.forEach(cell => {
  cell.addEventListener('click', function(event) {
    const cell = event.target;
    const left = getComputedStyle(cell).left;
    const top = getComputedStyle(cell).top;
    document.getElementById('display').innerHTML = 'Left: ' + left + ' - Top: ' + top;
  });
})
.container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 50vh;
  margin: 0 auto;
  justify-content: center;
  align-items: center;
}

.container .row {
  display: flex;
}

:root {
  --cell-size: 20px;
}

.container .row .cell {
  width: var(--cell-size);
  height: var(--cell-size);
  background-color: steelblue;
  border: 1px #ccc solid;
  border-radius: 100%;
  margin: calc(var(--cell-size) / 4);
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Animation demo</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <div>Click a flex child to see its computed top and left</div>
    <div id="display">&nbsp;</div>
    <div class="row">
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
    </div>
  </div>
</body>
</html>
TylerH
  • 20,799
  • 66
  • 75
  • 101
LondonRob
  • 73,083
  • 37
  • 144
  • 201
  • You won't be able to get the computed style because left and top are only computed when the element is absolute positioned. – David Gomez Oct 16 '18 at 18:44
  • Partial duplicate of https://stackoverflow.com/questions/442404/retrieve-the-position-x-y-of-an-html-element - covers the getting left and top offsets, but not the condition of "only flex elements". – TylerH Oct 16 '18 at 18:46

1 Answers1

4

You want .offsetLeft and .offsetTop:

const cells = document.querySelectorAll('.cell')

cells.forEach(cell => {
  cell.addEventListener('click', function(event) {
    const cell = event.target;
    const left = cell.offsetLeft;
    const top = cell.offsetTop;
    document.getElementById('display').innerHTML = 'Left: ' + left + ' - Top: ' + top;
  });
})
.container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 50vh;
  margin: 0 auto;
  justify-content: center;
  align-items: center;
}

.container .row {
  display: flex;
}

:root {
  --cell-size: 20px;
}

.container .row .cell {
  width: var(--cell-size);
  height: var(--cell-size);
  background-color: steelblue;
  border: 1px #ccc solid;
  border-radius: 100%;
  margin: calc(var(--cell-size) / 4);
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Animation demo</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <div>Click a flex child to see its computed top and left</div>
    <div id="display">&nbsp;</div>
    <div class="row">
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
      <div class="cell"></div>
    </div>
  </div>
</body>
</html>
inorganik
  • 24,255
  • 17
  • 90
  • 114
  • 1
    Are these values definitely right? If I add a div with `position: absolute` and a top and left of the `offsetLeft` and `offsetTop` of one of the flexbox children, they don't *quite* line up! – LondonRob Oct 16 '18 at 21:33
  • My bad: needed to take the margins into account! – LondonRob Oct 16 '18 at 21:36