web-dev-qa-db-fra.com

Centrer un pseudo-élément

Première utilisation réelle du pseudo :after sélecteur. Je ne sais pas si le problème que je rencontre est une limitation ou je manque juste quelque chose d'évident.

Voici mon code en direct.

li.current:after {
    border-width: 1px 1px 0 0;
    content: ' ';
    background: #256f9e;
    display: block;
    height: 13px;
    position: absolute;
    width: 10px;
    top: 6;
    margin:0px auto;
    z-index: 99;
    transform: rotate(-224deg);
    -webkit-transform: rotate(-224deg);
    -moz-transform: rotate(-224deg);
    -ms-transform: rotate(-224deg);
    -o-transform: rotate(-224deg);
    transform-Origin: 50% 50%;
    -webkit-transform-Origin: 50% 50%;
    -moz-transform-Origin: 50% 50%;
    -ms-transform-Origin: 50% 50%;
    -o-transform-Origin: 50% 50%;
    text-align: center;
    float: center;
}

J'ai créé un petit triangle (ou plutôt une boîte qui a été tournée pour ressembler à un triangle). Je veux qu'il soit centré dans le <li></li> mais je ne peux pas le comprendre en utilisant mes méthodes normales. Les choses qui ont échoué (sans ordre particulier):

text-align: center;
float: center;
margin: 0 auto;
margin-right: 0;
margin-left: 0;

Qu'est-ce que je rate? Je doute que cela soit important, mais j'utilise AngularJS. J'ai pensé le mentionner au cas où il y aurait un conflit connu entre Angular & Pseudo sélecteurs (dont je doute). Merci.

43
EnigmaRM

Le problème est votre utilisation du positionnement absolute et de la méthode que vous utilisez pour essayer de le centrer. Si vous positionnez absolument un élément, l'ol 'margin: 0 auto; la méthode ne fonctionnera pas pour centrer la chose. Je vous indique une explication de la raison pour laquelle cela se trouve à la fin de la question, mais au cas où vous voudriez que cela fonctionne, passons d'abord à la solution.

Voici un code de travail. Voir sur JSFiddle

#tool-menu li {
  ...
  position: relative;
}

li.current:after {
  ...
  position: absolute;
  width: 10px;
  top: 6;
  left: 50%;
  margin-left: -5px;
}

Décomposons ce qui se passe ici.

Configuration d'un nouveau bloc contenant

Dans votre Fiddle d'origine, le pseudo-élément est positionné absolument par rapport à la fenêtre d'affichage. Un exemple pourrait être le meilleur moyen de montrer ce que cela signifie et pourquoi nous n'en voulons pas. Pensez à le définir sur top: 0. Cela le garderait verrouillé en haut de la fenêtre du navigateur (ou, dans ce cas, le cadre JSFiddle), plutôt que le parent (le li). Donc, si notre menu se trouvait au bas de la page, ou même se déplaçait, le pseudo-élément flottait indépendamment de lui, coincé en haut de la page.

Il s'agit du comportement par défaut d'un élément positionné de manière absolue lorsque vous ne définissez explicitement la position sur aucun élément parent. Ce que nous voulons, c'est que sa position soit définie par rapport au parent. Si nous faisons cela, le pseudo-élément reste avec le parent, peu importe où il se trouve.

Pour ce faire, vous devez définir le parent, #tool-menu li, pour être positionné explicitement (ce qui signifie qu'il doit être différent de position: static). Si vous choisissez d'utiliser position: relative;, cela ne changera pas l'emplacement calculé du parent sur la page et fait ce que nous voulons. C'est pourquoi j'ai utilisé celui-là.

En termes techniques, ce que nous faisons ici est de créer un nouveau contenant un bloc pour l'enfant.

Positionnement du pseudo-élément

Maintenant que notre positionnement absolu sera déterminé par rapport au parent, nous pouvons profiter du fait que nous pouvons utiliser des pourcentages pour définir où placer l'enfant. Dans ce cas, vous voulez que ce soit centré, donc je l'ai défini comme left: 50%.

Si vous faites juste cela, cependant, vous verrez que cela aligne le bord gauche du pseudo-élément à 50%. Ce n'est pas ce que nous voulons - nous voulons que le centre du pseudo-élément soit au milieu. Et c'est pourquoi j'ai ajouté le négatif margin-left. Cela le déplace un peu pour aligner le milieu avec le centre du parent.

Et une fois que nous faisons cela, c'est centré! Éclat!

Pourquoi mon margin: auto; travail?

La valeur automatique d'une marge est calculée à partir d'un algorithme assez complexe. Parfois, il calcule à 0. Je sais par expérience que c'est un exemple de ce qui se passe, bien que je n'aie pas encore tracé mon chemin à travers l'algorithme pour voir exactement pourquoi. Si vous souhaitez le parcourir, jetez un œil aux spécifications que la plupart des navigateurs ont probablement implémentées.

90
jamesplease

Utilisation de calc pour centrer

Vous pouvez également utiliser la fonction calc dans css pour centrer le pseudo-élément.

Remarque: cela n'est pas pris en charge dans IE8 et ci-dessous ( caniuse ), mais vous pouvez fournir un remplacement pour les navigateurs plus anciens.

Regardez-le sur ce stylo code . J'utilise également la méthode de bordure CSS de MarkP pour dessiner le triangle.

li.current:after {
  content: '';
  display: block;
  height: 0;
  position: absolute;
  width: 0;
  overflow: hidden;
  bottom: -5px;
  left: calc(50% - 5px);
  z-index: 2;
  border-top: 5px #256f9e solid;
  border-left: 5px transparent solid;
  border-right: 5px transparent solid;
}
9
Mark Reilly

Ne serait-il pas préférable de simplement définir la largeur en pourcentage, d'en faire un élément de bloc et de l'aligner avec le texte au centre?

"float: center;" n'est pas valide et ne fonctionnera pas. Le mélange d'éléments flottants et positionnés en absolu est un moyen sûr de créer des problèmes avec votre mise en page car ils ne fonctionnent pas vraiment aussi bien ensemble.

Essayez quelque chose comme ceci:

li.current:after {
content: 'YOUR CONTENT';
display: block;
width: 100%;
text-align: center; }
3
Hexdom

Pas directement lié (ont déjà voté pour jmeas) mais vous pouvez également trouver plus facile d'utiliser l'astuce de bordure CSS pour créer le triangle. par exemple.

li.current:after {
    content: '';
    display: block;
    height: 0;
    position: absolute;
    width: 0;
    overflow:hidden;
    bottom: 0;
    left: 50%;
    margin: 0 0 -5px -5px;
    z-index: 99;
    border-top: 5px #256f9e solid;
    border-left: 5px transparent solid;
    border-right: 5px transparent solid;
}

Tactique similaire quant à ce que jmeas a suggéré en ce qui concerne le positionnement vertical. Nous nous alignons sur le bas, puis utilisons une marge négative en bas pour pousser cela à l'emplacement souhaité.

3
MarkP

En utilisant margin:auto au centre

Tant que l'élément a une largeur déclarée, vous pouvez utiliser la méthode de centrage absolu.

Pour utiliser cette méthode, les propriétés right et left doivent être définies sur 0 pour margin: auto pour être efficace.

Cette méthode peut également être étendue pour implémenter le centrage horizontal.

voir le lien pour plus d'informations:

http://www.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/

li.current:after {
  content: "";
  position: absolute;
  display: block;
  right: 0;
  bottom: -5px;
  left: 0;
  margin: auto;
  border-width: 5px;
  border-style: solid;
  border-color: transparent;
  border-top-color: #256f9e;
  width: 200px;
  height: 200px;
}

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}
<div>
  <ul>
    <li class="current"></li>
  </ul>
</div>
1
user1095118