web-dev-qa-db-fra.com

Forcer les polices non monospaces en largeur fixe à l'aide de CSS

Existe-t-il un moyen de forcer une police à être monospace à l'aide de CSS?

Je veux dire par là, en utilisant une police non monospace, pouvez-vous forcer le navigateur à rendre chaque caractère à une largeur fixe?

32
Jon Raasch

Pourquoi ne pas penser en dehors de la boîte et à l'intérieur d'une table pour cela:

<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>
12
Dour High Arch

S'il s'agit d'aligner des chiffres dans des tableaux où certaines polices (avec une typographie traditionnelle) les rendent par défaut avec une largeur variable (par exemple, Segoe UI sous Windows), vous devez rechercher dans les propriétés CSS:

font-variant-numeric: tabular-nums;

(ceci désactive la valeur par défaut proportional-nums pour la variante numeric-spacing prise en charge au moins par les polices OpenType et éventuellement par d'autres formats de polices pris en charge par le rendu du texte de votre navigateur Web pour votre plate-forme particulière)

Pas de javascript nécessaire! C’est le moyen le plus simple de désactiver les glyphes de largeur variable dans ces polices et de les forcer à utiliser des chiffres tabulaires (généralement utilisés dans les mêmes glyphes de la même police, mais leur espace entre les chiffres de début et de fin est augmenté de sorte que les 10 chiffres de 0 à 9 sera rendu à la même largeur, mais certaines polices peuvent éviter l’espacement visuel variable entre les chiffres et masquer légèrement certains chiffres, ou ajouter des empreintes au bas du pied du chiffre 1.

Notez que cela ne désactive pas la hauteur variable observée avec Segoe UI (certains chiffres auront une hauteur x seulement comme des lettres minuscules, d'autres auront des ascendeurs ou des descendeurs). Ces formes numériques traditionnelles peuvent également être désactivées avec CSS, en utilisant

font-variant-numeric: lining-nums;

(ceci désactive la valeur oldstyle-nums par défaut pour la variante numeric-figure prise en charge au moins par les polices OpenType et éventuellement par d'autres formats de police pris en charge par le rendu du texte de votre navigateur Web pour votre plate-forme particulière)

Vous pouvez combiner les deux:

font-variant-numeric: tabular-nums lining-nums;


L'extrait ci-dessous le montre en utilisant une seule police proportionnelle (non monospace!) Comportant des variantes de forme pour les chiffres, telles que 'Segoe UI' sous Windows et montrant les différents alignements horizontaux et verticaux produits.

Notez que ce style n'interdit pas aux chiffres de changer de largeur si différents styles, tels que gras ou italique, sont appliqués à la place du moyen roman, comme indiqué ci-dessous, car ils utiliseront des polices différentes avec leurs propres métriques distinctes (ceci n'est pas garanti non plus avec toutes les polices monospaces). .

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>

Référence: https://developer.mozilla.org/fr/docs/Web/CSS/font-variant-numeric

11
verdy_p

Vous ne pouvez pas faire cela avec CSS. Même si vous le pouviez, le résultat serait horrible:

enter image description here

Si vous en avez vraiment besoin, vous pouvez utiliser JavaScript pour envelopper chaque caractère dans un élément (ou le faire à la main):

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>

10
Blender

Non, il n'y a aucun moyen de forcer quoi que ce soit en CSS. Et il n’ya même pas moyen de suggérer qu’une police non monospace soit rendue comme une police monospace.

3
Jukka K. Korpela

Eh bien, vous n'avez pas dit d'utiliser seulement CSS. Il est possible de faire cela avec juste un peu de Javascript pour envelopper chaque lettre dans une span. Le reste est en 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>

Dans un paragraphe avec du texte normal, cela semble terrible, mais il y a des cas où cela est logique. Les polices d'icônes et les symboles Unicode pourraient tous deux utiliser cette technique.

J'ai trouvé cette question en essayant de trouver une solution aux symboles Unicode qui déplaçaient le texte normal vers la droite lorsqu'ils ont été remplacés par d'autres symboles Unicode.

2
Vince

J'ai fait une très jolie chose parfois pour les comptes à rebours:

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:

$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;}
}
1
Mettin Parzinski

Je viens de trouver le text-transform: full-width; mot-clé expérimental , qui:

[...] force l'écriture d'un caractère [...] à l'intérieur d'un carré [...]

text-transform | MDN

Combiné avec letter-spacing négatif, vous pouvez obtenir des résultats pas si horribles:

 Fixed-width sans-serif font to mock monospaced font

<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.
0
Tamás Márton

Non, sauf si c'est une police mono-espacée.

0
jeremyharris