CSS悬停边框会使元素微调

75

我有一个包含锚点的无序列表。我有一个CSS :hover事件,它会添加边框,但当我悬停时,所有锚点都会向左微调,因为它添加了1像素的宽度并自动调整。如何确保位置是绝对的?

div a:visited, #homeheader a{
    text-decoration:none;
    color:black;
    margin-right:5px;
}
div a:hover{
    background-color:#D0DDF2;
    border-radius:5px;
    border:1px solid #102447;
}

div li{
    padding:0;
    margin:0px 10px;
    display:inline;
    font-size:1em;
}
<div>
    <ul>
        <li><a href ="#">this</a></li>
        <li><a href ="#">that</a></li>
        <li><a href="#">this again</a></li>
        <li><a href="#">that again</a></li>
    </ul>
</div>

我在这里制作了一个JS Fiddle演示


3
边框在大小计算中很重要,因此如果你添加了1像素的边框,你需要将高度/宽度缩小1像素来进行补偿。 - Marc B
14个回答

119

在非悬停状态下添加透明边框可以避免边框出现时的"跳动"问题:

http://jsfiddle.net/TEUhM/3/

#homeheader a:visited, #homeheader a{
    border:1px solid transparent;
}

我偶然发现这个问题,并惊讶地发现没有人在 border: 1px solid transparent; css 中包含 background-clip: padding-box;。对我来说,同时包含这两个条目似乎是必须的,以解决这个问题。 - Borgboy
顺便提一下,如果有人遇到同样的问题,给bootstrap导航标签添加透明背景会表现不同(其中活动的导航标签具有不同的字体颜色和背景颜色)。对我来说,使用rgba是有效的:border: 1px solid rgba(0, 0, 0, 0);,其中最后一个0表示透明度。 - Anupam
这会添加额外的空格。如果我不想要那个额外的空格呢? - Hope
1
@Hope https://dev59.com/MWox5IYBdhLWcg3wyHTc - Wesley Murch

22

您还可以使用outline,它不会影响宽度,即没有“跳跃”效果。但是,对于圆形轮廓的支持可能有限。


12

你可以使用盒阴影而不是边框来实现这种功能。

这是因为你的阴影不会在DOM中占据空间,所以不像边框会影响定位。

尝试使用类似于以下声明:

box-shadow: 0 0 0 2px black;
box-shadow:0 0 1px 1px #102447;

代替你的。
border:1px solid #102447;

在您的悬停状态下。

以下是其快速演示:

演示

#homeheader a:visited,
#homeheader a {
  text-decoration: none;
  color: black;
  margin-right: 5px;
}
#homeheader a:hover {
  background-color: #D0DDF2;
  border-radius: 5px;
  box-shadow: 0 0 1px #102447;
}
#homeheader li {
  padding: 0;
  margin: 0px 10px;
  display: inline;
  font-size: 1em;
}
<div id="homecontainer">
  <div id="homeheader">
    <ul>
      <li><a href="#">this</a>
      </li>
      <li><a href="#">that</a>
      </li>
      <li><a href="#">this again</a>
      </li>
      <li><a href="#">that again</a>
      </li>
    </ul>
  </div>
</div>


7

幸运的是,这几乎从不必要。而且你尽量不去做也适合你。 :) - GolezTrol

7

在承受长时间压力后,我找到了一个很酷的解决方案。希望它能帮助其他人。

在下面添加以下代码:

HTML

<div class="border-test">
  <h2> title </h2>
  <p> Technology founders churn rate niche market </p>
</div>

CSS

.border-test {
  outline: 1px solid red;
  border: 5px solid transparent;
}
.border-test:hover {
  outline: 0px solid transparent;
  border: 5px solid red;
}

检查现场:演示链接

希望这将有所帮助。


“traparent” 对我来说似乎是个打字错误。 - byxor
1
它的打字错误是透明的。 - Siful Islam
这是一个很棒的黑客技巧。谢谢! - GeoMeteoMe

5

这里还没有提到,但在我看来,最好且简单的解决方案是使用“盒阴影”而非边框。其神奇之处在于“inset”值,它使其类似于边框。

box-shadow: inset 0 -3px 0 0 red;

您可以通过偏移X或Y来更改顶部/底部,并对相反的侧面使用负值。

.button {
  width: 200px;
  height: 50px;
  padding: auto;
  background-color: grey;
  text-align: center;
}

.button:hover {
  box-shadow: inset 0 -3px 0 0 red;
  background-color: lightgrey;
}
<div class="button"> Button </div>


4

3

CSS中的"box-sizing"属性帮助我解决了这个问题。如果您为元素设置了

.class-name {
    box-sizing: border-box; 
}

然后当浏览器计算宽度时,边框的宽度会被添加到盒子的内部。这样,当你打开或关闭边框样式时,元素的大小不会改变(这就是导致你观察到抖动的原因)。
虽然这是一种新技术,但支持border-box的浏览器相当稳定。这里有一个演示

2
这绝对是最优雅的解决方案。 - gion_13

3
只需将以下代码添加到您的CSS文件中。
#homeheader a {
    border:1px solid transparent;
}

2

这个可以工作,但是当与border-radius一起使用时,它会忽略圆角。 - byxor

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