Selektor dla jednego tagu, po którym bezpośrednio następuje inny tag

88

Wybiera wszystkie <B>znaczniki bezpośrednio poprzedzone przez <A>tagi:

A+B {
    /* styling */
}

Jaki jest selektor dla wszystkich <A>tagów, po których bezpośrednio następują<B> tagi?

Oto przykładowy kod HTML pasujący do mojego pytania:

<a>some text</a>
<b>some text</b>
Mostafa Farghaly
źródło
3
Podaj nam przykład DOM, jak Ai Bsą powiązane.
Gumbo,
2
Są ze sobą powiązane w tym sensie, że są rodzeństwem, a po B następuje A. OP chce wybrać wszystkie bs, po których następuje as, podobnie jak w a+bprzypadku, gdy można wybrać wszystkie bs poprzedzone bezpośrednio przez a.
Anthony
Czy 2,5 roku później jest aktualizacja tej odpowiedzi? Szukam również celu a, po którym następuje b.
chovy

Odpowiedzi:

29

Nie możesz w css.

Edycja: Aby być nieco bardziej pomocnym, jeśli używasz na przykład jQuery (biblioteki JavaScript), możesz użyć .prev().

jeroen
źródło
wydaje się, że jedynym rozwiązaniem jest używanie JavaScript
Mostafa Farghaly
2
Dzięki jeroen! To rozwiązało mój problem. Ponieważ moje „A” pływa w lewo, a „B” w prawo, nie ma znaczenia, w jakiej kolejności
wstawię
53

Czy masz na myśli styl A, biorąc pod uwagę, że ma on element B bezpośrednio wewnątrz lub za nim? Lubię to:

<A>
    <B>
    </B>
</A>

// OR

<A>
</A>
<B>
</B>

Nie możesz (jeszcze) zrobić czegoś takiego w CSS. Eric Meyer stwierdza, że ​​ten rodzaj selektora był dyskutowany kilka razy na liście mailingowej CSS i nie jest wykonalny. Dave Hyatt, jeden z głównych programistów WebKit, komentuje z dobrym wyjaśnieniem, dlaczego nie można tego zrobić.

Zobacz: post na blogu Shauna Inmana i komentarz Erica Meyera .
David Hyatt też się liczy .

Nick Presta
źródło
mam na myśli ten drugi, rozumiem problem dziękuję nick :)
Mostafa Farghaly
17

Możesz TYLKO odwrotnie: Zaznacza to wszystkie tagi bezpośrednio poprzedzone tagami.

Jest to logicznie równoważne z twoją prośbą.

Często używam tego do stylizowania rzędu wielu pól wyboru z etykietami

CSS:

label+input {
    margin-left: 4px;
}

DOM:

<input id="a" name="a" type="checkbox"/><label for="a">...</label>
<input id="b" name="b" type="checkbox"/><label for="b">...</label>
<input id="c" name="c" type="checkbox"/><label for="c">...</label>
Marco Marsala
źródło
3
Myślę, że chciałeś wpisać „wejście + etykieta” w CSS, tak aby lewy margines został zastosowany do etykiety.
CAK2
1
@ CAK2 - Myślę, że miał to na myśli. Dzięki temu label+inputmargines jest stosowany do wszystkich inputelementów zaczynając od drugiego . To kreatywny sposób na stworzenie przestrzeni między nimi, ale nie na początku czy na końcu rzędu. W tym przypadku jest to odpowiednik input:not(:first-child).
David
1

Chociaż nie jest to zbyt przydatne, w dzisiejszych czasach można osiągnąć to zachowanie, odwracając kolejność elementów zarówno podczas generowania kodu HTML, jak i stosując reguły CSS: display: flexiflex-direction: column-reverse

ul {
  display: flex;
  flex-direction: column-reverse;
}

.b ~ .a {
  color: red;
}
<ul>
    <li class="a">A 3</li>
    <li class="c">C 2</li>
    <li class="c">C 1</li>
    <li class="b">B 1</li>
    <li class="a">A 2</li>
    <li class="a">A 1</li>
</ul>

Ponadto, jeśli masz 2 lub więcej elementów wbudowanych, możesz to osiągnąć, stosując float: right, ponieważ będą one wyświetlane w odwrotnej kolejności:

ul {
  float: left;
  list-style-type: none;
}

li {
  float: right;
}

li:not(:first-child) {
  margin-right: 20px;
}

.b ~ .a {
  color: red;
}
<ul>
    <li class="a">A 3</li>
    <li class="c">C 2</li>
    <li class="c">C 1</li>
    <li class="b">B 1</li>
    <li class="a">A 2</li>
    <li class="a">A 1</li>
</ul>

Mihai Matei
źródło