为什么行内元素底部有额外的边距?

4
我有以下测试页面。基本上,它会在鼠标下方绘制一个边框,并在元素的左下角显示工具提示。对于块级元素,没有问题。

enter image description here

但对于内联元素,高亮元素和工具提示之间总是有间隙。

enter image description here

我试图为这些内联元素添加0边距,但没有效果。有人能帮忙指点一下方向吗? 为了更容易调试,我创建了这个CodePen链接:https://codepen.io/ogrishman/pen/gObMNWa

var tip = jQuery("<div id='tip' style='display:none;'></div>");
tip.appendTo("body");
jQuery("*").on("mouseover", function (event) {
    event.stopPropagation();
    var thisj = jQuery(this);
    var thisj_pos = thisj.offset();

    thisj.css("border", "2px solid red");
    tip.text(thisj.prop("tagName"));

    $("#tip").css({
        "top": thisj_pos.top + thisj.outerHeight(),
        "left": thisj_pos.left,
        display: "block"
    });
}).on("mouseout", function (event) {
    event.stopPropagation();
    jQuery(this).css("border", "")
});
#b {
  width: 200px;
  height: 200px;
  background: #0fa3e0;
  border: 10px solid grey;
  position: absolute;
  top: 50px;
  left: 100px;
}

#s {
  width: 50px;
  height: 50px;
  background: #ff0000;
  border: 10px solid gold;
  position: absolute;
}

#tip {
  border-radius: 0 0 5px 5px;
  border: 2px solid #000000;
  background-color: #fdf0ca;
  position: absolute;
  color: #000000;
  padding: 3px;
}
<div id="b"></div>
<div id="s"></div>
<div style="position: absolute; top: 300px;">
    <a href="#">Test anchor 1</a>
    <a href="#">Test anchor 2</a>
    <a href="#">Test anchor 3</a>
    <a href="#">Test anchor 4</a>
    <a href="#">Test anchor 5</a>
    <br />
    <span>Test span 1</span>
    <span>Test span 2</span>
    <span>Test span 3</span>
    <span>Test span 4</span>
    <span>Test span 5</span>
    <br />
    <p>test paragraph 1</p>
    <p>test paragraph 2</p>
    <p>test paragraph 3</p>
    <p>test paragraph 4</p>
    <p>test paragraph 5</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

3个回答

3

这是因为你在获取元素的偏移量后再应用边框。由于行内元素的边框上/下在布局方面没有影响,它不会将元素向下推,因此你将得到一个与边框顶部厚度完全相等的间隙。

在添加边框之前获取正确的偏移量并解决问题:

var tip = jQuery("<div id='tip' style='display:none;'></div>");
tip.appendTo("body");
jQuery("a").on("mouseover", function(event) {
  event.stopPropagation();
  var thisj = jQuery(this);
   thisj.css("border", "5px solid red");
  var thisj_pos = thisj.offset();

  tip.text(thisj.prop("tagName"));

  $("#tip").css({
    "top": thisj_pos.top + thisj.outerHeight(),
    "left": thisj_pos.left,
    display: "block"
  });
}).on("mouseout", function(event) {
  event.stopPropagation();
   jQuery(this).css("border", "")
});
#tip {
  border-radius: 0 0 5px 5px;
  border: 2px solid #000000;
  background-color: #fdf0ca;
  position: absolute;
  color: #000000;
  padding: 3px;
}
<a href="#" >Test j anchor 1</a>
<a href="#" >Test anchor 2</a>
<a href="#" >Test anchor 3</a>
<a href="#" >Test anchor 4</a>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

这里有一段代码以更好地说明问题:

var tip = jQuery("<div id='tip' style='display:none;'></div>");
tip.appendTo("body");
jQuery("a.before").on("mouseover", function(event) {
  event.stopPropagation();
  var thisj = jQuery(this);
   thisj.css("border", "10px solid red");
  var thisj_pos = thisj.offset();

  tip.text(thisj.prop("tagName"));
  console.log(thisj_pos.top)
  $("#tip").css({
    "top": thisj_pos.top + thisj.outerHeight(),
    "left": thisj_pos.left,
    display: "block"
  });
}).on("mouseout", function(event) {
  event.stopPropagation();
   jQuery(this).css("border", "")
});
jQuery("a.after").on("mouseover", function(event) {
  event.stopPropagation();
  var thisj = jQuery(this);
  var thisj_pos = thisj.offset();
   thisj.css("border", "10px solid red");

  tip.text(thisj.prop("tagName"));
 console.log(thisj_pos.top)
  $("#tip").css({
    "top": thisj_pos.top + thisj.outerHeight(),
    "left": thisj_pos.left,
    display: "block"
  });
}).on("mouseout", function(event) {
  event.stopPropagation();
   jQuery(this).css("border", "")
});
#tip {
  border-radius: 0 0 5px 5px;
  border: 2px solid #000000;
  background-color: #fdf0ca;
  position: absolute;
  color: #000000;
  padding: 3px;
}

a {
 margin: 0 10px;
}
<a href="#" class="before">inline element</a>
<a href="#" class="after">inline element</a>
<a href="#" class="before" style="display:inline-block;">inline block element</a>
<a href="#" class="after" style="display:inline-block;">inline block element</a>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

您可以清楚地看到,当您为内联元素添加边框时,它们不会向下移动,而内联块(或块)元素则会。使用内联块,在边框之前或之后添加边框没有区别,因为元素始终具有相同的顶部值,但是在添加边框后内联元素的顶部值将不同:


非常感谢您详细的回答! - Just a learner

1
为了给内联元素添加边距,你需要添加 display: inline-block。我记得,display: inline 不考虑 box-model。 基本上,盒模型让我们管理元素的边距/填充。 在此了解更多关于盒模型的内容:https://www.w3schools.com/css/css_boxmodel.asp

2
嗯,你说得对。不过我认为 OP 的问题是“为什么会有间隙?”,而不是“如何更改内联元素的边距?”这并没有真正回答实际问题。 - gforce301
3
据我所记,display:inline不考虑盒模型是错误的,而且这样的回答获得3个赞让人感到可疑。 - Temani Afif
更可疑的是,我将其标记为“不是答案”,但它已经成功地被争议。 - gforce301
@TemaniAfif 我想SO现在正在发放参与奖杯。你甚至没有接近正确答案,也不应该有人阅读你的错误信息,但我们会为你的尝试给予积分。 - gforce301

1

try this one:

const boundingClientRect = this.getBoundingClientRect()

$("#tip").css({
    top: boundingClientRect.top + boundingClientRect.height + window.scrollY,
    left: boundingClientRect.left + window.scrollX,
    display: "block"
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接