CSS: Nachdem bestimmten Elementen kein Inhalt hinzugefügt wurde


100

Ich habe Probleme, das Verhalten der CSS- :afterEigenschaft zu verstehen . Entsprechend der Spezifikation ( hier und hier ):

Wie ihre Namen anzeigen, geben die :beforeund :after-Elemente den Speicherort des Inhalts vor und nach dem Dokumentbauminhalt eines Elements an.

Dies scheint keine Einschränkungen zu setzen, welche Elemente eine :after(oder :before) Eigenschaft haben können. Es scheint jedoch nur mit bestimmten Elementen zu<p> funktionieren ... funktioniert, <img>nicht, <input>nicht, <table>tut. Ich könnte mehr testen, aber der Punkt ist gemacht. Beachten Sie, dass dies in allen Browsern ziemlich konsistent erscheint. Was bestimmt, ob ein Objekt eine :beforeund :after-Eigenschaft akzeptieren kann ?

Antworten:


156

imgund inputsind beide ersetzte Elemente .

Ein ersetztes Element ist jedes Element, dessen Aussehen und Abmessungen von einer externen Ressource definiert werden. Beispiele hierfür sind Bilder ( <img>Tags), Plugins ( <object>Tags) und Formelemente ( <button>, <textarea>, <input>, und <select>Tags). Alle anderen Elementtypen können als nicht ersetzte Elemente bezeichnet werden.

:beforeund arbeiten :afternur mit nicht ersetzten Elementen.

Aus der Spezifikation :

Hinweis. Diese Spezifikation definiert die Interaktion von :beforeund :aftermit ersetzten Elementen (wie IMG in HTML) nicht vollständig . Dies wird in einer zukünftigen Spezifikation genauer definiert.

Mit span:before, span:aftersieht das DOM folgendermaßen aus:

<span><before></before>Content of span<after></after></span>

Offensichtlich wird das nicht funktionieren <img src="" />.


2
"Generierter Inhalt ändert den Dokumentbaum nicht." Ich wäre also überrascht, wenn Sie so etwas wie " <before></before>" in der Quelle finden könnten .
Knu

4
@ Knu: Du hast recht, ich habe es schlecht erklärt. Du wirst es nie finden <before></before>. Ich hätte sagen sollen "so tun als ob DOM" oder so. Es ging darum, das zu zeigen :beforeund :aftersich innerhalb des Elements zu befinden, nicht außerhalb.
dreißig Punkte

Nein, sie werden nicht im Schatten-DOM gespeichert.
Werkzeug

3
Die angegebene Spezifikation sagt dies nicht aus :beforeund :afterfunktioniert nicht für ersetzte Elemente. es heißt nur, dass es nicht „vollständig definiert“, wie und dass dies in Zukunft definiert wird (was bisher noch nicht geschehen ist). Was in DOM passiert, spielt hier keine Rolle. Während Browser diese Pseudoelemente für einige Elemente nicht unterstützen, steht dies nicht in den Spezifikationen, sondern nur für die Implementierungen.
Jukka K. Korpela

Früher habe ich die Erklärung als logisch angesehen ::beforeund ::afterarbeite nicht für leere (leere) Elemente, die niemals tatsächlichen Inhalt haben, bevor / nach denen sie angewendet werden könnten. Überraschenderweise funktionieren sie hrin fast allen Browsern für Elemente.
Ilya Streltsyn

9

:beforeund :aftersind nicht erforderlich für ersetzte Elemente zu arbeiten, und CSS - Spezifikationen nicht angeben , wie sie für sie arbeiten würden, und das Konzept des ersetzten Elements ist etwas vage.

Die CSS 2.1-Spezifikation legt klar nahe, dass sie für ersetzte Elemente funktionieren können , und sagt nur, dass sie nicht vollständig definiert, wie. Dies bezieht sich auf das Problem, dass von einem ersetzten Element ein eigenes visuelles Rendering erwartet wird, das nicht von CSS gesteuert wird, während die Pseudoelemente dem Inhalt des Elements etwas hinzufügen sollten. Die Spezifikation fügt hinzu, dass dies in einer zukünftigen Spezifikation "detaillierter" definiert wird, aber dies hat bisher nicht stattgefunden.

Browser-Anbieter haben nur beschlossen, Probleme zu vermeiden, indem sie diese Pseudoelemente für einige Elemente überhaupt nicht implementiert haben.

Es ist überhaupt nicht klar, was "ersetztes Element" bedeutet, und die Bedeutung scheint sich etwas geändert zu haben. Es wird oft so interpretiert, dass es dasselbe bedeutet wie ein leeres Element (ein Element mit EMPTYdeklariertem Inhalt, dh ein Element, das keinen Inhalt haben kann), aber CSS 2.1 selbst zeigt ein Beispiel-Stylesheet mit dem Selektor br:before(obwohl Browser dies ignoriert haben und brihr eigenes implementieren Weg). Es kann argumentiert werden, dass immer mehr Elemente zumindest teilweise in den Bereich des CSS-Renderings gerückt sind. Beispielsweise kann ein inputElement (einschließlich Schriftart, Farben usw.) in modernen Browsern weitgehend mit CSS gesteuert werden.

Aktuelle Browser (Firefox, IE, Chrome) scheinen die :afterund :beforePseudo-Elemente für andere leere Elemente als nicht zu unterstützen hr. Für hr, IE und Chrome den erzeugten Inhalt in einer begrenzten Box platzieren, die die Durchführung ist hr; Der Inhalt macht die Box größer. Firefox platziert den Inhalt beider (!) Pseudoelemente nach der horizontalen Regel, deren Implementierung es ist hr. Diese Variante veranschaulicht die Arten von Interaktionsproblemen, auf die in CSS 2.1 Bezug genommen wird.

Es wird oft behauptet, dass diese Pseudoelemente nicht für leere Elemente verwendet werden können, da ihre HTML-Definitionen keinen Inhalt zulassen. Dies ist ein Kategoriefehler. Die Syntaxregeln einer Auszeichnungssprache schränken nicht ein, was Sie in CSS tun können

Zum Abschluss :afterund :beforesind derzeit nicht verwendbar für leere Elemente (außer geringfügig für hr), aber dies ist im Wesentlichen auf Implementierungen und kann sich in Zukunft ändern.


-1

Elemente ohne schließendes Tag sind ungültige Elemente und können keinen Inhalt anzeigen:

https://www.w3.org/TR/html5/syntax.html#void-elements

In allen Blink-, Webkit- und Quantum-Browsern können Sie Pseudoelemente nur in Kontrollkästchen erstellen. Dies ist jedoch umstritten, da keine Spezifikation dieses Verhalten zulässt.

Hier ein Beispiel: https://codepen.io/equinusocio/pen/BOBaEM/

input[type="checkbox"] {
  appearance: none;
  color: #000;
  width: 42px;
  height: 24px;
  border: 1px solid currentColor;
  border-radius: 100px;
  cursor: pointer;
  transition: all 100ms;
  background-size: 30%;
  outline: none;
  position: relative;
  box-sizing: border-box;
  background-color: #eee;
  transition: background-color 200ms;

  &::before {
    content: '';
    position: absolute;
    left: 2px;
    top: 2px;
    bottom: 2px;
    height: 18px;
    width: 18px;
    border-radius: 50%;
    background-color: currentColor;
    will-change: transform;
    transition: transform 200ms cubic-bezier(.01,.65,.23,1);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  }

  &:checked {
    background-color: aquamarine;

    &::before {
      transform: translateX(100%);
    }
  }
}

es wird nicht in allen Browsern funktionieren ... und es gibt keine Spezifikation, die besagt, dass wir es jetzt können . Wenn Sie eine haben, teilen Sie sie bitte mit, da es nicht sicher ist,
Pseudoelemente

Es funktioniert in allen Browsern außer IE. Selbst Flexbox wird von IE 9 nicht unterstützt. Wo liegt also das Problem? Diese Lösung funktioniert in allen Blink-, Webkit- und Quantum-Browsern und kann für Benutzer sehr nützlich sein, die nur in Webkit-Umgebungen wie Electron arbeiten.
Mattia Astorino

Wie Sie in Ihrer Antwort gesagt haben, gibt es keine Spezifikation dafür, sodass es eines Tages möglicherweise nicht mehr funktioniert. Es ist nicht das einzige, was sich verhält und ohne definierte Spezifikation funktioniert, aber wir sollten uns niemals auf sie verlassen und sagen, dass sie funktionieren. Es ist wie obselete Tags, sie funktionieren immer noch, aber wir sollten sie nicht mehr verwenden, weil sie eines Tages nicht mehr funktionieren werden. Also ja, dies kann für Leute nützlich sein und meine Kommentare sind auch nützlich, um Leute zu warnen, dass sie sich bewusst sein sollten, dass dies nicht offiziell ist.
Temani Afif
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.