悬停时加粗时内联元素会发生变化
我使用 HTML 列表和 CSS 创建了一个水平菜单。 一切正常,除非您将鼠标悬停在链接上。 您会看到,我为链接创建了粗体悬停状态,现在菜单链接由于粗体尺寸差异而发生变化。
我遇到了与 此 SitePoint 帖子 相同的问题。 不过该帖子并没有给出正确的解决方案。 我到处寻找解决方案,但找不到。 当然,我不是唯一一个尝试这样做的人。
有人有什么想法吗?
PS:我不知道菜单项中文本的宽度,所以我不能只设置 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>
I created a horizontal menu using a HTML lists and CSS. Everything works as it should except when you hover over the links. You see, I created a bold hover state for the links, and now the menu links shift because of the bold size difference.
I encounter the same problem as this SitePoint post. However, the post does not have proper solution. I've searched everywhere for a solution and can't find one.
Surely I can't be the only one trying to do this.
Does anyone have any ideas?
P.S: I don't know the width of the text in menu items so I cannot just set the width of the li items.
.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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
通过使用与父悬停样式具有相同内容和样式的不可见伪元素来预设宽度。 使用数据属性(例如
title
)作为内容源。Pre-set the width by using an invisible pseudo-element which has the same content and styling as the parent hover style. Use a data attribute, like
title
, as the source for content.一个折衷的解决方案是用文本阴影伪造粗体,例如:
为了更好的比较,我创建了这些示例:
传递给
text-shadow
的blur-radius
值非常低,将使模糊效果不那么明显。一般来说,重复
text-shadow
的次数越多,文本就会变得越粗,但同时会失去字母的原始形状。我应该警告您,将
blur-radius
设置为分数不会在所有浏览器中呈现相同的效果! 例如,Safari 需要更大的值来呈现它,就像 Chrome 一样。A compromised solution is to fake bold with text-shadow, e.g:
For better comparison I created these examples:
Passing to
text-shadow
really low value forblur-radius
will make the blurring effect not so apparent.In general the more your repeat
text-shadow
the bolder your text will get but in the same time loosing original shape of the letters.I should warn you that setting the
blur-radius
to fractions is not going to render the same in all browsers! Safari for example need bigger values to render it the same way Chrome will do.另一个想法是使用
letter-spacing
Another idea is using
letter-spacing
如果您无法设置宽度,则意味着宽度将随着文本变粗而改变。 没有办法避免这种情况,除非采取妥协措施,例如修改每个状态的填充/边距。
If you cannot set the width, then that means the width will change as the text gets bold. There is no way to avoid this, except by compromises such as modifying the padding/margins for each state.
CSS3 解决方案 - 实验
(Fake boldness)
思想分享一种这里没有人建议的不同解决方案。 有一个名为
text-lines
的属性对此非常方便。在这里,我的目标是
span
标签内的文本,并使用black
对其进行像素描边,这将模拟该特定的bold
样式文本。请注意,此属性并未得到广泛支持,截至目前(在撰写此答案时),似乎只有 Chrome 和 Firefox 支持此属性。 有关浏览器对
text-lines
的支持的更多信息,可以参考 CanIUse< /a>.只是为了共享一些额外的内容,如果您不想为笔划设置
颜色
,则可以使用-webkit-text-lines-width: 1px;
。CSS3 Solution - Experimental
(Fake boldness)
Thought to share a different solution which no one suggested here. There's a property called
text-stroke
which will be handy for this.Here, I am targeting the text inside of the
span
tag and we stroke it by a pixel withblack
which will simulatebold
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 acolor
for your stroke.jquery 中的一行:
编辑:
虽然这可以带来解决方案,但应该提到它不能与原始帖子中的代码结合使用。 “display:inline”必须替换为浮动参数,宽度设置才能有效,并且水平菜单才能按预期工作。
One line in jquery:
edit:
While this can bring about the solution, one should mention that it does not work in conjunction with the code in the original post. "display:inline" has to be replaced with floating-parameters for a width-setting to be effective and that horizontal menu to work as intended.
如果您不想预设列表项的宽度,一个非常好的替代方法是尝试在列表项中使用 uniwidth 字体。
与等宽字体不同,它们仍然是比例字体 - 但它们在不同的字体粗细中占据相同的大小。 不需要 CSS、JS 或花哨的技巧来保持大小不变。它直接融入到字体中。
我认为这是解决这个常见问题的一个非常优雅的解决方案。
以下是这篇优秀文章中的示例,将比例字体 IBM Plex Sans 与单宽递归。
注意在比例字体 (IBM Plex Sans) 中,列表项如何随着粗体字体大小的改变而变化。 使用单宽字体 Recursive,项目在悬停时会变为粗体,但不更改大小。
您可以尝试的免费单宽字体有:
还有许多链接的非免费选项通过上述文章。
If you don't want to preset the width of the list items, a really good alternative would be to try using a uniwidth font in your list items.
Unlike a monospace font, they're still proportional typefaces -- but they occupy the same size across different font weights. No CSS, JS, or fancy hacks are required to keep the size constant. It's baked right into the typeface.
I think it's a really elegant solution to this common problem.
Here's an example from this excellent article comparing the proportional font IBM Plex Sans to the uniwidth Recursive.
Notice how in the proportional font (IBM Plex Sans), the list items shift as they change size in the bold typeface. With the uniwidth font Recursive, the items become bold on hover but don't change size.
Free uniwidth fonts you can try are:
There are also many non-free options linked to via the aforementioned article.
您可以使用类似的东西
,然后在您的CSS中只需将跨度内容设置为粗体并使用visibility:hidden隐藏它,以便它保持其尺寸。 然后您可以调整以下元素的边距以使其正确适合。
我不确定这种方法是否适合 SEO。
You could use somehting like
and then in your css just set the span content bold and hide it with visibility: hidden, so that it keeps its dimensions. Then you can adjust margins of the following elements to make it fit properly.
I am not sure if this approach is SEO friendly though.
我刚刚用“影子”解决方案解决了这个问题。
这似乎是最简单有效的。
不需要重复阴影三次(结果对我来说是一样的)。
I just solved the problem with the "shadow" solution.
It seems the most simple and effective.
No need to repeat the shadow three times (result was the same for me).
我使用文本阴影解决方案,就像这里提到的其他一些解决方案一样:
不同之处在于我没有指定阴影颜色,因此该解决方案对于所有字体颜色都是通用的。
I use text-shadow solution as some others mentioned here:
the difference is that I do not specify shadow color, so this solution is universal for all font colors.
我遇到了与你类似的问题。 我希望当您将鼠标悬停在链接上时,它们会变得粗体,不仅在菜单中,而且在文本中。 正如您所猜测的那样,计算所有不同的宽度将是一项真正的苦差事。 解决方案非常简单:
创建一个框,其中包含粗体的链接文本,但颜色与您的背景相同,但其上方是真正的链接。 这是我页面中的一个示例:
CSS:
当然,您需要将 #FFFFE0 替换为页面的背景颜色。 z 索引似乎不是必需的,但我还是把它们放了(因为“hypo”元素将出现在 HTML 代码中的“hyper”元素之后)。 现在,要将链接放在页面上,请包含以下内容:
HTML:
第二个“此处”将不可见并隐藏在链接下方。 因为这是一个静态框
如果您的链接文本以粗体显示,则文本的其余部分将不再移动,因为在您将鼠标悬停在链接上之前它已经发生了移动。
I had a problem similar to yours. I wanted my links to get bold when you hover over them but not only in the menu but also in the text. As you cen guess it would be a real chore figuring out all the different widths. The solution is pretty simple:
Create a box that contains the link text in bold but coloured like your background and but your real link above it. Here's an example from my page:
CSS:
Of course you need to replace #FFFFE0 by the background colour of your page. The z-indices don't seem to be necessary but I put them anyway (as the "hypo" element will occur after the "hyper" element in the HTML-Code). Now, to put a link on your page, include the following:
HTML:
The second "here" will be invisible and hidden below your link. As this is a static box with
your link text in bold, the rest of your text won't shift any longer as it is already shifted before you hover over the link.
我喜欢用文字阴影代替。 特别是因为您可以使用过渡来为文本阴影添加动画效果。
您真正需要的是:
要获得完整的导航,请查看此 jsfiddle:
https://jsfiddle.net/831r3yrb/
浏览器支持和有关文本阴影的更多信息:
http://www.w3schools.com/cssref/css3_pr_text-shadow.asp
I like to use text-shadow instead. Especially because you can use transitions to animate text-shadow.
All you really need is:
For a complete navigation check out this jsfiddle:
https://jsfiddle.net/831r3yrb/
Browser support and more info on text-shadow:
http://www.w3schools.com/cssref/css3_pr_text-shadow.asp
另一种方法是通过文本阴影“模拟”粗体文本。 这有一个好处(/malus,取决于你的情况)也可以用于字体图标。
有点老套,尽管它可以让您免于重复文本(如果文本很多,这很有用,就像我的情况一样)。
An alternative approach would be to "emulate" bold text via text-shadow. This has the bonus (/malus, depending on your case) to work also on font icons.
Kinda hacky, although it saves you from duplicating text (which is useful if it is a lot, as it was in my case).
您可以使用“margin”属性:
只需确保左右边距足够大,以便额外的空间可以包含粗体文本。 对于长单词,您可以选择不同的边距。
这只是另一种解决方法,但为我完成了这项工作。
You can work with the "margin" property:
Just make sure that the left and right margin are big enough so the extra space can contain the bold text. For long words, you might choose different margins.
It's just another workaround but doing the job for me.
在这里看到很多很棒但非常复杂的答案。 实际上不需要重置宽度、添加隐藏元素、为不同的布局声明重新设计元素等。最简单的解决方案就是通过将悬停声明中的字体大小稍微调整一下来解决粗体文本大小的增加。尺寸较小。 例如,正常 1em 声明中的 font-size: .985em 允许文本在悬停时加粗,但也保持原始大小的外观。
Seeing a lot of great but very involved answers here. There's really not a need for resetting widths, adding hidden elements, reworking elements for different layout declarations, etc. The simplest solution is just to account for the increase in size from the bold text by adjusting the font size in the hover declaration to a slightly smaller size. Like for example font-size: .985em from the normal 1em declaration, which allows the text to bold when hovered but also maintain the original size appearance.
我建议不要在悬停时切换字体(°)。 在这种情况下,只是菜单项移动了一点,但我见过整个段落重新格式化的情况,因为加宽会导致额外的自动换行。 当您所做的唯一事情就是移动光标时,您不希望看到这种情况发生; 如果您不执行任何操作,则页面布局不应更改。
在正常和斜体之间切换时也会发生这种转变。 如果文本下方有空间,我会尝试更改颜色或切换下划线。 (下划线应该从底部边框保持清晰)
如果我在表单设计课程中使用切换字体,我会被嘘:-)
(°) 单词字体经常被误用。 “Verdana”是一种字体,“Verdana 普通”和“Verdana 粗体”是同一字体的不同字体。
I would advice against switching fonts(°) on hover. In this case it's just the menu items moving a bit, but I've seen cases where the complete paragraph gets reformatted because the widening causes an extra word wrap. You don't want to see this happen when the only thing you do is move the cursor; if you don't do anything the page layout should not change.
The shift can also happen when switching between normal and italic. I would try changing colors, or toggle underline if you have room below the text. (underlining should stay clear from the bottom border)
I would be boo'd if I used switching fonts for my Form Design class :-)
(°) The word font is often misused. "Verdana" is a typeface, "Verdana normal" and "Verdana bold" are different fonts of the same typeface.
不是非常优雅的解决方案,但是“有效”:
Not very elegant solution, but "works":
将
letter-spacing
与text-shadow
结合使用:Use
letter-spacing
withtext-shadow
:我用几行 JavaScript 解决了这个问题。
I solved this with few lines of javascript.
这是我更喜欢的解决方案。 它需要一些 JS,但你不需要你的 title 属性完全相同,并且你的 CSS 可以保持非常简单。
This is the solution I prefer. It requires a bit of JS but you don't need your title property to be the exact same and your CSS can remain very simple.
那这个呢? 一个 javascript - CSS3 免费解决方案。
http://jsfiddle.net/u1aks77x/1/
What about this? A javascript - CSS3 free solution.
http://jsfiddle.net/u1aks77x/1/
我结合了上面的一些技术来提供一些在关闭 js 的情况下不会完全糟糕的东西,并且使用一些 jQuery 会更好。 现在浏览器对亚像素字母间距的支持正在改进,使用它真的很不错。
I've combined a bunch of the techniques above to provide something that doesn't totally suck with js turned off and is even better with a bit of jQuery. Now that browsers support for subpixel letter-spacing is improving, it's really nice to use it.
最好使用 a::before 而不是 a::after,如下所示:
有关更多详细信息:https://jsfiddle.net/r25foavy/
It's better to use a::before instead a::after like this:
For more details: https://jsfiddle.net/r25foavy/
我修复了悬停大胆成功时的菜单。 它支持响应式,这是我的代码:
I fixed menu when hover bold success. It support responsive, this is my code:
我可以建议您两种变体
第一个选项:是将每个列表项的宽度设置为%
这是一个简单的示例
第二个选项: > 是在活动元素上使用文本阴影
但我建议使用第一个选项,即将每个元素的宽度指定为百分比,因为文本阴影并不总是在移动浏览器中起作用
I can advise you two variants
The first option: is you set the width of each list item to %
Here is a simple example
The second option: is to use a text-shadow on the active element
But I recommend using the first option, that is, specifying the width as a percentage for each element, since text-shadow does not always work in mobile browsers
使用 Overflow:hidden 隐藏其他像素
当元素的
font-weight:400
时,将元素的父元素overflow:hidden
和max-width
设置为元素大小代码>.Hide additional pixels with overflow:hidden
Give parent of the element
overflow:hidden
andmax-width
set to element size when it hasfont-weight:400
.如果您不反对使用 Javascript,则可以在页面显示后设置适当的宽度。 这是我的做法(使用原型):
If you're not averse to using Javascript, you can set the proper width once the page is shown. Here's how I did it (using Prototype):
当问题有一个简单的解决方案时,有人告诉你不要这样做,我真的无法忍受。 我不确定 li 元素,但我刚刚解决了同样的问题。 我有一个由 div 标签组成的菜单。
只需将 div 标签设置为“display: inline-block”即可。 内联,因此它们彼此相邻并阻塞,您可以设置宽度。 只需将宽度设置得足以容纳粗体文本并使文本居中对齐即可。
(注意:它似乎剥离了我的 html [如下],但每个菜单项都有一个 div 标签,其中包含相应的 ID 和类名 SearchBar_Cateogory。即:
HTML
(我在每个菜单项周围都包含了锚标记,但我无法作为新用户提交它们)
CSS:
I really can't stand it when someone tells you not to do something that way when there's a simple solution to the problem. I'm not sure about li elements, but I just fixed the same issue. I have a menu consisting of div tags.
Just set the div tag to be "display: inline-block". Inline so they sit next to each other and block to that you can set a width. Just set the width wide enough to accomodate for the bolded text and have the text center aligned.
(Note: It seems to be stripping out my html [below], but each menu item had a div tag wrapped around it with the corrasponding ID and the class name SearchBar_Cateogory. ie:
<div id="ROS_SearchSermons" class="SearchBar_Category">
HTML
(I had anchor tags wrapped around each menu item, but i wasn't able to submit them as a new user)
CSS:
如果粗体文本比常规文本宽,您也可以尝试使用负边距。 (不总是)
因此,我们的想法是使用类来设置 :hover 状态的样式。
jQuery:
CSS:
我希望我能提供帮助!
You can try the negative margins too if the bold text is wider than the regular. (not always)
So the idea is to use classes instead to style the :hover state.
jQuery:
CSS:
I hope I could help!