105 votes

Forcer une police non-monospace en largeur fixe en utilisant CSS

Existe-t-il un moyen de forcer une police d'écriture à être à espacement fixe en utilisant CSS ?

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

95voto

verdy_p Points 101

Si cela est pour 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 sur Windows), vous devriez examiner les propriétés CSS pour :

font-variant-numeric: tabular-nums;

(cela 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 police pris en charge par le moteur de texte de votre navigateur Web pour votre plateforme particulière)

Aucun JavaScript nécessaire ! C'est la façon la plus propre de désactiver les glyphes à largeur variable dans ces polices et de les forcer à utiliser des chiffres tabulaires (en général, ils utilisent les mêmes glyphes dans la même police, mais leur espace intermédiaire est augmenté de sorte que les 10 chiffres de 0 à 9 s'afficheront à la même largeur ; cependant, certaines polices peuvent éviter l'espace interdigit visuellement variable et élargir légèrement certains chiffres, ou pourraient ajouter des empattements inférieurs au pied du chiffre 1.

Notez que ceci ne désactive pas la hauteur variable observée avec Segoe UI (comme certains chiffres seront constitués uniquement de x-height comme les lettres minuscules, d'autres auront des ascendantes ou des descendantes). Ces formes de chiffres traditionnels peuvent également être désactivées avec CSS, en utilisant

font-variant-numeric: lining-nums;

(cela désactive la valeur par défaut oldstyle-nums 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 moteur de texte de votre navigateur web pour votre plateforme particulière)

Vous pouvez combiner les deux :

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

--

Le code ci-dessous démontre ceci en utilisant une seule police proportionnelle (non à espacement fixe !) présentant des variantes de formes pour les chiffres, comme 'Segoe UI' sur Windows, et montre les différentes alignements horizontaux et verticaux produits.

Notez que ce style n'empêche pas les chiffres de changer de largeur si des styles différents comme gras ou italique sont appliqués au lieu de romain moyen tel que montré ci-dessous, car cela utilisera des polices différentes avec leurs propres métriques distinctes (ce n'est pas non plus garanti avec toutes les polices à espacement fixe).

html { font-family: 'Segoe UI'; /* proportionnelle avec des variantes de chiffres */ }
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; }

unset
  Rs12,34,56,789.00/GalDifference Rs86,41,97,532.11/Gal
  Rs98,76,54,321.11/GalTotal Rs1,11,11,11,110.11/Gal

traditional
  Rs12,34,56,789.00/GalDifference Rs86,41,97,532.11/Gal
  Rs98,76,54,321.11/GalTotal Rs1,11,11,11,110.11/Gal

lining
  Rs12,34,56,789.00/GalDifference Rs86,41,97,532.11/Gal
  Rs98,76,54,321.11/GalTotal Rs1,11,11,11,110.11/Gal

tabular-old
  Rs12,34,56,789.00/GalDifference Rs86,41,97,532.11/Gal
  Rs98,76,54,321.11/GalTotal Rs1,11,11,11,110.11/Gal

tabular-new
  Rs12,34,56,789.00/GalDifference Rs86,41,97,532.11/Gal
  Rs98,76,54,321.11/GalTotal Rs1,11,11,11,110.11/Gal

normal
  Rs12,34,56,789.00/GalDifference Rs86,41,97,532.11/Gal
  Rs98,76,54,321.11/GalTotal Rs1,11,11,11,110.11/Gal

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

Notez que pour la police 'Segoe UI', le style 'normal' est le même que 'tabular-new' (c'est-à-dire 'tabular-nums lining-nums'). Ce n'est pas nécessairement le cas avec toutes les polices qui définissent des variantes pour les chiffres, et ce n'est pas nécessairement le cas pour tous les systèmes numéraux (si les chiffres latins ne sont pas affichés, par exemple avec certains chiffres Brahmi natifs, notamment s'ils proviennent de polices de secours qui ne prennent pas en charge tous ces styles). De même, cela n'a aucun effet sur les caractères non numériques, qui conservent leur largeur variable, mais peuvent définir des variantes spécifiques contrôlées par d'autres propriétés CSS ou en utilisant des contrôles de variantes encodés.

Si vous utilisez des nombres notés dans le système numéral romain, ces chiffres peuvent encore être affichés avec une largeur variable (par exemple, "MCMLXVIII" pour 1968), à moins que le HTML ne contienne des styles CSS permettant de changer leur sémantique en tant que lettres en sémantique en tant que chiffres, ou que ces chiffres soient encodés différemment, par exemple dans des polices CJK avec des variantes "fullwidth", ou dans des polices mathématiques définissant des variantes spécifiques de styles avec des points de code spécifiques au lieu d'utiliser un stylisme et un balisage).

16voto

Dour High Arch Points 11896

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

TheraininSpainstays
mainlyintheplains.

12voto

Blender Points 114729

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

entrer la description de l'image ici

Si vous avez vraiment besoin de le faire, vous pourriez utiliser JavaScript pour envelopper chaque caractère individuel 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;
}

C'est un titre
C'est un titre

12voto

Tamás Márton Points 724

J'ai juste trouvé 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 un letter-spacing négatif, vous pouvez obtenir des résultats pas si horribles :

Police sans empattement à largeur fixe pour imiter une police à espacement uniforme

pre {
  font-family: sans-serif;
  text-transform: full-width;
  letter-spacing: -.2em;
}

. i I 1  | Cela va être génial.
ASDFGHJK | Cela va être génial.

. i I 1  | Cela va être génial.

ASDFGHJK | Cela va être génial.

6voto

Ghodmode Points 342

Eh bien, tu n'as pas dit en utilisant seulement CSS. Il est possible de le faire avec juste un peu de Javascript pour envelopper chaque lettre dans un span. Le reste se trouve en CSS...

window.onload = function() {
  const secondP = document.getElementById('fixed');
  const text = secondP.innerText;
  const newText = text.split('').map(c => {
    const span = `${c}`;
    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;
}

Cela pourrait ne pas sembler agréable, mais avec un peu de Javascript, je peux forcer une police de caractères à largeur variable à se comporter comme une police à largeur fixe.
Cela pourrait ne pas sembler agréable, mais avec un peu de Javascript, je peux forcer une police de caractères à largeur variable à se comporter comme une police à largeur fixe.

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

J'ai trouvé cette question en essayant de trouver une solution pour des symboles Unicode qui décalaient le texte normal vers la droite lorsqu'ils étaient remplacés par d'autres symboles Unicode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X