Заставить немоно-космический шрифт фиксированной ширины с помощью CSS
Есть ли способ заставить моноширинный шрифт с помощью CSS?
Под этим я подразумеваю, используя немонокальный шрифт, вы можете заставить браузер отображать каждый символ с фиксированной шириной?
11 ответов
Если это для выравнивания цифр в таблицах, где некоторые шрифты (с традиционной типографикой) отображают их по умолчанию с переменной шириной (например, Segoe UI в Windows), вы должны изучить свойства CSS для:
font-variant-numeric: tabular-nums;
(это отключает proportional-nums
значение по умолчанию для numeric-spacing
вариант поддерживается как минимум шрифтами OpenType и, возможно, другими форматами шрифтов, поддерживаемыми средством визуализации текста вашего веб-браузера для вашей конкретной платформы)
Нет необходимости в JavaScript! Это самый чистый способ отключить глифы переменной ширины в этих шрифтах и заставить их использовать табличные цифры (обычно они используются в одних и тех же глифах одним и тем же шрифтом, но их начальный и конечный пробел увеличивается, так что 10 цифр от 0 до 9 будет отображаться с той же шириной, однако некоторые шрифты могут избегать межвидового расстояния между визуальными переменными и будут слегка расширять некоторые цифры, или могут добавить нижние засечки к основанию цифры 1.
Обратите внимание, что это не отключает переменную высоту, наблюдаемую в пользовательском интерфейсе Segoe (например, некоторые цифры будут иметь высоту x только как строчные буквы, другие будут иметь восходящие или спусковые элементы). Эти традиционные цифровые формы также можно отключить с помощью CSS, используя
font-variant-numeric: lining-nums;
(это отключает по умолчанию oldstyle-nums
значение для numeric-figure
вариант поддерживается по крайней мере шрифтами OpenType и, возможно, другими форматами шрифтов, поддерживаемыми средством визуализации текста вашего веб-браузера для вашей конкретной платформы)
Вы можете комбинировать оба:
font-variant-numeric: tabular-nums lining-nums;
Приведенный ниже фрагмент демонстрирует это с использованием одного пропорционального шрифта (не моноширинного!) С вариантами формы для цифр, такими как "Segoe UI" в Windows, и показывает различные произведенные горизонтальные и вертикальные выравнивания.
Обратите внимание, что этот стиль не запрещает цифрам изменять ширину, если вместо среднего римского применяются разные стили, такие как полужирный или курсивный, как показано ниже, потому что они будут использовать разные шрифты со своими собственными метриками (это не гарантируется также для всех моноширинных шрифтов),
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>
Ссылка: https://developer.mozilla.org/fr/docs/Web/CSS/font-variant-numeric
Почему бы не мыслить нестандартно и внутри стола для этого:
<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>
Вы не можете сделать это с помощью CSS. Даже если бы вы могли, результат будет выглядеть ужасно:
Если вам действительно нужно это сделать, вы можете использовать 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>
Я только что нашел text-transform: full-width;
экспериментальное ключевое слово, которое:
[...] заставляет писать символ [...] внутри квадрата [...]
В сочетании с негативом 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.
Ну, вы не сказали, используя только 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>
В абзаце с обычным текстом это выглядит ужасно, но бывают случаи, когда это имеет смысл. Иконочные шрифты и символы Unicode могут использовать эту технику.
Я нашел этот вопрос, пытаясь найти решение для символов Юникода, которые смещали обычный текст вправо, когда их заменяли другими символами Юникода.
Нет, в CSS нет возможности что-либо форсировать. И даже нет способа предложить, чтобы немонокальный шрифт отображался как моноширинный шрифт.
Я делал очень милые вещи иногда для обратного отсчета:
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>
СКС:
$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;}
}
Вы можете обернуть цифры секунд в диапазон и стилизовать его как...
.time-seconds {display: inline-block;width: .52em;text-align: center;}
См. Фрагмент.
у меня была такая же проблема. мой шрифт не поддерживал
font-variant-numeric: tabular-nums
(о котором я знал), и другие решения меня не устраивали, поэтому я придумал это - в моем случае мне просто нужно было увеличить расстояние между буквами, а затем раздавить (гигантские) нули, чтобы это выглядело приемлемо:
CSS:
.squashzeros { letter-spacing:.2em; }
.squashzeros span { display:inline-block; margin:0 -.09em; }
JS:
document.querySelectorAll('.squashzeros').forEach((o)=>{
o.innerHTML = o.innerText.replaceAll(/0/g,'<span>0</span>');
});
к сожалению, я не нашел решения только для css.