281 votes

Déplacement des éléments en ligne lorsqu'ils sont mis en gras au survol de la souris

J'ai créé un menu horizontal en utilisant des listes HTML et CSS. Tout fonctionne comme il se doit, sauf lorsque vous survolez les liens. Vous voyez, j'ai créé un état de survol en gras pour les liens, et maintenant les liens du menu se déplacent à cause de la différence de taille en gras.

Je rencontre le même problème que ce billet de SitePoint . Cependant, le message ne contient pas de solution appropriée. J'ai cherché partout une solution et je n'en ai pas trouvé. Je ne dois pas être le seul à essayer de le faire.

Quelqu'un a-t-il une idée ?

P.S. : Je ne connais pas la largeur du texte des éléments de menu et je ne peux donc pas simplement définir la largeur des éléments li.

.nav { margin: 0; padding: 0; }
.nav li { 
    list-style: none; 
    display: inline; 
    border-left: #ffffff 1px solid; 
}
.nav li a:link, .nav li a:visited { 
    text-decoration: none; 
    color: #000; 
    margin-left: 8px; 
    margin-right: 5px; 
}
.nav li a:hover{ 
    text-decoration: none; 
    font-weight: bold; 
}
.nav li.first { border: none; }

<ul class="nav">
    <li class="first"><a href="#">item 0</a></li>
    <li><a href="#">item 1</a></li>
    <li><a href="#">item 2</a></li>
    <li><a href="#">item 3</a></li>
    <li><a href="#">item 4</a></li>
</ul>

521voto

350D Points 457

Prédéfinir la largeur en utilisant un pseudo-élément invisible qui a le même contenu et le même style que le style de survol du parent. Utilisez un attribut de données, comme title comme source de contenu.

li {
    display: inline-block;
    font-size: 0;
}

li a {
    display:inline-block;
    text-align:center;
    font: normal 16px Arial;
    text-transform: uppercase;
}

a:hover {
    font-weight:bold;
}

/* SOLUTION */
/* The pseudo element has the same content and hover style, so it pre-sets the width of the element and visibility: hidden hides the pseudo element from actual view. */
a::before {
    display: block;
    content: attr(title);
    font-weight: bold;
    height: 0;
    overflow: hidden;
    visibility: hidden;
}

<ul>
    <li><a href="#" title="height">height</a></li>
    <li><a href="#" title="icon">icon</a></li>
    <li><a href="#" title="left">left</a></li>
    <li><a href="#" title="letter-spacing">letter-spacing</a></li>
    <li><a href="#" title="line-height">line-height</a></li>
</ul>

26 votes

Parfait ! Cela fonctionne pour le <a> même sans utiliser un ul, j'utiliserais un autre attribut comme data-text au lieu de title par contre.

6 votes

Cette solution fonctionne, mais elle est meilleure lorsque vous ajoutez margin-top: -1px a :after pour éviter de créer un espace de 1px de hauteur.

1 votes

C'est une excellente solution ! Par curiosité, y a-t-il une différence de résultat entre "a:after" et "a::after" ?

62voto

Stefan Jestanoff Points 111

Une solution de compromis consiste à simuler le gras avec l'ombre du texte, par exemple :

text-shadow : 0 0 0.01px noir ;

Pour une meilleure comparaison, j'ai créé ces exemples :

a, li {
  color: black;
  text-decoration: none;
  font: 18px sans-serif;
  letter-spacing: 0.03em;
}
li {
  display: inline-block;
  margin-right: 20px;
  color: gray;
  font-size: 0.7em;
}
.bold-x1 a.hover:hover,
.bold-x1 a:not(.hover) {
  text-shadow: 0 0 .01px black;
}
.bold-x2 a.hover:hover,
.bold-x2 a:not(.hover){
  text-shadow: 0 0 .01px black, 0 0 .01px black;
}
.bold-x3 a.hover:hover,
.bold-x3 a:not(.hover){
  text-shadow: 0 0 .01px black, 0 0 .01px black, 0 0 .01px black;
}
.bold-native a.hover:hover,
.bold-native a:not(.hover){
  font-weight: bold;
}

.bold-native li:nth-child(4),
.bold-native li:nth-child(5){
 margin-left: -6px;
 letter-spacing: 0.01em;
}

<ul class="bold-x1">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Bold (text-shadow x1)</li>
</ul>
<ul class="bold-x2">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Extra Bold (text-shadow x2)</li>
</ul>
<ul class="bold-native">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Bold (native)</li>
</ul>
<ul class="bold-x3">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Black (text-shadow x3)</li>
</ul>

Passage à text-shadow valeur vraiment faible pour blur-radius rendra l'effet de flou moins apparent.

En général, plus vous répétez text-shadow plus votre texte sera gras, mais dans le même temps, vous perdrez la forme originale des lettres.

Je dois vous avertir que le réglage de la blur-radius en fractions ne va pas rendre la même chose dans tous les navigateurs ! Safari, par exemple, a besoin de valeurs plus grandes pour que le rendu soit le même que celui de Chrome.

11 votes

C'est encore plus laid que les solutions en gras calculées par d'autres navigateurs et devrait être évité.

28voto

Andrew Vit Points 10630

Si vous ne pouvez pas définir la largeur, cela signifie que la largeur changera au fur et à mesure que le texte deviendra gras. Il n'y a aucun moyen d'éviter cela, sauf par des compromis tels que la modification du padding/margins pour chaque état.

2 votes

+1 comme le dit Andrew, le texte en gras est plus large. C'est une réalité. On peut même fixer la largeur des éléments de menu pour éviter cela ou vivre avec (recalculer le padding est imprécis et source d'erreurs).

1 votes

Oui, j'ai tendance à éviter l'effet de survol en gras pour cette raison.

1 votes

"Il n'y a aucun moyen d'éviter cela". Voir la réponse de 350D ci-dessous.

17voto

Alex Points 121

Un dans jquery :

$('ul.nav li a').each(function(){
    $(this).parent().width($(this).width() + 4);
});

éditer : Bien que cela puisse apporter la solution, il faut mentionner que cela ne fonctionne pas en conjonction avec le code dans le post original. "display:inline" doit être remplacé par des paramètres flottants pour qu'un paramètre de largeur soit efficace et que le menu horizontal fonctionne comme prévu.

0 votes

Pouvez-vous faire cela pour tous les liens de la page ? Autrement dit, est-ce que le fait de remplacer ul.nav li a con a fonctionne ?

2 votes

Cette question n'a pas été étiquetée avec JS, et encore moins avec jQuery. Veuillez ne pas publier de solutions inutiles.

2 votes

@Zach Saucier Dans certaines situations, certains développeurs pourraient préférer une solution JS, car elles sont généralement plus courtes. Au lieu de déclasser tous ceux qui ont posté quelque chose avec JS, vous pourriez ajouter le tag JS à la question et laisser chaque personne décider de la solution qu'elle trouve la plus utile.

2voto

Martin Horvath Points 130

Vous pouvez travailler avec la propriété "margin" :

li a {
  margin: 0px 5px 0px 5px;
}

li a:hover {
  margin: 0;
  font-weight: bold;
}

Assurez-vous simplement que les marges gauche et droite sont suffisamment grandes pour que l'espace supplémentaire puisse contenir le texte en gras. Pour les mots longs, vous pouvez choisir des marges différentes. C'est juste une autre solution de contournement, mais elle me convient parfaitement.

0 votes

J'ai utilisé une solution similaire, mais pour moi, le simple fait d'ajouter "margin:0 -2px" au style de survol (et de ne rien ajouter d'autre au style normal) a très bien fonctionné.

8 votes

Cela ne fonctionne pas s'il y a une quelconque variabilité dans la longueur de votre chaîne.

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