行内元素在悬停时加粗时发生移动

我使用HTML列表和CSS创建了一个水平菜单。一切工作,它应该除了当你悬停在链接。您可以看到,我为链接创建了一个粗体悬浮状态,现在菜单链接因为粗体大小的差异而移动。

我遇到了与这篇SitePoint文章相同的问题。然而,这篇文章并没有合适的解决方案。我到处寻找解决办法,但没有找到。

.我肯定不是唯一一个想这么做的人

有人有什么想法吗?

附注:我不知道菜单项中文本的宽度,所以我不能只设置li项的宽度。

.nav { margin: 0; padding: 0; }
.nav li {
list-style: none;
display: inline;
border-left: #ffffff 1px solid;
}
.nav li a:link, .nav li a:visited {
text-decoration: none;
color: #000;
margin-left: 8px;
margin-right: 5px;
}
.nav li a:hover{
text-decoration: none;
font-weight: bold;
}
.nav li.first { border: none; }
<ul class="nav">
<li class="first"><a href="#">item 0</a></li>
<li><a href="#">item 1</a></li>
<li><a href="#">item 2</a></li>
<li><a href="#">item 3</a></li>
<li><a href="#">item 4</a></li>
</ul>

216842 次浏览

如果您不能设置宽度,那么这意味着宽度将随着文本变得粗体而改变。除了修改每个状态的填充/边距之类的妥协,没有办法避免这种情况。

我建议不要在hover时切换字体(°)。在这种情况下,只是菜单项移动了一点,但我曾见过由于扩大导致额外的换行导致整个段落重新格式化的情况。你不希望看到这种情况发生时,你所做的唯一的事情是移动光标;如果你什么都不做,页面布局应该不会改变。

在正常和斜体之间切换时也会发生偏移。我会尝试改变颜色,或者切换下划线,如果你有文字下面的空间。(下划线应该远离底部边框)

如果我在窗体设计课上使用切换字体,我会被嘘的:-)

字体这个词经常被误用。“Verdana”是一个字体,“Verdana normal”和“Verdana bold”是同一字体的不同字体

我真的无法忍受有人告诉你不要那样做,而其实有一个简单的解决方法。我不确定li元素,但我刚刚修复了相同的问题。我有一个由div标签组成的菜单。

只需将div标签设置为“display: inline-block”。内联,所以他们坐在彼此和块,你可以设置宽度。只需要设置足够宽的宽度来容纳粗体文本,并使文本居中对齐。

(注意:它似乎剥离了我的html[下面],但每个菜单项都有一个div标签围绕它与corrasponding ID和类名searchbar_category。即:<div id="ROS_SearchSermons" class="SearchBar_Category">

< p > HTML (我有锚标签围绕每个菜单项,但我不能提交他们作为一个新用户)

<div id="ROS_SearchSermons" class="SearchBar_Cateogry bold">Sermons</div>|
<div id="ROS_SearchIllustrations" class="SearchBar_Cateogry">Illustrations</div>|
<div id="ROS_SearchVideos" class="SearchBar_Cateogry">Videos</div>|
<div id="ROS_SearchPowerPoints" class="SearchBar_Cateogry">PowerPoints</div>|
<div id="ROS_SearchScripture" class="SearchBar_Cateogry">Scripture</div>|

CSS:

#ROS_SearchSermons { width: 75px; }
#ROS_SearchIllustrations { width: 90px; }
#ROS_SearchVideos { width: 55px; }
#ROS_SearchPowerPoints { width: 90px; }
#ROS_SearchScripture { width: 70px; }


.SearchBar_Cateogry
{
display: inline-block;
text-align:center;
}

我遇到过和你类似的问题。我想让我的链接变得粗体时,你悬停在他们,但不仅在菜单,而且在文本。正如你可以猜到的,这将是一个真正的苦差事,找出所有不同的宽度。解决方法很简单:

创建一个框,其中包含粗体的链接文本,但颜色像你的背景,但你的真实链接在上面。下面是我个人主页上的一个例子:

CSS:

.hypo { font-weight: bold; color: #FFFFE0; position: static; z-index: 0; }
.hyper { position: absolute; z-index: 1; }

当然,你需要将#FFFFE0替换为页面的背景色。z指数似乎没有必要,但我还是把它们(作为“猜想”;元素将出现在“超”之后;HTML-Code中的元素)。现在,在你的页面上放一个链接,包括以下内容:

HTML:

You can find foo <a href="http://bar.com" class="hyper">here</a><span class="hypo">here</span>

第二个“here”;将是无形的,隐藏在你下面的链接。因为这是一个静态的盒子 你的粗体链接文本,你的其余文本将不会再移动,因为它已经移动之前,你悬停在链接

如果不反对使用Javascript,可以在页面显示后设置适当的宽度。以下是我的做法(使用Prototype):

$$('ul.nav li').each(this.setProperWidth);


setProperWidth: function(li)
{
// Prototype's getWidth() includes padding, so we
// have to subtract that when we set the width.
var paddingLeft = li.getStyle('padding-left'),
paddingRight = li.getStyle('padding-right');


// Cut out the 'px' at the end of each padding
paddingLeft = paddingLeft.substring(0,paddingLeft.length-2);
paddingRight = paddingRight.substring(0,paddingRight.length-2);


// Make the li bold, set the width, then unbold it
li.setStyle({ fontWeight: 'bold' });
li.setStyle({ width: (li.getWidth() - paddingLeft - paddingRight) + 'px'});
li.setStyle({ fontWeight: 'normal', textAlign: 'center' });
}

jquery中的一个行:

$('ul.nav li a').each(function(){
$(this).parent().width($(this).width() + 4);
});

< em >编辑: 虽然这可以带来解决方案,但应该提到的是,它不能与原始文章中的代码一起工作。"display:inline"必须替换为浮动参数,以便宽度设置有效,水平菜单可以正常工作

你可以使用"margin"属性:

li a {
margin: 0px 5px 0px 5px;
}


li a:hover {
margin: 0;
font-weight: bold;
}
只要确保左右边距足够大,以便额外的空间可以包含粗体文本。对于较长的单词,可以选择不同的页边距。

.这只是另一种变通办法,但对我来说很有用

你可以用

<ul>
<li><a href="#">Some text<span><br />Some text</span></a></li>
</ul>

然后在CSS中,将span content设置为粗体,用可见性隐藏它:hidden,这样它就能保持它的维度。然后,您可以调整以下元素的边距,使其适当适合。

我不确定这种方法是否是SEO友好的。

折衷的解决方案是使用文本阴影来伪装粗体,例如:

文字阴影:0 0 0.01px黑色;

为了更好地进行比较,我创建了以下示例:

a, li {
color: black;
text-decoration: none;
font: 18px sans-serif;
letter-spacing: 0.03em;
}
li {
display: inline-block;
margin-right: 20px;
color: gray;
font-size: 0.7em;
}
.bold-x1 a.hover:hover,
.bold-x1 a:not(.hover) {
text-shadow: 0 0 .01px black;
}
.bold-x2 a.hover:hover,
.bold-x2 a:not(.hover){
text-shadow: 0 0 .01px black, 0 0 .01px black;
}
.bold-x3 a.hover:hover,
.bold-x3 a:not(.hover){
text-shadow: 0 0 .01px black, 0 0 .01px black, 0 0 .01px black;
}
.bold-native a.hover:hover,
.bold-native a:not(.hover){
font-weight: bold;
}


.bold-native li:nth-child(4),
.bold-native li:nth-child(5){
margin-left: -6px;
letter-spacing: 0.01em;
}
<ul class="bold-x1">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">About</a></li>
<li>Bold (text-shadow x1)</li>
</ul>
<ul class="bold-x2">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">About</a></li>
<li>Extra Bold (text-shadow x2)</li>
</ul>
<ul class="bold-native">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">About</a></li>
<li>Bold (native)</li>
</ul>
<ul class="bold-x3">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">About</a></li>
<li>Black (text-shadow x3)</li>
</ul>

blur-radius的低值传递给text-shadow将使模糊效果不那么明显。

一般来说,你重复text-shadow的次数越多,你的文本就会变得越粗体,但同时也会失去字母的原始形状。

我应该警告你,将blur-radius设置为分数并不会在所有浏览器中呈现相同的效果!例如,Safari需要更大的值来呈现它,就像Chrome一样。

我刚刚用“阴影”解决了这个问题。

nav.mainMenu ul li > a:hover, nav.mainMenu ul li.active > a {
text-shadow:0 0 1px white;
}

不需要重复阴影三次(结果对我来说是一样的)。

预设宽度通过使用一个不可见的伪元素,它具有与父悬停样式相同的内容和样式。使用数据属性(如title)作为内容的源。

li {
display: inline-block;
font-size: 0;
}


li a {
display:inline-block;
text-align:center;
font: normal 16px Arial;
text-transform: uppercase;
}


a:hover {
font-weight:bold;
}


/* SOLUTION */
/* The pseudo element has the same content and hover style, so it pre-sets the width of the element and visibility: hidden hides the pseudo element from actual view. */
a::before {
display: block;
content: attr(title);
font-weight: bold;
height: 0;
overflow: hidden;
visibility: hidden;
}
<ul>
<li><a href="#" title="height">height</a></li>
<li><a href="#" title="icon">icon</a></li>
<li><a href="#" title="left">left</a></li>
<li><a href="#" title="letter-spacing">letter-spacing</a></li>
<li><a href="#" title="line-height">line-height</a></li>
</ul>

如果粗体文本比常规文本宽,您也可以尝试负边距。(不总是) 所以我们的想法是使用类来样式:hover状态。

jQuery:

 $(".nav-main .navbar-collapse > ul > li > a").hover(function() {
var originalWidth = $(this).outerWidth();


$(this).parent().addClass("hover");
$(this).css({
"margin-left": -(($(this).outerWidth() - originalWidth) / 2),
"margin-right": -(($(this).outerWidth() - originalWidth) / 2)
});
},
function() {
$(this).removeAttr("style");
$(this).parent().removeClass("hover");
});

CSS:

ul > li > a {
font-style: normal;
}


ul > li > a.hover {
font-style: bold;
}

希望我能帮上忙!

另一个想法是使用letter-spacing

li, a { display: inline-block; }
a {
font-size: 14px;
padding-left: 10px;
padding-right: 10px;
letter-spacing: 0.235px
}


a:hover, a:focus {
font-weight: bold;
letter-spacing: 0
}
<ul>
<li><a href="#">item 1</a></li>
<li><a href="#">item 2</a></li>
<li><a href="#">item 3</a></li>
</ul>

这是我喜欢的解决办法。它需要一些JS,但你不需要你的标题属性完全相同,你的CSS可以保持非常简单。

.
$('ul a').each(function() {
$(this).css({
'padding-left': 0,
'padding-right': 0,
'width': $(this).outerWidth()
});
});
li, a { display: inline-block; }
a {
padding-left: 10px;
padding-right: 10px;
text-align: center; /* optional, smoother */
}
a:hover { font-weight: bold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><a href="#">item 1</a></li>
<li><a href="#">item 2</a></li>
<li><a href="#">item 3</a></li>
</ul>

这个呢?一个javascript - CSS3免费的解决方案。

http://jsfiddle.net/u1aks77x/1/

ul{}
li{float:left; list-style-type:none; }
a{position:relative; padding-right: 10px; text-decoration:none;}
a > .l1{}
a:hover > .l1{visibility:hidden;}
a:hover > .l2{display:inline;}
a > .l2{position: absolute; left:0; font-weight:bold; display:none;}


<ul>
<li><a href="/" title="Home"><span class="l1">Home</span><span class="l2">Home</span></a></li>
<li><a href="/" title="Contact"><span class="l1">Contact</span><span class="l2">Contact</span></a></li>
<li><a href="/" title="Sitemap"><span class="l1">Sitemap</span><span class="l2">Sitemap</span></a></li>
</ul>

CSS3解决方案-实验性

(假大胆)

想分享一个不同的解决方案,没有人在这里建议。有一个名为text-stroke的属性,它会很方便。

.
p span:hover {
-webkit-text-stroke: 1px black;
}
<p>Some stuff, <span>hover this,</span> it's cool</p>

Here, I am targeting the text inside of the span tag and we stroke it by a pixel with black which will simulate bold style for that particular text.

Note that this property is not widely supported, as of now (while writing this answer), only Chrome and Firefox seems to support this. For more information on browser support for text-stroke, you can refer to CanIUse.


Just for sharing some extra stuff, you can use -webkit-text-stroke-width: 1px; if you are not looking to set a color for your stroke.

我喜欢用文本阴影代替。特别是因为您可以使用过渡来动画文本阴影。

你真正需要的是:

a {
transition: text-shadow 1s;
}
a:hover {
text-shadow: 1px 0 black;
}
对于一个完整的导航,检查这个jsfiddle: https://jsfiddle.net/831r3yrb/ < / p >

浏览器支持和文本阴影的更多信息: http://www.w3schools.com/cssref/css3_pr_text-shadow.asp < / p >

不是很优雅的解决方案,但“有效”:

a
{
color: #fff;
}


a:hover
{
text-shadow: -1px 0 #fff, 0 1px #fff, 1px 0 #fff, 0 -1px #fff;
}

我结合了上面的一些技术来提供一些东西,如果关闭js,它不会完全糟糕,如果使用jQuery,效果会更好。现在浏览器对亚像素字母间距的支持正在改进,使用它真的很好。

jQuery(document).ready(function($) {
$('.nav a').each(function(){
$(this).clone().addClass('hoverclone').fadeTo(0,0).insertAfter($(this));
var regular = $(this);
var hoverclone = $(this).next('.hoverclone');
regular.parent().not('.current_page_item').hover(function(){
regular.filter(':not(:animated)').fadeTo(200,0);
hoverclone.fadeTo(150,1);
}, function(){
regular.fadeTo(150,1);
hoverclone.filter(':not(:animated)').fadeTo(250,0);
});
});
});
ul {
font:normal 20px Arial;
text-align: center;
}
li, a {
display:inline-block;
text-align:center;
}
a {
padding:4px 8px;
text-decoration:none;
color: #555;
}


.nav a {
letter-spacing: 0.53px; /* adjust this value per font */
}
.nav .current_page_item a,
.nav a:hover {
font-weight: bold;
letter-spacing: 0px;
}
.nav li {
position: relative;
}
.nav a.hoverclone {
position: absolute;
top:0;
left: 0;
white-space: nowrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="nav">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li class="current_page_item"><a  href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
<li><a href="#">Item 5</a></li>
</ul>

ul {
list-style-marker: none;
padding: 0;
}


li {
display: inline-block;
}


li + li {
margin-left: 1em;
}


a {
display: block;
position: relative;
text-align: center;
}


a:before, a:after {
content: attr(aria-label);
text-decoration: inherit;
}


a:before {
font-weight: bold;
visibility: hidden;
}


a:after {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}


a:hover:before {
visibility: visible;
}


a:hover:after {
display: none;
}
<ul>
<li>
<a href="" aria-label="Long-long-long"></a>
</li><li>
<a href="" aria-label="or"></a>
</li><li>
<a href="" aria-label="Short"></a>
</li><li>
<a href="" aria-label="Links"></a>
</li><li>
<a href="" aria-label="Here"></a>
</li>
</ul>

< p >试试这个:

.nav {
font-family: monospace;
}

我使用文本阴影解决方案,其他一些提到这里:

text-shadow: 0 0 0.01px;

不同之处在于我没有指定阴影颜色,所以这个解决方案适用于所有字体颜色。

另一种方法是通过文本阴影“模拟”粗体文本。这有一个额外的好处(/malus,取决于你的情况),也适用于字体图标。

   nav li a:hover {
text-decoration: none;
text-shadow: 0 0 1px; /* "bold" */
}

有点俗气,尽管它可以避免重复文本(如果文本很多,这很有用,就像我的情况一样)。

最好像这样使用之前:代替后::

.breadcrumb {
margin: 0;
padding: 0;
list-style: none;
overflow: hidden;
}


.breadcrumb li,
.breadcrumb li a {
display: inline-block;
}


.breadcrumb li:not(:last-child)::after {
content: '>'; /* or anything else */
display: inline-block;
}


.breadcrumb a:hover {
font-weight: bold;
}


.breadcrumb a::before {
display: block;
content: attr(data-label);
font-weight: bold;
height: 0;
overflow: hidden;
visibility: hidden;
}
<ul class="breadcrumb">
<li><a data-label="one" href="https://www.google.fr/" target="_blank">one</a></li>
<li><a data-label="two" href="https://duckduckgo.com/" target="_blank">two</a></li>
<li><a data-label="three" href="#">three</a></li>
</ul>

更多详细信息:https://jsfiddle.net/r25foavy/

我固定菜单时,悬停粗体成功。它支持响应式,这是我的代码:

(function ($) {
'use strict';


$(document).ready(function () {
customWidthMenu();
});
$(window).resize(function () {
customWidthMenu();
});
function customWidthMenu() {
$('ul.nav li a').each(function() {
$(this).removeAttr('style');
var this = $(this);
var width = this.innerWidth();
this.css({'width': width + 12});
});
}})(jQuery);

如果你不想预设列表项的宽度,一个真正好的替代方法是尝试在列表项中使用uniwidth字体。

与单行字体不同,它们仍然是比例字体——但它们在不同的字体粗细上占用相同的大小不需要CSS, JS,或花哨的hack来保持大小不变。它被烘焙到字体中。

我认为这是一个很好的解决这个常见问题的方法。

下面是来自这篇精彩的文章的一个比较比例字体IBM Plex Sans和uniwidth Recursive的例子。

 compare proportional to uniwidth font

注意在比例字体(IBM Plex Sans)中,列表项如何随着粗体字体的大小变化而变化。使用单宽字体递归,项目在悬停时变成粗体,但不要改变尺寸

你可以尝试的免费单宽字体有:

还有许多非免费的选项链接到前面提到的文章中。

使用letter-spacingtext-shadow:

a {
letter-spacing: .1em;
}


a:hover {
text-shadow: 0 0 .9px #color, 0 0 .9px #color, 0 0 .9px #color;
}

我用几行javascript解决了这个问题。

$('a.menu_item').each(function() {
let width = $(this).width();
$(this).css('width',width + 'px');
});

在这里看到了很多很棒但很复杂的答案。真的不需要重置宽度,添加隐藏元素,为不同的布局声明重做元素等等。最简单的解决方案是通过将hover声明中的字体大小调整为略小的大小来考虑粗体文本的大小增加。例如font-size: .985em来自正常的1em声明,它允许文本在悬浮时加粗,但也保持原始大小外观。

我可以给你两种建议

第一个选项:是将每个列表项的宽度设置为

这里有一个简单的例子

<ul>
<li><a href="#">First Item</a></li>
<li><a href="#">Second Item</a></li>
<li><a href="#">Third Item</a></li>
<li><a href="#">Fourth Item</a></li>
</ul>


li {
list-style-type: none;
display: inline-block;
width: 24%;
}


a {
text-decoration: none;
color: #333;
font-size: 1.4em;
background: #A5C77F;
display: block;
padding: 10px 15px;
margin: 10px 0;
border-right: 1px solid whitesmoke;
transition: font-weight .3s;
}


a:hover {
font-weight: bold;
}

第二种选择:是在活动元素上使用文本阴影

text-shadow: 0 0 .65px #333, 0 0 .65px #333;

但我建议使用第一个选项,即为每个元素指定一个百分比的宽度,因为文本阴影并不总是在移动浏览器中工作