web-dev-qa-db-fra.com

Positionnement du contenu dans: after the pseudo-element

Je recherche un moyen uniquement CSS de positionner le contenu dans un pseudo-élément :after absolument par rapport à un autre - éventuellement multiline- le bord supérieur de l'élément. Le résultat devrait ressembler à ceci:

Result demonstration

Habituellement, aucune science de fusée n'est impliquée pour résoudre ce problème, mais j'aimerais trouver une solution répondant également aux critères suivants:

  • N'utilisez pas le pseudoélément :beforec'est déjà nécessaire pour obtenir une autre chose indépendante),
  • n'utilisez pas display: block/inline-block; sur l'élément inline (car il crée des trous laids dans le flux de texte),
  • permettre de définir la largeur des éléments en pourcentage de l'élément contenu (au moins après l'application de la règle de trois),
  • ne codez pas en dur la position/marge/remplissage du pseudo-élément :after- de manière à le rendre dépendant de la position de l'élément parent dans l'élément grand-parent, de la hauteur de l'élément parent ou de la hauteur de l'élément réel (ou pour le raccourcir: ne faites rien dépendre du contenu),
  • ne pas insérer d'éléments HTML supplémentaires, et
  • ne pas ajouter JS.

J'ai créé un Codepen qui, espérons-le, facilite la compréhension de ce que je vais faire ici.

Je sais qu’il est facilement possible d’obtenir le résultat en violant l’une des restrictions énumérées ci-dessus (comme le montre le Codepen), mais je cherche une solution _ (élégante) à ce problème qui ne soit pas nécessaire.

Après avoir joué avec cela pendant un bon bout de temps, je dirais que ce n'est pas possible, mais ce serait formidable si quelqu'un pouvait me convaincre du contraire - ou du moins prouve formellement que c'est en fait impossible. Merci beaucoup pour toute aide à l'avance.

11
bfncs

Eh bien, la seule solution possible avec la méthode souhaitée pourrait être la suivante.

- Tout d'abord, pour que cela fonctionne, vous devez définir ::aftercontent directement dans CSS, et non via l'attribut data-. (Je ne sais pas pourquoi, mais cela semble être un problème d'analyse syntaxique.)

- Définissez position:relative sur .wrapper. comme vous allez déplacer ::afterleft-right en fonction de ce parent (pas un seul).

- Définissez width: 100% sur ::after (100% du parent)

- Réglez white-space: pre sur ::after - c'est important

- Écrivez la content directement en utilisant \A (caractère d'échappement) pour casser le mot dans des endroits particuliers.

- Définissez top: 0 et attribuez-lui une position right négative (à quelle distance vous voulez)

Remarque: Vous devrez peut-être définir Word-wrap: break-Word sur certains éléments si le texte supplémentaire déborde du wrapper.

Fondamentalement, ceci est l'ajout/modification de votre CSS:

.wrapper {
  position: relative;
}

.accent::before{
    position: absolute;
    width: 100%;
    content: "Unfortunately \A it is aligned with \A the last line of said span.";
    white-space: pre;
    right: -70%;
}

.content p {
    Word-wrap: break-Word; /* in my example <p> was problematic */
}

_ {Note: Je ne sais pas à quel point cette méthode est bonne pour les conceptions réactives, je ne l'ai jamais essayée de cette façon.

Testé sur FF et Chrome.
Exemple en direct

MODIFIER:
Hm, oui, j'ai commencé avec ::after puis, par accident, je suis passé à ::before =)

Bon, des modifications mineures au CSS:

- Au lieu de width: 100%, définissez width: auto

- Au lieu de top: 0, vous devez manuellement (désolé) réduire margin-top: -(number)px - ne pas utilisertop car il va définir la première position en fonction du wrapper lui-même.

- Réglez right: -(number)% sur right: -(number)px

Modification CSS:

.accent::after{
    width: auto;
    right: -50px;
    margin-top: -40px;
    /* and remove "top" property completely */
}

Exemple live

UN AUTRE ÉDITION
Solution de travail plus propre, dans laquelle vous pouvez utiliser content: attr(data-meta) (supprimé white-space: pre et définir width sur la taille en pourcentage souhaitée:

.accent::after{
    position: absolute;
    width: 30%;
    content: attr(data-meta);
    right: -50px;
    margin-top: -40px;
}

Exemple live

3
Davion

Avec ces exigences, j'ai essayé:

  • en utilisant bottom [?] property à l'élément ::after, ou
  • en utilisant translateY [?] property

Par exemple: http://jsfiddle.net/csdtesting/w4zvmbjh/

<div class="wrapper">
    <div class="content">
         <h2>1-Unfortunately it doesn't work with multline content</h2>

        <p>Pellentesque ultrices sed quam pellentesque, eu ultricies nulla semper.
            <label for="pretty" class="accent" data-meta="Unfortunately it is aligned with the last line of said span.">Etiam leo ligula, laoreet eget urna et, dignissim facilisis nisi ante.</label>Duis gravida lectus tellus, sed rutrum nisi ultricies a. Aliquam pellentesque ante at ipsum convallis porta.</p>
         <h2>2-Unfortunately it doesn't work with multline content</h2>

        <p>Pellentesque ultrices sed quam pellentesque, eu ultricies nulla semper. <span class="accent-bottom" data-meta="Unfortunately it is aligned with the last line of said span.">Etiam leo ligula, laoreet eget urna et, dignissim facilisis nisi ante.</span> Duis gravida lectus tellus, sed rutrum nisi ultricies a. Aliquam pellentesque ante at ipsum convallis porta.</p>
    </div>
</div>

label
{
    color:red !important;
}

/* Basic typo (not problem related) */
body {
  font-family: Georgia, serif;
  font-size: 82.5%;
  line-height: 1.167;
  color: #555;
}

h1, h2 {
  color: #222;
}

h1 {
  font-size: 1.167em;
}

h2 {
  font-size: 1em;
}

/* Problem related styles */

.wrapper {
  position: relative;
  width: 580px;
  margin: 2em auto;
}

.content p {
  width: 62.069%;
}

.accent {
  color: cornflowerblue;
  &:after {
    content: attr(data-meta);
    position: absolute;
    right: 0;
    width: 31.035%;
    transform:translateY(-50%)

  }
}

.accent-bottom {
  color: cornflowerblue;
  &:after {
      content: attr(data-meta);
    position: absolute;
    right: 0;
    width: 31.035%;
    bottom: 14%;
  }
}
0
Giannis Grivas