Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is getBoundingClientRect().left returning a wrong value?

Tags:

javascript

css

I want to position a div ".indicator" just where a li element starts, so for example, if I want to position the div in relation to the second li, I do:

indicator.style.left = li[1].getBoundingClientRect().left+"px";

This is my code:

var li = document.querySelectorAll(".ulcontainer > li");

var indicator = document.querySelector(".indicator");

indicator.style.left = li[1].getBoundingClientRect().left+"px";
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
.ulcontainer {
    white-space: nowrap;
    padding: 0;
    position: relative;
}
.ulcontainer li {
    list-style: none;
    display: inline-block;
    border: 1px solid;
    padding: 0 20px;
}

.indicator {
    background-color: red;
    display: inline-block;
    position: relative;
}
<ul class="ulcontainer">
    <li>OPTION 1</li><li>OPTION 2</li><li>OPTION 3</li>
</ul>
<div class="indicator">indicator</div>

The problem is that the div getBoundingClientRect().left is not returning the correct value for the li elements. If you run the example, you will see that ".indicator" is not starting in the beggining of the current li.

Why is not getBoundingClientRect().left returning the current value?

like image 937
Boel Avatar asked Jun 08 '15 14:06

Boel


1 Answers

.indicator has relative positioning. So any offset will be relative to its default position, not relative to the browser window. (To contrast, fixed position is nearly always relative to the browser window, and absolute position is relative to the nearest-positioned ancestor – which is often the browser window.)

Since .indicator is a block-level element, and its immediate parent is the document body, its default left position is equal to the left margin of the document body.

Set body margin to 0, and it will line up:

var li = document.querySelectorAll(".ulcontainer > li");

var indicator = document.querySelector(".indicator");

indicator.style.left = li[1].getBoundingClientRect().left+"px";
body {
  margin: 0;
}
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
.ulcontainer {
    white-space: nowrap;
    padding: 0;
    position: relative;
}
.ulcontainer li {
    list-style: none;
    display: inline-block;
    border: 1px solid;
    padding: 0 20px;
}

.indicator {
    background-color: red;
    display: inline-block;
    position: relative;
}
<ul class="ulcontainer">
    <li>OPTION 1</li><li>OPTION 2</li><li>OPTION 3</li>
</ul>
<div class="indicator">indicator</div>
like image 199
Rick Hitchcock Avatar answered Oct 16 '22 18:10

Rick Hitchcock