我使用 HTML 列表和 CSS 创建了一个水平菜单。除非您将鼠标悬停在链接上,否则一切正常。你看,我为链接创建了一个粗体悬停状态,现在菜单链接由于粗体大小的不同而发生了变化。
我遇到与 this SitePoint post 相同的问题。但是,该帖子没有适当的解决方案。我到处寻找解决方案,但找不到。当然,我不可能是唯一一个尝试这样做的人。
有没有人有任何想法?
PS:我不知道菜单项中文本的宽度,所以我不能只设置 li 项的宽度。
.nav {边距:0;填充:0; } .nav li { 列表样式:无;显示:内联;左边框:#ffffff 1px 实心; } .nav li a:link, .nav li a:visited { text-decoration: none;颜色:#000;左边距:8px;右边距:5px; } .nav li a:hover{ text-decoration: none;字体粗细:粗体; } .nav li.first { 边框:无; }
预设宽度,使用与父悬停样式具有相同内容和样式的不可见伪元素。使用数据属性(如 title
)作为内容的来源。
li { display: inline-block;字体大小:0; } li a { display:inline-block;文本对齐:居中;字体:正常 16px Arial;文本转换:大写; } a:hover { 字体粗体:粗体; } /* SOLUTION */ /* 伪元素具有相同的内容和悬停样式,因此它预先设置了元素的宽度和可见性:hidden 从实际视图中隐藏伪元素。 */ a::before { display: block;内容:attr(标题);字体粗细:粗体;高度:0;溢出:隐藏;可见性:隐藏; }
一个妥协的解决方案是用文本阴影伪造粗体,例如:
文字阴影:0 0 0.01px 黑色;
为了更好地比较,我创建了这些示例:
a, li { 颜色:黑色;文字装饰:无;字体:18px 无衬线;字母间距:0.03em; } li { 显示:内联块;右边距:20px;颜色:灰色;字体大小: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){ 文本阴影:0 0 .01px 黑色,0 0 .01px 黑色; } .bold-x3 a.hover:hover, .bold-x3 a:not(.hover){ 文字阴影:0 0 .01px 黑色,0 0 .01px 黑色,0 0 .01px 黑色; } .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;字母间距:0.01em; }
另一个想法是使用 letter-spacing
li, a { display: inline-block; } a { 字体大小:14px;左边距:10px; padding-right: 10px;字母间距:0.235px } a:hover, a:focus { 字体粗细:粗体;字母间距:0 }
如果你不能设置宽度,那么这意味着宽度会随着文本变粗而改变。没有办法避免这种情况,除非通过修改每个状态的填充/边距等妥协。
jquery中的一行:
$('ul.nav li a').each(function(){
$(this).parent().width($(this).width() + 4);
});
编辑:虽然这可以带来解决方案,但应该提到它不能与原始帖子中的代码一起使用。 "display:inline" 必须替换为浮动参数才能使宽度设置生效并且水平菜单按预期工作。
a
替换 ul.nav li a
有效吗?
CSS3 解决方案 - 实验性
想分享一种不同的解决方案,这里没有人建议。有一个名为 text-stroke
的属性会很方便。
p跨度:悬停{-webkit-text-stroke:1px黑色; }
一些东西,悬停这个,很酷
在这里,我以 span
标记内的文本为目标,我们用一个像素用 black
对其进行描边,这将模拟该特定文本的 bold
样式。
请注意,此属性并未得到广泛支持,截至目前(在编写此答案时),似乎只有 Chrome 和 Firefox 支持此属性。有关浏览器对 text-stroke
的支持的更多信息,您可以参考 CanIUse。
只是为了分享一些额外的东西,如果您不想为您的笔划设置 color
,您可以使用 -webkit-text-stroke-width: 1px;
。
你可以使用类似的东西
<ul>
<li><a href="#">Some text<span><br />Some text</span></a></li>
</ul>
然后在你的css中将span内容设置为粗体并用可见性隐藏它:隐藏,这样它就可以保持它的尺寸。然后您可以调整以下元素的边距以使其适合。
我不确定这种方法是否对 SEO 友好。
我刚刚用“影子”解决方案解决了这个问题。这似乎是最简单有效的。
nav.mainMenu ul li > a:hover, nav.mainMenu ul li.active > a {
text-shadow:0 0 1px white;
}
不需要重复阴影三次(结果对我来说是一样的)。
我遇到了和你类似的问题。当您将鼠标悬停在它们上时,我希望我的链接变得粗体,但不仅在菜单中,而且在文本中。正如您猜测的那样,弄清楚所有不同的宽度将是一件真正的苦差事。解决方案非常简单:
创建一个框,其中包含粗体的链接文本,但颜色与您的背景相似,但在其上方是您的真实链接。这是我页面中的一个示例:
CSS:
.hypo { font-weight: bold; color: #FFFFE0; position: static; z-index: 0; }
.hyper { position: absolute; z-index: 1; }
当然,您需要将#FFFFE0 替换为页面的背景颜色。 z 索引似乎不是必需的,但我还是把它们放在了(因为“hypo”元素将出现在 HTML 代码中的“hyper”元素之后)。现在,要在您的页面上放置一个链接,请包括以下内容:
HTML:
You can find foo <a href="http://bar.com" class="hyper">here</a><span class="hypo">here</span>
第二个“此处”将不可见并隐藏在您的链接下方。由于这是一个带有粗体链接文本的静态框,因此您的其余文本将不再移动,因为在您将鼠标悬停在链接上之前它已经移动了。
希望我能提供帮助:)。
太长
如果您不想预设列表项的宽度,一个非常好的选择是尝试在列表项中使用等宽字体。
与等宽字体不同,它们仍然是成比例的字体——但它们在不同的字体粗细中占据相同的大小。不需要 CSS、JS 或花哨的技巧来保持大小不变。它直接融入字体。
我认为这是解决这个常见问题的一个非常优雅的解决方案。
这是来自 this excellent article 的一个示例,比较了比例字体 IBM Plex Sans 和 uniwidth Recursive。
https://miro.medium.com/max/2400/1*eUu31P1t6Ez6xwD56BQJaw.gif
注意在比例字体 (IBM Plex Sans) 中,列表项如何随着粗体字体大小的变化而变化。使用 uniwidth 字体 Recursive,项目在悬停时变为粗体,但不改变大小。
您可以尝试的免费单角字体有:
递归的
PT 根用户界面
戈洛斯用户界面
看台
也有许多通过上述文章链接到的非免费选项。
我喜欢使用 text-shadow 代替。特别是因为您可以使用过渡来为文本阴影设置动画。
您真正需要的是:
a {
transition: text-shadow 1s;
}
a:hover {
text-shadow: 1px 0 black;
}
如需完整导航,请查看此 jsfiddle:https://jsfiddle.net/831r3yrb/
浏览器支持和有关文本阴影的更多信息:http://www.w3schools.com/cssref/css3_pr_text-shadow.asp
我使用 text-shadow 解决方案,就像这里提到的其他人一样:
text-shadow: 0 0 0.01px;
不同的是我没有指定阴影颜色,所以这个解决方案对所有字体颜色都是通用的。
您可以使用“margin”属性:
li a {
margin: 0px 5px 0px 5px;
}
li a:hover {
margin: 0;
font-weight: bold;
}
只需确保左右边距足够大,以便额外的空间可以包含粗体文本。对于长词,您可以选择不同的边距。这只是另一种解决方法,但为我完成了这项工作。
另一种方法是通过文本阴影“模拟”粗体文本。这有一个好处(/malus,取决于你的情况)也可以在字体图标上工作。
nav li a:hover {
text-decoration: none;
text-shadow: 0 0 1px; /* "bold" */
}
Kinda hacky,虽然它可以让你免于复制文本(如果它很多,这很有用,就像我的情况一样)。
我建议不要在悬停时切换字体(°)。在这种情况下,它只是菜单项移动了一点,但我已经看到了整个段落被重新格式化的情况,因为加宽会导致额外的自动换行。当您唯一要做的就是移动光标时,您不希望看到这种情况发生;如果您不执行任何操作,则页面布局不应更改。
在正常和斜体之间切换时也会发生这种转变。如果文本下方有空间,我会尝试更改颜色或切换下划线。 (下划线应远离底部边框)
如果我为我的表单设计课使用切换字体,我会被嘘的:-)
(°) 字体一词经常被误用。 “Verdana”是一种字体,“Verdana normal”和“Verdana bold”是同一种字体的不同字体。
不是很优雅的解决方案,但“有效”:
a
{
color: #fff;
}
a:hover
{
text-shadow: -1px 0 #fff, 0 1px #fff, 1px 0 #fff, 0 -1px #fff;
}
将 letter-spacing
与 text-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');
});
在这里看到很多很棒但非常复杂的答案。真的不需要重置宽度,添加隐藏元素,为不同的布局声明重新设计元素等。最简单的解决方案是通过将悬停声明中的字体大小调整为稍微增加粗体文本来解决大小的增加较小的尺寸。例如 font-size: .985em 来自正常的 1em 声明,它允许文本在悬停时变为粗体,但也保持原始大小外观。
这是我喜欢的解决方案。它需要一点 JS,但你不需要你的 title 属性完全相同,你的 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;文本对齐:居中; /* 可选,更平滑 */ } a:hover { font-weight: bold; }
那这个呢?一个 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>
我结合了上面的一堆技术来提供一些在关闭 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;文本对齐:居中; } li, 一个 { display:inline-block;文本对齐:居中; } a { 填充:4px 8px;文字装饰:无;颜色:#555; } .nav a { 字母间距:0.53px; /* 调整每个字体的这个值 */ } .nav .current_page_item a, .nav a:hover { font-weight: bold;字母间距:0px; } .nav li { 位置:相对; } .nav a.hoverclone { 位置:绝对;顶部:0;左:0;空白:nowrap; }
最好使用 a::before 而不是 a::after 像这样:
.breadcrumb { 边距:0;填充:0;列表样式:无;溢出:隐藏; } .breadcrumb li, .breadcrumb li a { display: inline-block; } .breadcrumb li:not(:last-child)::after { content: '>'; /* 或其他任何东西 */ display: inline-block; } .breadcrumb a:hover { 字体粗细:粗体; } .breadcrumb a::before { 显示:块;内容:attr(数据标签);字体粗细:粗体;高度:0;溢出:隐藏;可见性:隐藏; }
更多详情:https://jsfiddle.net/r25foavy/
a::before
比 a::after
更好?这似乎是您答案的关键部分,但在这种情况下,为什么一个比另一个更可取并不明显。
当悬停大胆成功时,我修复了菜单。它支持响应式,这是我的代码:
(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);
我可以建议你两种变体
第一个选项:您是否将每个列表项的宽度设置为 %
这是一个简单的例子
<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;
但我建议使用第一个选项,即将每个元素的宽度指定为百分比,因为 text-shadow 在移动浏览器中并不总是有效
如果您不反对使用 Javascript,则可以在页面显示后设置适当的宽度。这是我的做法(使用原型):
$$('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' });
}
当有一个简单的问题解决方案时,有人告诉你不要那样做,我真的无法忍受。我不确定 li 元素,但我刚刚解决了同样的问题。我有一个由 div 标签组成的菜单。
只需将 div 标签设置为“display: inline-block”。内联,因此它们彼此相邻并阻挡您可以设置宽度。只需将宽度设置为足以容纳粗体文本并对齐文本中心即可。
(注意:它似乎正在剥离我的 html [下面],但每个菜单项都有一个 div 标记,其中包含相应的 ID 和类名 SearchBar_Cateogory。即:<div id="ROS_SearchSermons" class="SearchBar_Category">
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;
}
尝试这个:
.nav {
font-family: monospace;
}
如果粗体文本比常规文本更宽,您也可以尝试负边距。 (并非总是如此)所以想法是使用类来设置 :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;
}
我希望我能帮上忙!
margin-top: -1px
添加到:after
以避免创建 1 像素高度的空间时效果会更好。:
vs::
"每个支持双冒号::
CSS3 语法的浏览器也只支持:
语法,但 IE 8 只支持单冒号,所以现在建议只使用最佳浏览器支持的单冒号。” css-tricks.com/almanac/selectors/a/after-and-beforeUL
或a::after
,换句话说 - 重置所有填充/边距/行高/字体大小等。