Zastosuj style CSS do elementu w zależności od jego elementów potomnych

203

Czy można zdefiniować styl CSS dla elementu, który jest stosowany tylko wtedy, gdy dopasowany element zawiera określony element (jako bezpośredni element potomny)?

Myślę, że najlepiej to wyjaśnić na przykładzie.

Uwaga : staram się stylizować element nadrzędny , w zależności od tego, jakie elementy potomne zawiera.

<style>
  /* note this is invalid syntax. I'm using the non-existing
   ":containing" pseudo-class to show what I want to achieve. */
  div:containing div.a { border: solid 3px red; }
  div:containing div.b { border: solid 3px blue; }
</style>

<!-- the following div should have a red border because
     if contains a div with class="a" -->
<div>
  <div class="a"></div>
</div>

<!-- the following div should have a blue border -->
<div>
  <div class="b"></div>
</div>

Uwaga 2 : Wiem, że mogę to osiągnąć za pomocą javascript, ale zastanawiałem się, czy jest to możliwe przy użyciu nieznanych (dla mnie) funkcji CSS.

M4N
źródło
1
Możesz zaktualizować pytanie, aby oświadczyć, być może z migającym pogrubionym tekstem, że próbujesz stylizować DODATKOWEGO diva, a nie jego dzieci. Wiem, że informacje są w samym pytaniu, ale chyba, że ​​chcesz uzyskać mnóstwo niepoprawnych odpowiedzi, prawdopodobnie warto.
Seth Petry-Johnson
Dzięki @Seth. Próbowałem poprawić tytuł i tekst pytania. Edytuj pytanie, jeśli uważasz, że nadal jest niejasne.
M4N
3
możliwy duplikat Czy istnieje selektor nadrzędny CSS?
James Donnelly,
Jest to idealny przykład tego, dlaczego ten rodzaj wsparcia w CSS byłby idealny: ol < li:nth-child(n+10) { margin-left: 2rem; } ol < li:nth-child(n+100) { margin-left: 3rem; } ol < li:nth-child(n+1000) { margin-left: 4rem; }w idealnym świecie zwiększyłoby to margines olzależny od liczby lizawartych w nim dzieci, tak że margines po lewej stronie byłby tak szeroki, jak to tylko możliwe. musiał być.
Jonmark Weber,

Odpowiedzi:

124

O ile mi wiadomo, stylowanie elementu nadrzędnego na podstawie elementu podrzędnego nie jest dostępną funkcją CSS. Prawdopodobnie będziesz potrzebować do tego skryptu.

Byłoby wspaniale, gdybyś mógł zrobić coś takiego div[div.a]lub div:containing[div.a]jak powiedziałeś, ale nie jest to możliwe.

Możesz rozważyć spojrzenie na jQuery . Jego selektory działają bardzo dobrze z typami „zawierającymi”. Możesz wybrać div, na podstawie jego zawartości potomnej, a następnie zastosować klasę CSS do elementu nadrzędnego w jednym wierszu.

Jeśli użyjesz jQuery, coś w tym stylu może działać (niesprawdzone, ale teoria istnieje):

$('div:has(div.a)').css('border', '1px solid red');

lub

$('div:has(div.a)').addClass('redBorder');

w połączeniu z klasą CSS:

.redBorder
{
    border: 1px solid red;
}

Oto dokumentacja selektora jQuery „ma” .

KP.
źródło
15
Uwaga dodatkowa: dla lepszej wydajności strona dokumentu jQuery dla :hasselektora zaleca użycie .has()metody ( api.jquery.com/has ) => zastosowanej do bieżącego pytania, które dałoby na przykład$('div').has('div.a').css('border', '1px solid red');
Frosty Z
Aby to zadziałało, należałoby użyć obserwatora mutacji, aby sprawdzić, czy dziecko zmieniło swój stan ...
Legends
To tak naprawdę nie odpowiada na pytanie, które brzmi: „Czy można to zrobić za pomocą CSS”. Wyraźnie stwierdza: „Wiem, że mogę to osiągnąć za pomocą javascript, ale po prostu zastanawiałem się, czy jest to możliwe przy użyciu nieznanych (dla mnie) funkcji CSS”.
SunshinyDoyle
developer.mozilla.org/en-US/docs/Web/CSS/:mas , myślę, że ten :hasselektor może działać, ale jest w wersji roboczej i żadna przeglądarka go nie obsługuje.
AliF50
62

Zasadniczo nie. Dodaje , że być to, czego szukali w teorii:

div.a < div { border: solid 3px red; }

Niestety nie istnieje.

Istnieje kilka opisów w stylu „dlaczego, do diabła, nie”. Dobrze rozwinięty Shaun Inman jest całkiem niezły:

http://www.shauninman.com/archive/2008/05/05/css_qualified_selectors

Justin Wignall
źródło
34
tylko aktualizacja 8 lat później: wciąż nie ma wsparcia dla tej metody wyboru.
Kraang Prime
1
Istnieje robocza wersja robocza tej funkcji w formie :has()pseudoklasy, ale będziemy mogli jej używać tylko w CSS4. Na dzień dzisiejszy (koniec 2019 r.) JS jest nadal jedynym sposobem na osiągnięcie tej funkcjonalności.
zepp.lee
Wierzę, że to nie włączy stylów css, nadal będzie potrzebował javascript, aby użyć selektora. Chyba że to się zmieniło?
Justin Wignall,
3
9 lat i czy uważają, że ta funkcja jest niepotrzebna?
Loi Nguyen Huynh
1

Oprócz odpowiedzi @ kp:

Mam do czynienia z tym iw moim przypadku muszę pokazać element potomny i odpowiednio skorygować wysokość obiektu nadrzędnego (automatyczne dostosowywanie nie działa w nagłówku bootstrap z jakiegoś powodu, dla którego nie mam czasu na debugowanie) .

Ale zamiast używać javascript do modyfikowania elementu nadrzędnego, myślę, że dynamicznie dodam klasę CSS do elementu nadrzędnego i odpowiednio wybiję elementy podrzędne przez CSS. Pozwoli to zachować decyzje w logice, a nie na podstawie stanu CSS.

tl; dr; zastosuj style ai bdo rodzica <div>, a nie dziecka (oczywiście nie każdy będzie w stanie to zrobić, tj. komponenty kątowe podejmujące własne decyzje).

<style>
  .parent            { height: 50px; }
  .parent div        { display: none; }
  .with-children     { height: 100px; }
  .with-children div { display: block; }
</style>

<div class="parent">
  <div>child</div>
</div>

<script>
  // to show the children
  $('.parent').addClass('with-children');
</script>
Mauricio Morales
źródło
0

W moim przypadku musiałem zmienić wypełnienie komórki elementu zawierającego pole wyboru danych wejściowych dla tabeli dynamicznie renderowanej za pomocą DataTables:

<td class="dt-center">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

Po zaimplementowaniu następującego kodu wiersza w ramach funkcji initComplete byłem w stanie wyprodukować poprawne wypełnienie, które naprawiło wyświetlanie wierszy o nienormalnie dużej wysokości

 $('tbody td:has(input.a)').css('padding', '0px');

Teraz możesz zobaczyć, że poprawne style są stosowane do elementu nadrzędnego:

<td class=" dt-center" style="padding: 0px;">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

Zasadniczo ta odpowiedź jest rozszerzeniem odpowiedzi @ KP, ale im więcej współpracy przy wdrażaniu, tym lepiej. Podsumowując, mam nadzieję, że to pomoże komuś innemu, ponieważ działa! Na koniec dziękuję bardzo @KP za poprowadzenie mnie we właściwym kierunku!

mile
źródło