196 votes

CSS : mise en gras d'un texte sans modifier la taille de son conteneur

J'ai un menu de navigation horizontal, qui n'est en fait qu'un simple menu de navigation. <ul> avec les éléments juxtaposés. Je ne définis pas la largeur, mais j'utilise simplement le remplissage, car je souhaite que les largeurs soient définies par la largeur de l'élément de menu. Je mets en gras l'élément sélectionné.

Le problème est qu'en gras, le mot devient légèrement plus large, ce qui entraîne un léger décalage du reste des éléments vers la gauche ou la droite. Existe-t-il un moyen astucieux d'éviter cela ? Quelque chose qui consisterait à dire au padding d'ignorer la largeur supplémentaire causée par les caractères gras ? Ma première idée a été de soustraire simplement quelques pixels de l'espacement de l'élément "actif", mais cette quantité varie.

Dans la mesure du possible, j'aimerais éviter de définir une largeur statique pour chaque entrée et de la centrer ensuite, contrairement à la solution de remplissage que j'ai actuellement, afin de simplifier les modifications futures des entrées.

221voto

Thorgeir Points 11

J'ai eu le même problème, mais j'ai obtenu un effet similaire avec un petit compromis, j'ai utilisé l'ombre du texte à la place.

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

Voici un exemple concret :

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>

exemple jsfiddle

176voto

La meilleure solution consiste à utiliser ::after

HTML

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

CSS

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

Il ajoute un pseudo-élément invisible dont la largeur correspond à celle d'un texte en gras, dont la source est title attribut.

Les text-shadow la solution n'est pas naturelle sur Mac et n'utilise pas toute la beauté qu'offre le rendu de texte sur Mac :)

http://jsfiddle.net/85LbG/

Crédit : https://stackoverflow.com/a/20249560/5061744

57voto

Adam Katz Points 857

Classic - toutes les polices, un large support

La solution la plus portable et la plus agréable à l'œil serait d'utiliser text-shadow (h/t to <a href="https://stackoverflow.com/a/14978871/519360">Réponse de Thorgeir </a>con <a href="https://stackoverflow.com/q/5687035/519360#comment69586072_14978871">Commentaire de atorscho </a>) combinée avec -webkit-text-stroke-width (lorsque disponible. h/t to <a href="https://stackoverflow.com/a/50511696/519360">Réponse d'Oliver </a>) .

li:hover   { text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor; }
@supports (-webkit-text-stroke-width: 0.04ex) { /* 2017+, mobile 2022+ */
  li:hover { text-shadow: -0.03ex 0 0 currentColor, 0.03ex 0 0 currentColor;
             -webkit-text-stroke-width: 0.04ex; }
}

Cela permet de placer de minuscules "ombres" dans la couleur actuelle de votre police de part et d'autre de chaque caractère en utilisant des unités qui s'échelonneront correctement avec le rendu de la police. S'il y a support du navigateur En revanche, l'ombre est réduite de moitié et nous augmentons la largeur des traits utilisés pour dessiner le texte. L'effet est un peu plus net, car les ombres sont floues sans rayon de flou et les traits sont flous à des niveaux plus élevés (voir la démo ci-dessous).

warning Avertissement : alors que px prennent en charge les valeurs décimales, elles ne seront pas très esthétiques lorsque la taille de la police change (par exemple, si l'utilisateur modifie l'affichage à l'aide de la fonction Ctrl + + ). Utilisez plutôt des valeurs relatives.

Cette réponse utilise des fractions de ex puisqu'elles s'adaptent à la taille de la police.
Dans la plupart des navigateurs par défaut * attendez 1ex8px et donc 0.025ex0.1px .

Moderne - polices variables

Il y a maintenant quelques nouveaux polices variables capable de changer qualité de la police via font-variation-settings . Vous avez besoin des deux support du navigateur (bon depuis 2018) et dans la police spécifique que vous utilisez (ce qui est encore rare).

@import url("https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght,GRAD@8..144,400,45;8..144,400,50;8..144,1000,0&family=Roboto+Serif:opsz,GRAD@8..144,71&display=swap");
li { font-family:Roboto Flex, sans-serif; }

/* Grade: Increase the typeface's relative weight/density */
@supports (font-variation-settings: 'GRAD' 150) {
  li:hover { font-variation-settings: 'GRAD' 150; }
}
/* Text Shadow: Failover for pre-2018 browsers */
@supports not (font-variation-settings: 'GRAD' 150) {
  li:hover { text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor; }
}

Elle charge une police variable puis, dans les navigateurs qui prennent en charge les paramètres de ces polices, demande au navigateur d'afficher cette police avec une note en gras lorsqu'elle est survolée. La solution classique (sans traits puisque ceux-ci sont aussi récents que la prise en charge des polices variables) est fournie comme solution de secours pour les navigateurs plus anciens, mais comme il y a une prise en charge plutôt universelle de la gradation des polices depuis 2018, cela ne devrait plus être nécessaire.

Pour être complet (puisque cela affecte la largeur rendue), les polices variables prennent également en charge les graisses analogiques (gras), ce qui contraste avec les graisses prédéfinies de font-weight . Quelle que soit la méthode utilisée, vous êtes tributaire de la granularité de votre police. Alors que les polices variables qui prennent en charge la méthode wght La plupart des polices de caractères n'ont pas de variation en gras ou n'en ont qu'une seule. Les systèmes qui ont besoin de rendre une police en gras le feront eux-mêmes si nécessaire, mais seulement avec une seule graisse ( détails et exemples ici ). Certaines polices non variables offrent plusieurs poids, comme Roboto utilisé dans la démo ci-dessous. Jouez avec le curseur dans la démo pour voir la différence de granularité.

Démonstration de six méthodes

(Ne vous laissez pas décourager par le gros bloc de code, qui sert principalement à mettre en œuvre le curseur interactif et à comparer toutes les méthodes proposées dans les réponses à cette question).

@import url("https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900");
@import url("https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght,GRAD@8..144,400,45;8..144,400,50;8..144,1000,0&family=Roboto+Serif:opsz,GRAD@8..144,71&display=swap");

body { font-family: 'Roboto'; }
.v   { font-family: 'Roboto Flex'; } /* variable! */

/* For parity w/ shadow, weight is 400+ (not 100+) & grade is 0+ (not -200+) */
li:hover { text-shadow: initial !important; font-weight: normal !important;
           -webkit-text-stroke-width: 0 !important; }
.weight  { font-weight: calc(var(--bold) * 500 + 400); }
.shadow, .grade { text-shadow: calc(var(--bold) * -0.06ex) 0 0 currentColor,
                               calc(var(--bold) * 0.06ex) 0 0 currentColor; }
ul[style*="--bold: 0;"] li { text-shadow:none; } /* none < zero */
.stroke   { -webkit-text-stroke-width: calc(var(--bold) * 0.08ex); }
.strokshd { -webkit-text-stroke-width: calc(var(--bold) * 0.04ex);
              text-shadow: calc(var(--bold) * -0.03ex) 0 0 currentColor,
                           calc(var(--bold) * 0.03ex) 0 0 currentColor; }

.after span   { display:inline-block; font-weight: bold; } /* @SlavaEremenko */
.after:hover span  { font-weight:normal; }
.after span::after { content: attr(title); font-weight: bold;
                     display: block; height: 0; overflow: hidden; }
.ltrsp        { letter-spacing:0px; font-weight:bold; } /* @Reactgular */
.ltrsp:hover  { letter-spacing:1px; }

@supports (font-variation-settings: 'GRAD' 150) { /* variable font support */
  :hover { font-variation-settings: 'GRAD' 0 !important; }
  .weight.v { font-weight: none !important;
    font-variation-settings: 'wght' calc(var(--bold) * 500 + 400); }
  .grade { text-shadow: none !important;
    font-variation-settings: 'GRAD' calc(var(--bold) * 150); }
}

Boldness: <input type="range" value="0.5" min="0" max="1.5" step="0.01"
            style="height: 1ex;"
            onmousemove="document.getElementById('dynamic').style
                           .setProperty('--bold', this.value)">

<ul style="--bold: 0.5; margin:0;" id="dynamic">
<li class=""        >MmmIii123 This tests regular weight/grade/shadow</li>
<li class="weight"  >MmmIii123 This tests the slider (weight)</li>
<li class="weight v">MmmIii123 This tests the slider (weight, variable)</li>
<li class="grade v" >MmmIii123 This tests the slider (grade, variable)</li>
<li class="shadow"  >MmmIii123 This tests the slider (shadow)</li>
<li class="stroke"  >MmmIii123 This tests the slider (stroke)</li>
<li class="strokshd">MmmIii123 This tests the slider (50/50 stroke/shadow)</li>
<li class="after"><span title="MmmIii123 This tests [title]"
                    >MmmIii123 This tests [title]</span> (@SlavaEremenko)</li>
<li class="ltrsp"   >MmmIii123 This tests ltrsp (@Reactgular)</li>
</ul>

Survolez les lignes rendues pour voir en quoi elles diffèrent du texte standard. (Cela inverse l'intention de la question de mettre en gras le texte survolé afin de pouvoir comparer plus facilement les différentes méthodes). Déplacez le curseur d'audace (pour les entrées contrôlées par le curseur) ou modifiez le niveau de zoom de votre navigateur ( Ctrl + + et Ctrl + - ) pour voir comment ils varient.

Notez que le poids (non variable) s'ajuste en quatre étapes discrètes alors que le poids variable est continu.

J'ai ajouté deux autres solutions à titre de comparaison : L'astuce de @Reactgular pour l'espacement des lettres qui ne fonctionne pas très bien puisqu'elle implique de deviner les plages de largeur de la police, et Le site de @SlavaEremenko ::after astuce de dessin ce qui laisse un espace supplémentaire gênant pour que le texte en gras puisse s'étendre sans gêner les éléments de texte voisins (j'ai placé l'attribution après le texte en gras pour que vous puissiez voir qu'il ne bouge pas).

26voto

Mathew Foscarini Points 6076

J'ai constaté que la plupart des polices ont la même taille lorsque l'on ajuste l'espacement des lettres de 1 px.

a {
   letter-spacing: 1px;
}

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

Bien que cela modifie la police normale, chaque lettre a un espacement supplémentaire d'un pixel. Pour les menus, les titres sont si courts que cela ne pose pas de problème.

18voto

Oliver Points 660

Pour une réponse plus actualisée, vous pouvez utiliser -webkit-text-stroke-width :

.element {
  font-weight: normal;
}

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

Cela permet d'éviter les pseudo-éléments (ce qui est un avantage pour les lecteurs d'écran) et les ombres de texte (qui ont un aspect désordonné et peuvent encore créer un léger effet de "saut") ou de fixer des largeurs fixes (ce qui peut s'avérer peu pratique).

Il vous permet également de définir un élément plus gras que 1px (théoriquement, vous pouvez rendre une police aussi grasse que vous le souhaitez et pourrait également être un entraînement de mauvaise qualité pour créer une version grasse d'une police qui n'a pas de variante grasse, comme les polices personnalisées ( edit : les polices variables déprécient cette suggestion ). Bien qu'il faille éviter de le faire, car certaines polices risquent d'apparaître rayées et déchiquetées.)

Cela fonctionne définitivement dans Edge, Firefox, Chrome et Opera (au moment de la publication). et dans Safari ( éditer : @Lars Blumberg merci de le confirmer ). Il ne fonctionne pas dans IE11 ou dans les versions inférieures.

Notez également qu'il utilise l'option -webkit préfixe, il ne s'agit donc pas d'une norme et le soutien pourrait être supprimé à l'avenir ; ne vous fiez donc pas à cette technique si l'audace est vraiment importante - il est préférable d'éviter cette technique à moins qu'elle ne soit simplement esthétique.

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