Rolf B: Greedyness von Kombinatoren

Hallo alle,

in MBs Frage zu seinen Kommentarblöcken ist mir etwas aufgefallen.

Gegeben sei dieses HTML (jaaaa - da fehlen Attribute, es ist Dummy-Markup)

<a>a1</a> <b>b1</b> 
<a>a2</a> <b>b2</b> 
<a>a3</a> <b>b3</b> 
<a>a4</a> <b>b4</b> 
<a>a5</a> <b>b5</b> 

Und diese Regeln:

b { color: green; }
a:active ~ b { color: blue; }
a:active ~ b ~ a ~ b { color: red; }

Ohne Klick sind alle b-Elemente grün. Klicke ich auf ein a-Element, wird das darauf folgende b-Element blau und alle weiteren rot.

ABER

Das müsste ja nicht so sein. Die zweite Regel matcht jedes b hinter einem a:active-Element. Die Existenz eines weiteren a Elementes ist für CSS also kein Grund, mit der Suche nach b Elementen aufzuhören. Das Matching ist greedy.

Wer sagt dem Browser, dass die dritte Regel non-greedy zu sein hat und das erste gefundene a hinter dem :active a matchen muss? CSS könnte ja auch wie in Regel 2 greedy vorgehen und solange b Elemente matchen, bis es nicht mehr anders geht, und dann das letzte a matchen.

Aus Performancegründen ist die non-greedy Logik vermutlich vorzuziehen, denn ein greedy-Verhalten setzt regexiges Backtracking voraus. Aber ich will nicht spekulieren. Weiß jemand, ob und wo dieses Verhalten spezifiziert ist? In CSS-Selectors 4 scheint das nicht zu stehen.

Rolf

--
sumpsi - posui - obstruxi
  1. Hi,

    Gegeben sei dieses HTML (jaaaa - da fehlen Attribute, es ist Dummy-Markup)

    <a>a1</a> <b>b1</b> 
    <a>a2</a> <b>b2</b> 
    <a>a3</a> <b>b3</b> 
    <a>a4</a> <b>b4</b> 
    <a>a5</a> <b>b5</b> 
    

    Und diese Regeln:

    b { color: green; }
    a:active ~ b { color: blue; }
    a:active ~ b ~ a ~ b { color: red; }
    

    Ohne Klick sind alle b-Elemente grün. Klicke ich auf ein a-Element, wird das darauf folgende b-Element blau und alle weiteren rot.

    ABER

    Das müsste ja nicht so sein. Die zweite Regel matcht jedes b hinter einem a:active-Element. Die Existenz eines weiteren a Elementes ist für CSS also kein Grund, mit der Suche nach b Elementen aufzuhören. Das Matching ist greedy.

    Wer sagt dem Browser, dass die dritte Regel non-greedy zu sein hat und das erste gefundene a hinter dem :active a matchen muss? CSS könnte ja auch wie in Regel 2 greedy vorgehen und solange b Elemente matchen, bis es nicht mehr anders geht, und dann das letzte a matchen.

    es gibt doch so verschiedene nth-of- Pseudoklassen - helfen die vielleicht?

    cu,
    Andreas a/k/a MudGuard

    1. Hallo MudGuard,

      es geht mir nicht darum, ein Fehlverhalten zu korrigieren – der Selektor verhält sich wie gewünscht –, sondern darum, ob das vorgefundene Verhalten spezifiziert ist oder implementationsabhängig sein kann.

      Rolf

      --
      sumpsi - posui - obstruxi
  2. @@Rolf B

    Gegeben sei dieses HTML […]

    Und diese Regeln:

    Online-Beispiel? Ts, dass das man den Neulingen im Forum immer wieder sagen muss!

    Ich hab das mal für dich gemacht: Codepen

    Das Matching ist greedy.

    Wenn du mit greedy meinst, dass alle Elemente selektiert werden, auf die der Selektor zutrifft, dann ja.

    Wer sagt dem Browser, dass die dritte Regel non-greedy zu sein hat

    Niemand. Die Regel ist im obigen Sinn greedy.

    und das erste gefundene a hinter dem :active a matchen muss?

    Alle a hinter dem :active matchen, also auch das erste.

    🖖 Живіть довго і процвітайте

    --
    Ad astra per aspera
    1. Hallo Gunnar,

      du hast meine Frage nicht verstanden.

      Woher ist CSS klar, dass das ~ a ~ im Selektor das erste a hinter dem a:active meint, und nicht ein anderes?

      Die Antwort scheint "istnunmalso" zu sein, was aber blöd wäre. Ich suche den Punkt, wo das spezifiziert ist.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hallo,

        du hast meine Frage nicht verstanden.

        ich auch nicht.

        Woher ist CSS klar, dass das ~ a ~ im Selektor das erste a hinter dem a:active meint, und nicht ein anderes?

        Warum meinst du, dass es „CSS klar“ sein muss? Es ist sowohl das erste als auch alle anderen gemeint, auf das/die die Bedingung des Selektors zutrifft.

        Die Antwort scheint "istnunmalso" zu sein, was aber blöd wäre. Ich suche den Punkt, wo das spezifiziert ist.

        Irgendwo ganz am Anfang bei der Erklärung der Selektoren...

        Gruß
        Kalk

        1. Hallo Tabellenkalk,

          ich hatte eine vergleichbare Frage bei Github im Spec-Repository gestellt. Dort habe ich zwei Antworten bekommen, die mir zeigen, dass CSS an der Stelle mit Regexen nicht vergleichbar ist.

          Eine davon kam vom *Trommelwirbel* Tab Atkins 😲. Ui. Das Issue muss ich mir ausdrucken und einrahmen 😂.

          Hauptargument von Tab war: Ich muss mengenorientiert denken. Regexe sind da komplett irreführend. Seine Mengenerklärung, in der zusammengesetzte Selektoren Filter sind und Kombinatoren eine Mengentransformation durchführen, war plausibel, aber ich meine, dass sie so nicht in der Spec steht.

          Dort finde ich etwas anderes, in der Rubrik "API Hooks", und demnach muss ich einen Selektor, der Kombinatoren enthält, von rechts nach links lesen.

          Sei S ein komplexer Selektor (also keine Selektorliste), in der Form A $ B, wobei A wieder ein komplexer Selektor ist, $ ein beliebiger Kombinator und B ein zusammengesetzter Selektor (also kombinatorfrei), dann wird S so ausgewertet, dass zunächst alle Elemente bestimmt werden, auf die B zutrifft. Für jedes gefundene Element F wird der Kombinator „rückwärts“ angewendet, es werden also die Elemente E gesucht, für die E * F zutrifft.

          Für jedes dieser E Elemente wird nun geprüft, ob der Selektor A zutrifft. Falls A wiederum Kombinatoren enthält, ist dieser Prozess rekursiv.

          Und das ist etwas, was ich im Wiki aufschreiben und als klare Erklärung bringen kann. Vielleicht mit etwas weniger Mengenlehre 😉. Aber die ist der Schlüssel zur Erklärung des Verhaltens.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. @@Rolf B

            Und das ist etwas, was ich im Wiki aufschreiben und als klare Erklärung bringen kann.

            Für wen? Zielgruppe?

            Wer aus unserer Zielgruppe würde eine solche Erklärung verstehen? Wer würde eine solche Erklärung überhaupt brauchen?

            Ich sehe die Gefahr, dass man mit einer (über-)komplexen Erklärung eher Leute abschreckt. Manchmal ist weniger mehr.

            🖖 Живіть довго і процвітайте

            --
            Ad astra per aspera
            1. Hallo

              Und das ist etwas, was ich im Wiki aufschreiben und als klare Erklärung bringen kann.

              Für wen? Zielgruppe?

              Wer aus unserer Zielgruppe würde eine solche Erklärung verstehen? Wer würde eine solche Erklärung überhaupt brauchen?

              Anfänger und interessierte Laien brauchen das definitiv nicht. Das ist Wissen für professionelle Anwender und wohl auch eher für fortgeschrittene Solche.

              Ich sehe die Gefahr, dass man mit einer (über-)komplexen Erklärung eher Leute abschreckt. Manchmal ist weniger mehr.

              In einem Tutorial für Fortgeschrittene kann ich mir dieses Thema gut vorstellen. Aber, … haben wir ein solches überhaupt und, wenn nicht, wollten wir eines haben [1]?

              Tschö, Auge

              --
              „Habe ich mir das nur eingebildet, oder kann der kleine Hund wirklich sprechen?“ fragte Schnapper. „Er behauptet, nicht dazu imstande zu sein“ erwiderte Victor. Schnapper zögerte (…) „Nun …“ sagte er schließlich, „ich schätze, er muss es am besten wissen.“ Terry Prattchett, Voll im Bilde

              1. Im Sinne von „Was kann da sonst noch drinstehen, was nicht schon im ‚normalen‘ Tutorial steht?“ ↩︎

            2. Hallo Gunnar,

              da hast Du recht, das muss man vorsichtig formulieren. Trotzdem kann ich mir vorstellen, dass auch Anfänger Schwierigkeiten damit haben, längere Selektoren richtig zu erstellen und nachzuvollziehen, wie der Browser sie interpretiert.

              Der "von vorn nach hinten" Ansatz führt - wie bei mir erlebt - zur Verwirrung.

              Wo ich das einbaue, muss ich noch schauen.

              Rolf

              --
              sumpsi - posui - obstruxi