使用 CSS 将非等宽字体强制为固定宽度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10149330/
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
Force Non-Monospace Font into Fixed Width Using CSS
提问by Jon Raasch
Is there any way to force a font to be monospaced using CSS?
有什么方法可以使用 CSS 强制使字体等宽?
By this I mean, using a non-monospace font, can you force the browser to render each character at a fixed width?
我的意思是,使用非等宽字体,您能否强制浏览器以固定宽度呈现每个字符?
回答by verdy_p
If this is for aligning digits in tables where some fonts (with traditional typography) render them by default with variable width (e.g. Segoe UI on Windows), you should look into CSS properties for:
如果这是为了对齐表格中的数字,其中某些字体(使用传统排版)默认以可变宽度呈现它们(例如 Windows 上的 Segoe UI),您应该查看 CSS 属性:
font-variant-numeric: tabular-nums;
font-variant-numeric: tabular-nums;
(this disables the proportional-nums
default value for the numeric-spacing
variant supported at least by OpenType fonts, and possibly by other font formats supported by the text renderer of your web browser for your particular platform)
(这将禁用至少由 OpenType 字体支持proportional-nums
的numeric-spacing
变体的默认值,并且可能由您的特定平台的 Web 浏览器的文本渲染器支持的其他字体格式禁用)
No javascript needed! It is the cleanest way to disable the variable-width glyphs in these fonts and force them to use tabular digits (this generally uses in the same glyphs in the same font, but their leading and trailing gap is increased so the 10 digits from 0 to 9 will render at the same width; however some font may avoid the visual variable interdigit spacing and will slightly widden some digits, or could add bottom serifs to the foot of digit 1.
不需要javascript!这是禁用这些字体中的可变宽度字形并强制它们使用表格数字的最干净的方法(这通常用于相同字体中的相同字形,但它们的前导和尾随间隙增加,因此从 0 到9 将以相同的宽度呈现;但是某些字体可能会避免视觉上可变的数字间距,并且会稍微加宽一些数字,或者可以在数字 1 的底部添加底部衬线。
Note that this does not disable the variable height observed with Segoe UI (such as some digits will be x-height only like lowercase letters, others will have ascenders or descenders). These traditional digit forms may be disabled with CSS too, using
请注意,这不会禁用 Segoe UI 观察到的可变高度(例如,某些数字将只有小写字母的 x 高度,其他数字将具有上升或下降)。这些传统的数字形式也可以使用 CSS 禁用,使用
font-variant-numeric: lining-nums;
font-variant-numeric: lining-nums;
(this disables the default oldstyle-nums
value for the numeric-figure
variant supported at least by OpenType fonts, and by possibly other font formats supported by the text renderer of your web browser for your particular platform)
(这将禁用至少由 OpenType 字体支持oldstyle-nums
的numeric-figure
变体的默认值,以及您的特定平台的 Web 浏览器的文本渲染器可能支持的其他字体格式)
You can combine both:
您可以将两者结合起来:
font-variant-numeric: tabular-nums lining-nums;
font-variant-numeric: tabular-nums lining-nums;
The snippet below demonstrates this using a single proportional font (not monospaced!) featuring shape variants for digits, such as 'Segoe UI' on Windows and shows the different horizontal and vertical alignments produced.
下面的代码片段使用具有数字形状变体的单一比例字体(不是等宽!)演示了这一点,例如 Windows 上的“Segoe UI”,并显示了产生的不同水平和垂直对齐方式。
Note that this style does not prohibit digits to change width if different styles like bold or italic is applied instead of medium roman as shown below because these will use different fonts with their own distinct metrics (this is not warrantied as well with all monospace fonts).
请注意,如果应用不同的样式(如粗体或斜体)而不是下图所示的中罗马字体,则此样式不会禁止数字更改宽度,因为它们将使用具有自己独特度量的不同字体(并非所有等宽字体都保证如此) .
html { font-family: 'Segoe UI'; /* proportional with digit variants */ }
table { margin: 0; padding: 0; border: 1px solid #AAA; border-collapse: collapse; }
th, td { vertical-align:top; text-align:right; }
.unset { font-variant-numeric: unset; }
.traditional { font-variant-numeric: proportional-nums oldstyle-nums; }
.lining { font-variant-numeric: proportional-nums lining-nums; }
.tabular-old { font-variant-numeric: tabular-nums oldstyle-nums; }
.tabular-new { font-variant-numeric: tabular-nums lining-nums; }
.normal { font-variant-numeric: normal; }
<table>
<tr><th>unset<td><table width="100%" class="unset">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>traditional<td><table width="100%" class="traditional">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>lining<td><table width="100%" class="lining">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>tabular-old<td><table width="100%" class="tabular-old">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>tabular-new<td><table width="100%" class="tabular-new">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
<tr><th>normal<td><table width="100%" class="normal">
<tr><td>Rs12,34,56,789.00/Gal<td><i>Difference Rs86,41,97,532.11/Gal
<tr><td>Rs98,76,54,321.11/Gal<td><b>Total Rs1,11,11,11,110.11/Gal
</table>
</table>
Reference: https://developer.mozilla.org/fr/docs/Web/CSS/font-variant-numeric
参考:https: //developer.mozilla.org/fr/docs/Web/CSS/font-variant-numeric
回答by Blender
You can't do this with CSS. Even if you could, the result will look horrible:
你不能用 CSS 做到这一点。即使可以,结果也会看起来很糟糕:
If you really do need to do this, you could use JavaScript to wrap each individual character in an element (or just do it by hand):
如果你真的需要这样做,你可以使用 JavaScript 将每个单独的字符包装在一个元素中(或者只是手动完成):
function wrap_letters($element) {
for (var i = 0; i < $element.childNodes.length; i++) {
var $child = $element.childNodes[i];
if ($child.nodeType === Node.TEXT_NODE) {
var $wrapper = document.createDocumentFragment();
for (var i = 0; i < $child.nodeValue.length; i++) {
var $char = document.createElement('span');
$char.className = 'char';
$char.textContent = $child.nodeValue.charAt(i);
$wrapper.appendChild($char);
}
$element.replaceChild($wrapper, $child);
} else if ($child.nodeType === Node.ELEMENT_NODE) {
wrap_letters($child);
}
}
}
wrap_letters(document.querySelectorAll('.boxes')[0]);
wrap_letters(document.querySelectorAll('.boxes')[1]);
.char {
outline: 1px solid rgba(255, 0, 0, 0.5);
}
.monospace .char {
display: inline-block;
width: 15px;
text-align: center;
}
<h2 class="boxes">This is a title</h2>
<h2 class="boxes monospace">This is a title</h2>
回答by Dour High Arch
Why not think outside the box and inside a table for this:
为什么不跳出框框并在桌子内思考这个问题:
<table cellpadding="0" cellspacing="0">
<tr><td>T</td><td>h</td><td>e</td><td></td><td>r</td><td>a</td><td>i</td><td>n</td><td></td><td>i</td><td>n</td><td></td><td>S</td><td>p</td><td>a</td><td>i</td><td>n</td><td></td><td>s</td><td>t</td><td>a</td><td>y</td><td>s</td></tr>
<tr><td>m</td><td>a</td><td>i</td><td>n</td><td>l</td><td>y</td><td></td><td>i</td><td>n</td><td></td><td>t</td><td>h</td><td>e</td><td></td><td>p</td><td>l</td><td>a</td><td>i</td><td>n</td><td>s</td><td>.</td></tr>
</table>
回答by Márton Tamás
I've just found the text-transform: full-width;
experimental keyword, which:
我刚刚找到了text-transform: full-width;
实验关键字,它:
[...] forces the writing of a character [...] inside a square [...]
[...] 强制在正方形 [...] 内写入字符 [...]
Combined with negative letter-spacing
, you can get not-so-horrible results:
结合 negative letter-spacing
,您可以获得不那么可怕的结果:
<style>
pre {
font-family: sans-serif;
text-transform: full-width;
letter-spacing: -.2em;
}
</style>
<!-- Fixed-width sans-serif -->
<pre>
. i I 1 | This is gonna be awesome.
ASDFGHJK | This is gonna be awesome.
</pre>
<!-- Default font -->
. i I 1 | This is gonna be awesome.
<br>
ASDFGHJK | This is gonna be awesome.
回答by Vince
Well, you didn't say using onlyCSS. It is possible to do this with just a little bit of Javascript to wrap each letter in a span
. The rest is in CSS...
好吧,您并没有说只使用CSS。只需要一点点 Javascript 就可以做到这一点,将每个字母包装在span
. 其余的在 CSS 中...
window.onload = function() {
const secondP = document.getElementById('fixed');
const text = secondP.innerText;
const newText = text.split('').map(c => {
const span = `<span>${c}</span>`;
return span;
}).join('');
secondP.innerHTML = newText;
}
p {
position: relative;
border: 1px solid black;
border-radius: 1em;
padding: 1em;
margin: 3em 1em;
}
p::after {
content: attr(name);
display: block;
background-color: white;
color: green;
padding: 0 0.5em;
position: absolute;
top: -0.6em;
left: 0.5em;
}
#fixed span {
display: inline-block;
width: 1em;
text-align: center;
}
<p id="variable" name="Variable Width">It might not look nice, but with a little Javascript, I can force a variable width font to act like a fixed-width font.</p>
<p id="fixed" name="Fixed Width">It might not look nice, but with a little Javascript, I can force a variable width font to act like a fixed-width font.</p>
In a paragraph with regular text, it looks terrible, but There are instances when this makes sense. Icon fonts and Unicode symbols could both make use of this technique.
在带有常规文本的段落中,它看起来很糟糕,但在某些情况下这是有道理的。图标字体和 Unicode 符号都可以使用这种技术。
I found this question while trying to find a solution for Unicode symbols that were shifting regular text to the right when they were replaced with other Unicode symbols.
我在尝试为 Unicode 符号寻找解决方案时发现了这个问题,这些 Unicode 符号在替换为其他 Unicode 符号时会将常规文本向右移动。
回答by Jukka K. Korpela
No, there is no way to force anything in CSS. And there isn't even a way to suggest that a non-monospace font be rendered as a monospace font.
不,没有办法在 CSS 中强制执行任何操作。甚至没有办法建议将非等宽字体呈现为等宽字体。
回答by Mettin Parzinski
I've done a verry pretty thing sometimes for countdowns:
我有时为倒计时做了一件非常漂亮的事情:
html:
html:
<div class="counter">
<span class="counter-digit counter-digit-0">2</span>
<span class="counter-digit counter-digit-1">4</span>
<span class="counter-digit counter-digit-divider">/</span>
<span class="counter-digit counter-digit-2">5</span>
<span class="counter-digit counter-digit-3">7</span>
</div>
scss:
scss:
$digit-width: 18px;
.counter {
text-align: center;
font-size: $digit-width;
position: relative;
width : $digit-width * 4.5;
margin: 0 auto;
height: 48px;
}
.counter-digit {
position: absolute;
top: 0;
width: $digit-width;
height: 48px;
line-height: 48px;
padding: 0 1px;
&:nth-child(1) { left: 0; text-align: right; }
&:nth-child(2) { left: $digit-width * 1; text-align: left;}
&:nth-child(3) { left: $digit-width * 2; text-align: center; width: $digit-width / 2} // the divider (/)
&:nth-child(4) { left: $digit-width * 2.5; text-align: right;}
&:nth-child(5) { left: $digit-width * 3.5; text-align: left;}
}
回答by jeremyharris
No, not unless it's an actual mono-spaced font.
不,除非它是实际的等宽字体。