javascript - 为什么链接 offsetLeft 考虑列表填充?

标签 javascript html css

我正在读取链接元素的 offsetLeft 属性并相应地更改另一个元素的位置。但是,只有在没有将任何样式(甚至浏览器默认)应用于位置属性的情况下,这才可以按预期工作。例如:ul padding 的变化会影响 li offsetLeft 并导致从预期位置发生偏移。

navbarElementsList = document.getElementsByClassName('js-element');
navbarUnderline = document.getElementById('js-underline');
let navbarElement;

for (let i = 0, len = navbarElementsList.length; i < len; i++) {
    navbarElement = navbarElementsList[i];
    navbarElementsList[i].addEventListener('click', function(event){
        let underlineStart = this.offsetLeft;
        let underlineWidth = this.offsetWidth;
        document.getElementById('js-underline').style.left = underlineStart.toString() + "px";
        document.getElementById('js-underline').style.width = underlineWidth.toString() + "px";
    });
}
ul {
    list-style-type: none;
}
li {
    display: inline;
}
a {
    cursor: pointer;
}
#js-underline {
    position: relative;
    left: 0;
    width: 25px;
    height: 5px;;
    background-color: blue;
    transition: 0.5s ease;
    -moz-transition: 0.5s ease;
    -webkit-transition: 0.5s ease;
}
<!DOCTYPE html>
<html lang="pl">
<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>test</title>
  
</head>
<body>

    <ul style=" margin-left: 40px ;">
      <li><a class="c-navbar__element js-element">aaaaaaa</a></li>
      <li><a class="c-navbar__element js-element">bbbb</a></li>
      <li><a class="c-navbar__element js-element">c</a></li>
      <li><a class="c-navbar__element js-element">ddddddddddddddd</a></li>
      <li><div id="js-underline" class="c-navbar__underline"></div></li>
    </ul>

</body>
</html>

在上面的示例中,我将 ul margin-left 更改为 40px,不幸的是它加起来达到了最终的 #underline 位置。谁能解释这种行为并告诉我如何正确实现?我将非常感谢您的帮助。

最佳答案

Element.offsetNNN是相对于其 offsetParent ,这里所有元素都有其 offsetParent设置为 <body>元素。

您的#js-underline也受该填充的影响,或者更准确地说,受其父填充的影响。

因此,当您将该元素设置为其他元素的 offsetLeft 时,它自己的offsetLeft也还在那里。

一个丑陋的解决方法是在 left 时测量 offsetLeft样式是0 ;

const navbarElementsList = document.getElementsByClassName('js-element');
const navbarUnderline = document.getElementById('js-underline');
const default_left = navbarUnderline.offsetLeft;
let navbarElement;

for (let i = 0, len = navbarElementsList.length; i < len; i++) {
    navbarElement = navbarElementsList[i];
    navbarElementsList[i].addEventListener('click', function(event){
        let underlineStart = this.offsetLeft;
        let underlineWidth = this.offsetWidth;
        navbarUnderline.style.left = underlineStart - default_left + "px";
        navbarUnderline.style.width = underlineWidth.toString() + "px";
    });
}
ul {
    list-style-type: none;
}
li {
    display: inline;
}
a {
    cursor: pointer;
}
#js-underline {
    position: relative;
    left: 0;
    width: 25px;
    height: 5px;;
    background-color: blue;
    transition: 0.5s ease;
    -moz-transition: 0.5s ease;
    -webkit-transition: 0.5s ease;
}
<!DOCTYPE html>
<html lang="pl">
<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>test</title>
  
</head>
<body>

    <ul style=" margin-left: 40px ;">
      <li><a class="c-navbar__element js-element">aaaaaaa</a></li>
      <li><a class="c-navbar__element js-element">bbbb</a></li>
      <li><a class="c-navbar__element js-element">c</a></li>
      <li><a class="c-navbar__element js-element">ddddddddddddddd</a></li>
      <li><div id="js-underline" class="c-navbar__underline"></div></li>
    </ul>

</body>
</html>

另一种方法是绝对定位下划线,以便边距不再影响它。

const navbarElementsList = document.getElementsByClassName('js-element');
const navbarUnderline = document.getElementById('js-underline');

let navbarElement;

for (let i = 0, len = navbarElementsList.length; i < len; i++) {
    navbarElement = navbarElementsList[i];
    navbarElementsList[i].addEventListener('click', function(event){
        let underlineStart = this.offsetLeft;
        let underlineWidth = this.offsetWidth;
        navbarUnderline.style.left = underlineStart + "px";
        navbarUnderline.style.width = underlineWidth + "px";
    });
}
// set to firt item
navbarElementsList[0].click();
ul {
    list-style-type: none;
}
li {
    display: inline;
}
a {
    cursor: pointer;
}
#js-underline {
    position: absolute;
    left: 0;
    width: 25px;
    height: 5px;;
    background-color: blue;
    transition: 0.5s ease;
    -moz-transition: 0.5s ease;
    -webkit-transition: 0.5s ease;
}
<!DOCTYPE html>
<html lang="pl">
<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>test</title>
  
</head>
<body>

    <ul style=" margin-left: 40px ;">
      <li><a class="c-navbar__element js-element">aaaaaaa</a></li>
      <li><a class="c-navbar__element js-element">bbbb</a></li>
      <li><a class="c-navbar__element js-element">c</a></li>
      <li><a class="c-navbar__element js-element">ddddddddddddddd</a></li>
      <li>
        <div id="js-underline" class="c-navbar__underline"></div>      
      </li>
    </ul>


</body>
</html>

关于javascript - 为什么链接 offsetLeft 考虑列表填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61512636/

相关文章:

html - 我怎样才能制作一个直 Angular 三 Angular 形的语音框(CSS)

html - Bootstrap 中的垂直对齐响应容器

Javascript - 将字符串附加到包含点字符的对象的键

javascript - 更改在 HTML5 canvas 元素上绘制的图像的颜色

javascript - 了解 HTML anchor 标记

javascript - 防止输入失去焦点

javascript - div问题的奇偶选择器

javascript - jQuery根据rel属性替换div

javascript - Protractor/WebDriverJS 将元素值作为对象数组返回

html - 无法删除文字装饰?