CSS:在不改变容器大小的情况下加粗一些文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5687035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 00:16:59  来源:igfitidea点击:

CSS: bolding some text without changing its container's size

cssfontsmenu

提问by Mala

I have a horizontal navigation menu, which is basically just a <ul>with the elements set side-by-side. I do not define width, but simply use padding, because I would like the widths to be defined by the width of the menu item. I bold the currently-selected item.

我有一个水平导航菜单,它基本上只是一个<ul>并排设置的元素。我没有定义宽度,而只是使用填充,因为我希望宽度由菜单项的宽度定义。我将当前选择的项目加粗。

The trouble is that in bolding, the word becomes slightly wider, which causes the rest of the elements to shift slightly to the left or right. Is there a clever way to prevent this from happening? Something along the lines of telling the padding to ignore the extra width caused by the bolding? My first thought was to simply subtract a few pixels from the padding of the "active" element, but this amount varies.

麻烦的是,在加粗时,单词会稍微变宽,这会导致其余元素稍微向左或向右移动。有没有聪明的方法来防止这种情况发生?告诉填充忽略由粗体引起的额外宽度的东西?我的第一个想法是简单地从“活动”元素的填充中减去几个像素,但这个数量会有所不同。

If possible I'd like to avoid setting a static width on each entry and then centering as opposed to the padding solution I currently have, in order to make future changes to the entries simple.

如果可能的话,我想避免在每个条目上设置静态宽度然后居中,而不是我目前拥有的填充解决方案,以便将来对条目进行简单的更改。

回答by Thorgeir

I had the same problem, but got a similar effect with a little compromise, I used text-shadow instead.

我遇到了同样的问题,但稍作妥协就得到了类似的效果,我改用了 text-shadow 。

li:hover {text-shadow:0px 0px 1px black;}

Here's a working example:

这是一个工作示例:

body {
  font-family: segoe ui;
}

ul li {
  display: inline-block;
  border-left: 1px solid silver;
  padding: 5px
}

.textshadow :hover {
  text-shadow: 0px 0px 1px black;
}

.textshadow-alt :hover {
  text-shadow: 1px 0px 0px black;
}

.bold :hover {
  font-weight: bold;
}
<ul class="textshadow">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>text-shadow: 0px 0px 1px black;</code></li>
</ul>

<ul class="textshadow-alt">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>text-shadow: 1px 0px 0px black;</code></li>
</ul>

<ul class="bold">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>font-weight: bold;</code></li>
</ul>

jsfiddle example

jsfiddle 示例

回答by workaholic_gangster911

The best working solution using ::after

使用 ::after 的最佳工作解决方案

HTML

HTML

<li title="EXAMPLE TEXT">
  EXAMPLE TEXT
</li>

CSS

CSS

li::after {
  display: block;
  content: attr(title);
  font-weight: bold;
  height: 1px;
  color: transparent;
  overflow: hidden;
  visibility: hidden;
}

It adds an invisible pseudo-element with width of bold text, sourced by titleattribute.

它添加了一个不可见的伪元素,带有粗体文本的宽度,由title属性提供。

The text-shadowsolution looks unnatural on Mac and doesn't utilize all the beauty that text rendering on Mac offers.. :)

text-shadow解决方案在 Mac 上看起来不自然,并且没有利用 Mac 上文本渲染提供的所有美感.. :)

http://jsfiddle.net/85LbG/

http://jsfiddle.net/85LbG/

Credit: https://stackoverflow.com/a/20249560/5061744

信用:https: //stackoverflow.com/a/20249560/5061744

回答by Adam Katz

The most portable and visually pleasing solution would be to use text-shadow. This revises and shows examples of Thorgeir's answerusing Alexxali'sand my own tweaks:

最便携和视觉上令人愉悦的解决方案是使用text-shadow. 这使用Alexxali和我自己的调整修改并展示了Thorgeir 的答案示例:

  li:hover { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }

This puts tiny "shadows" in black (use your font's color name/code in place of blackif necessary) on both sides of each letter using units that will scale properly with font rendering.

这会在black每个字母的两侧放置黑色的微小“阴影”(如有必要,使用字体的颜色名称/代码代替),使用的单位将随着字体渲染正确缩放。

warningWarning:pxvalues do support decimal values, but they won't look so great when the font size changes (e.g. the user scales the view with Ctrl++). Use relative values instead.

This answer uses fractions of exunits since they scale with the font.
In ~most browser defaults*, expect 1ex8pxand therefore 0.025ex0.1px.

警告警告:px值确实支持十进制值,但是当字体大小改变时它们看起来不会那么好(例如用户用Ctrl+缩放视图+)。请改用相对值。

此答案使用ex单位的分数,因为它们随字体缩放。
在~大多数浏览器默认* 中,期望1ex8px,因此0.025ex0.1px

See for yourself:

你自己看:

li             { color: #000; } /* set text color just in case */
.shadow0       { text-shadow: inherit; }
.shadow2       { text-shadow: -0.02ex 0 #000, 0.02ex 0 #000; }
.shadow4       { text-shadow: -0.04ex 0 #000, 0.04ex 0 #000; }
.shadow6       { text-shadow: -0.06ex 0 #000, 0.06ex 0 #000; }
.shadow8       { text-shadow: -0.08ex 0 #000, 0.08ex 0 #000; }
.bold          { font-weight: bold; }
.bolder        { font-weight: bolder; }
.after span        { display:inline-block; font-weight: bold; } /* workaholic… */
.after:hover span  { font-weight:normal; }
.after span::after { content: attr(title); font-weight: bold; display:block; 
                     height: 0; overflow: hidden; }
.ltrsp         { letter-spacing:0; font-weight:bold; } /* @cgTag */
li.ltrsp:hover { letter-spacing:0.0125ex; }
li:hover       { font-weight: normal!important; text-shadow: none!important; }
<li class="shadow0">MmmIii123 This line tests shadow0 (plain)</li>
<li class="shadow2">MmmIii123 This line tests shadow2 (0.02ex)</li>
<li class="shadow4">MmmIii123 This line tests shadow4 (0.04ex)</li>
<li class="shadow6">MmmIii123 This line tests shadow6 (0.06ex)</li>
<li class="shadow8">MmmIii123 This line tests shadow8 (0.08ex)</li>
<li class="after"><span title="MmmIii123 This line tests [title]"
                   >MmmIii123 This line tests [title]</span> (@workaholic…)</li>
<li class="ltrsp"  >MmmIii123 This line tests ltrsp (@cgTag)</li>
<li class="bold"   >MmmIii123 This line tests bold</li>
<li class="bolder" >MmmIii123 This line tests bolder</li>
<li class="shadow2 bold">MmmIii123 This line tests shadow2 (0.02ex) + bold</li>
<li class="shadow4 bold">MmmIii123 This line tests shadow4 (0.04ex) + bold</li>
<li class="shadow6 bold">MmmIii123 This line tests shadow6 (0.06ex) + bold</li>
<li class="shadow8 bold">MmmIii123 This line tests shadow8 (0.08ex) + bold</li>

Hover over the rendered lines to see how they differ from standard text.

将鼠标悬停在渲染的行上以查看它们与标准文本的不同之处。

Alter your browser's zoom level (Ctrl++and Ctrl+-) to see how they vary.

更改浏览器的缩放级别(Ctrl++Ctrl+ -)以查看它们的变化情况。

I added two other solutions here for comparison: @cgTag's letter spacing trick, which doesn't work so well since it involves guessing font width ranges, and @workaholic_gangster911's ::after drawing trick, which leaves awkward extra space so the bold text can expand without nudging neighboring text items (I put the attribution after the bold text so you can see how it does not move).

我在这里添加了另外两个解决方案以进行比较:@cgTag 的字母间距技巧,它效果不佳,因为它涉及猜测字体宽度范围,以及@workaholic_gangster911 的 ::after 绘图技巧,它留下了尴尬的额外空间,以便粗体文本可以扩展不轻推相邻的文本项(我将属性放在粗体文本之后,这样您就可以看到它是如何不动的)。



In the future, we'll have more variable fontscapable of things like changing font gradevia font-variation-settings. Browser supportis ramping up (Chrome 63+, Firefox 62+) but this still requires more than just standard fonts and few existing fonts support it.

在未来,我们将有更多的可变字体能之类的东西改变字体级通过font-variation-settings浏览器支持正在增加(Chrome 63+、Firefox 62+),但这仍然需要的不仅仅是标准字体,而且很少有现有字体支持它。

If you embed a variable font, you'll be able to use CSS like this:

如果您嵌入了可变字体,您将能够像这样使用 CSS:

/* Grade: Increase the typeface's relative weight/density */
@supports (font-variation-settings: 'GRAD' 150) {
  li:hover { font-variation-settings: 'GRAD' 150; }
}
/* Failover for older browsers: tiny shadows at right & left of the text
 * (replace both instances of "black" with the font color) */
@supports not (font-variation-settings: 'GRAD' 150) {
  li:hover { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }
}

There is a live demowith a slider to play with various grades on the Mozilla Variable Fonts Guide. Google's Introduction to variable fonts on the webhas an animated GIF demonstrating a toggle between a high grade and no grade:

Mozilla Variable Fonts Guide 上有一个带有滑块的现场演示,可以使用各种等级。谷歌在网络上对可变字体介绍有一个动画 GIF,展示了高等级和无等级之间的切换:

animated Amstelvar Alpha font demo with toggling grade axis

带有切换等级轴的动画 Amstelvar Alpha 字体演示

回答by Reactgular

I found that most fonts are the same size when you adjust letter spacing by 1px.

我发现当您将字母间距调整 1px 时,大多数字体的大小都是相同的。

a {
   letter-spacing: 1px;
}

a:hover {
   font-weight: bold;
   letter-spacing: 0px;
}

While this does change the regular font so that each letter has an extra pixel spacing. For menus the titles are so short it doesn't present as a problem.

虽然这确实改变了常规字体,但每个字母都有一个额外的像素间距。对于菜单,标题很短,不会出现问题。

回答by Oliver

For a more up-to-date answer, you can use -webkit-text-stroke-width:

有关更新的答案,您可以使用-webkit-text-stroke-width

.element {
  font-weight: normal;
}

.element:hover {
  -webkit-text-stroke-width: 1px;
  -webkit-text-stroke-color: black;
}

This avoids any pseudo-elements (which is a plus for screen readers) and text-shadows (which looks messy and can still create a slight 'jump' effect) or setting any fixed widths (which can be impractical).

这避免了任何伪元素(这对屏幕阅读器来说是一个加分项)和文本阴影(看起来很乱,但仍会产生轻微的“跳跃”效果)或设置任何固定宽度(这可能不切实际)。

It also allows you to set an element to be bolder than 1px (theoretically, you can make a font as bold as you like and could also be a shoddy-ish workout for creating a bold version of a font that doesn't have a bold variant, like custom fonts (edit: variable fonts depreciate this suggestion). Though this should be avoided as it will probably make some fonts appear scratchy and jagged)

它还允许您将元素设置为大于 1px 的粗体(理论上,您可以将字体设置为您喜欢的粗体,也可以是一种粗体版本的粗体练习,用于创建没有粗体的字体变体,如自定义字体(编辑:可变字体贬低此建议)。尽管应该避免这种情况,因为它可能会使某些字体显得粗糙和锯齿状)

I this definitely works in Edge, Firefox, Chrome and Opera (at time of posting) and in Safari(edit: @Lars Blumberg thanks for confirming that). It does NOT work in IE11 or below.

我这绝对适用于 Edge、Firefox、Chrome 和 Opera(发布时)和 Safari编辑:@Lars Blumberg 感谢您确认)。它不适用于 IE11 或更低版本。

Also note, it uses the -webkitprefix, so this is not standard and support may be dropped in the future, so don't rely on this is bold is really important - it's best to avoid this technique unless it's merely aesthetic.

还要注意,它使用-webkit前缀,所以这不是标准的,将来可能会取消支持,所以不要依赖这个粗体真的很重要 - 最好避免这种技术,除非它只是为了美观。

回答by ajcw

Unfortunately the only way to avoid the width changing when the text is bold is to define the width of the list item, however as you stated doing this manually is time consuming and not scalable.

不幸的是,当文本为粗体时,避免宽度更改的唯一方法是定义列表项的宽度,但是正如您所说,手动执行此操作非常耗时且不可扩展。

The only thing I can think of is using some javascript that calculates the width of the tab before it is bold, and then applies the width at the same time the bold is required (either when you hover or click).

我唯一能想到的是使用一些 javascript 来计算选项卡的宽度,然后将其加粗,然后在需要加粗的同时应用宽度(无论是悬停还是单击时)。

回答by Dan Blows

Use JavaScript to set a fixed width of the li based on the unbolded content, then bold the content by applying a style to the <a>tag (or add a span if the <li>doesn't have any children).

使用 JavaScript 根据未加粗的内容设置 li 的固定宽度,然后通过对<a>标签应用样式来加粗内容(如果<li>没有任何子项,则添加跨度)。

回答by dannymcgee

This is a very old question, but I'm revisiting it because I had this problem in an app I'm developing and found all of the answers here wanting.

这是一个非常古老的问题,但我正在重新审视它,因为我在我正在开发的应用程序中遇到了这个问题,并在这里找到了所有想要的答案。

(Skip this paragraph for the TL;DR...)I'm using the Gotham webfont from cloud.typography.com, and I have buttons which start hollow (with a white border/text and a transparent background) and acquire a background color on hover. I found that some of the background colors I was using didn't contrast well with the white text, so I wanted to change the text to black for those buttons, but — whether because of a visual trick or common anti-aliasing methods — dark text on a light background always appears to be lighter weight than white text on a dark background. I found that increasing the weight from 400 to 500 for the dark text maintained almost exactly the same "visual" weight. However, it was increasing the button width by a tiny amount — a fraction of a pixel — but it was enough to make the buttons appear to "jitter" slightly, which I wanted to get rid of.

(对于 TL;DR 跳过此段...)我正在使用来自 cloud.typography.com 的 Gotham webfont,我有一些按钮,它们开始是空心的(带有白色边框/文本和透明背景)并在悬停时获得背景颜色。我发现我使用的一些背景颜色与白色文本的对比不佳,因此我想将这些按钮的文本更改为黑色,但是——无论是由于视觉技巧还是常见的抗锯齿方法——深色浅色背景上的文本总是比深色背景上的白色文本更轻。我发现将深色文本的权重从 400 增加到 500 可以保持几乎完全相同的“视觉”权重。然而,它只是将按钮宽度增加了一点点——一个像素的一小部分——但这足以使按钮看起来有点“抖动”,我想摆脱这种情况。

Solution:

解决方案:

Obviously, this is a really finicky problem so it required a finicky solution. Ultimately I used a negative letter-spacingon the bolder text as cgTag recommended above, but 1px would have been way overkill, so I just calculated exactly the width I would need.

显然,这是一个非常挑剔的问题,因此需要一个挑剔的解决方案。最终,我letter-spacing按照上面推荐的 cgTag 在粗体文本上使用了负数,但是 1px 会有点过分,所以我只是准确地计算了我需要的宽度。

By inspecting the button in Chrome devtools, I found that the default width of my button was 165.47px, and 165.69px on hover, a difference of 0.22px. The button had 9 characters, so:

通过在 Chrome devtools 中检查按钮,我发现我的按钮的默认宽度是 165.47px,悬停时为 165.69px,相差 0.22px。该按钮有 9 个字符,因此:

0.22 / 9 = 0.024444px

0.22 / 9 = 0.024444 像素

By converting that to em units I could make the adjustment font-size agnostic. My button was using a font size of 16px, so:

通过将其转换为 em 单位,我可以使调整字体大小不可知。我的按钮使用了 16px 的字体大小,所以:

0.024444 / 16 = 0.001527em

0.024444 / 16 = 0.001527em

So for my particular font, the following CSS keeps the buttons exactlythe same width on hover:

因此,对于我的特定字体,以下 CSS 使按钮在悬停时保持完全相同的宽度:

.btn {
  font-weight: 400;
}

.btn:hover {
  font-weight: 500;
  letter-spacing: -0.001527em;
}

With a little testing and using the formula above, you can find exactly the right letter-spacingvalue for your situation, and it should work regardless of font size.

通过一些测试并使用上面的公式,您可以找到letter-spacing适合您情况的正确值,并且无论字体大小如何,它都应该有效。

The one caveat is that different browsers use slightly different sub-pixel calculations, so if you're aiming for this OCD level of sub-pixel-perfect precision, you'll need to repeat the testing and set a different value for each browser. Browser-targeted CSS styles are generally frowned upon, for good reason, but I think this is one use case where it's the only option that makes sense.

一个警告是不同的浏览器使用稍微不同的子像素计算,所以如果你的目标是这种 OCD 级别的子像素完美精度,你需要重复测试并为每个浏览器设置不同的值。面向浏览器的 CSS 样式通常不受欢迎,这是有充分理由的,但我认为这是一个用例,它是唯一有意义的选择。

回答by Dave

Interesting question. I suppose you are using float, right?

有趣的问题。我想你正在使用浮动,对吧?

Well, I don't know any technique you can use to get rid of this font enlarging, hence they will try to fit in the minimum width required - and varying font thickness will change this value.

好吧,我不知道您可以使用任何技术来摆脱这种字体放大,因此他们会尝试适应所需的最小宽度 - 并且改变字体粗细会改变这个值。

The unique solution I know to avoid this changing is one you said you don't want: setting fixed sizes to li's.

我所知道的避免这种变化的独特解决方案是您说您不想要的解决方案:将固定大小设置为 li。

回答by Erik

UPDATE: Had to use the B tag for the title because in IE11 the pseudo class i:after didn't show when i had visibility:hidden.

更新:必须使用 B 标签作为标题,因为在 IE11 中,伪类 i:after 在我有可见性时没有显示:隐藏。

In my case I want to align a (custom designed) input checkbox/radio with label text where the text goes bold when the input is checked.

在我的情况下,我想将(自定义设计的)输入复选框/收音机与标签文本对齐,其中在检查输入时文本变为粗体。

The solution provided here did not work for me in Chrome. The vertical alignment of input and label got messed up with the :after psuedo class and -margins did not fix this.

此处提供的解决方案在 Chrome 中对我不起作用。输入和标签的垂直对齐与 :after 伪类和 -margins 没有解决这个问题。

Here is a fix where you don't get trouble with vertical alignments.

这是一个修复,您不会遇到垂直对齐的问题。

/* checkbox and radiobutton */
label
{
    position: relative;
    display: inline-block;
    padding-left: 30px;
    line-height: 28px;
}

/* reserve space of bold text so that the container-size remains the same when the label text is set to bold when checked. */
label > input + b + i
{
    font-weight: bold;
    font-style: normal;
    visibility: hidden;
}

label > input:checked + b + i
{
    visibility: visible;
}

/* set title attribute of label > b */
label > input + b:after
{
    display: block;
    content: attr(title);
    font-weight: normal;
    position: absolute;
    left: 30px;
    top: -2px;
    visibility: visible;
}

label > input:checked + b:after
{
    display: none;
}

label > input[type="radio"],
label > input[type="checkbox"]
{
    position: absolute;
    visibility: hidden;
    left: 0px;
    margin: 0px;
    top: 50%;
    transform: translateY(-50%);
}

    label > input[type="radio"] + b,
    label > input[type="checkbox"]  + b
    {
        display: block;
        position: absolute;
        left: 0px;
        margin: 0px;
        top: 50%;
        transform: translateY(-50%);
        width: 24px;
        height: 24px;
        background-color: #00a1a6;
        border-radius: 3px;
    }

    label > input[type="radio"] + b
    {
        border-radius: 50%;
    }

    label > input:checked + b:before
    {
        display: inline-block;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) rotate(45deg);
        content: '';
        border-width: 0px 3px 3px 0px;
        border-style: solid;
        border-color: #fff;
        width: 4px;
        height: 8px;
        border-radius: 0px;
    }

    label > input[type="checkbox"]:checked + b:before
    {
        transform: translate(-50%, -60%) rotate(45deg);
    }

    label > input[type="radio"]:checked + b:before
    {
        border-width: 0px;
        border-radius: 50%;
        width: 8px;
        height: 8px;
    }
<label><input checked="checked" type="checkbox"/><b title="Male"></b><i>Male</i></label>
<label><input type="checkbox"/><b title="Female"></b><i>Female</i></label>