Is er een CSS-ouderkiezer?

Hoe selecteer ik het <li>element dat een direct bovenliggend element is van het ankerelement?

Als voorbeeld zou mijn CSS er ongeveer zo uit zien:

li < a.active {
    property: value;
}

Natuurlijk zijn er manieren om dit met JavaScript te doen, maar ik hoop dat er een soort van tijdelijke oplossing is die native is voor CSS Level 2.

Het menu dat ik probeer te stylen wordt uitgespuwd door een CMS, dus ik kan het actieve element niet verplaatsen naar het <li>element… (tenzij ik het thema menu creatie module die ik liever niet doe).

Enig idee?


Antwoord 1, autoriteit 100%

Er is momenteel geen manier om het bovenliggende element van een element in CSS te selecteren.

Als er een manier was om het te doen, zou het in een van de huidige specificaties van CSS-selectors zijn:

Dat gezegd hebbende, het werkconcept van niveau 4 voor selectorsbevat een :has()pseudo-klasse die deze mogelijkheid zal bieden. Het zal vergelijkbaar zijn met de jQuery-implementatie.

li:has(> a.active) { /* styles to apply to the li tag */ }

Vanaf 2021 dit wordt echter nog steeds door geen enkele browser ondersteund.

In de tussentijd moet je JavaScript gebruiken als je een bovenliggend element moet selecteren.


Antwoord 2, autoriteit 7%

Ja: :has()

Browserondersteuning: geen


Antwoord 3, autoriteit 6%

Ik denk niet dat je de ouder alleen in CSS kunt selecteren.

Maar aangezien u al een klasse .activelijkt te hebben, zou het gemakkelijker zijn om die klasse te verplaatsen naar de li(in plaats van de a). Op die manier heb je alleen via CSS toegang tot zowel de lials de a.


Antwoord 4, autoriteit 5%

Je kunt dit scriptgebruiken:

*! > input[type=text] { background: #000; }

Hiermee wordt elke ouder van een tekstinvoer geselecteerd. Maar wacht, er is nog veel meer. Als je wilt, kun je een opgegeven ouder selecteren:

.input-wrap! > input[type=text] { background: #000; }

Of selecteer het wanneer het actief is:

.input-wrap! > input[type=text]:focus { background: #000; }

Bekijk deze HTML:

<div class="input-wrap">
    <input type="text" class="Name"/>
    <span class="help hide">Your name sir</span>
</div>

U kunt die span.helpselecteren wanneer de inputactief is en deze tonen:

.input-wrap! .help > input[type=text]:focus { display: block; }

Er zijn nog veel meer mogelijkheden; bekijk gewoon de documentatie van de plug-in.

BTW, het werkt in Internet Explorer.


Antwoord 5, autoriteit 4%

Zoals al door een aantal anderen vermeld, is er geen manier om de ouder(s) van een element op te maken met alleen CSS, maar het volgende werkt met jQuery:

$("a.active").parents('li').css("property", "value");

Antwoord 6, autoriteit 3%

Er is geen bovenliggende selector; net zoals er geen eerdere broer of zus-selector is. Een goede reden om deze selectors niet te hebben, is dat de browser alle onderliggende elementen van een element moet doorlopen om te bepalen of een klasse wel of niet moet worden toegepast. Als je bijvoorbeeld schreef:

body:contains-selector(a.active) { background: red; }

Vervolgens zal de browser moeten wachten totdat alles is geladen en geparseerd tot de </body>om te bepalen of de pagina rood moet zijn of niet.

Het artikel Waarom we geen ouderselector hebbenlegt het in detail uit.


Antwoord 7, autoriteit 2%

Er is geen manier om dit te doen in CSS 2. U kunt de klasse toevoegen aan de lien verwijzen naar de a:

li.active > a {
    property: value;
}

Antwoord 8

Probeer aom te schakelen naar de weergave blocken gebruik vervolgens elke gewenste stijl. Het a-element vult het li-element en u kunt het uiterlijk naar wens aanpassen. Vergeet niet om liopvulling in te stellen op 0.

li {
  padding: 0;
  overflow: hidden;
}
a {
  display: block;
  width: 100%;
  color: ..., background: ..., border-radius: ..., etc...
}
a.active {
  color: ..., background: ...
}

Antwoord 9

Met het pseudo-element :focus-withinkan een ouder worden geselecteerd als een afstammeling focus heeft.

Een element kan worden gefocust als het een tabindex-attribuut heeft.

Browserondersteuning voor focus-within

Tabindex

Voorbeeld

.click {
  cursor: pointer;
}
.color:focus-within .change {
  color: red;
}
.color:focus-within p {
  outline: 0;
}
<div class="color">
  <p class="change" tabindex="0">
    I will change color
  </p>
  <p class="click" tabindex="1">
    Click me
  </p>
</div>

Antwoord 10

De CSS-selector “Algemene Sibling Combinator” zou misschien gebruikt voor wat je wilt:

E ~ F {
    property: value;
}

Dit komt overeen met elk F-element dat wordt voorafgegaan door een E-element.


Antwoord 11

Voor zover ik weet niet in CSS 2. CSS 3 heeft robuustere selectors, maar wordt niet consequent in alle browsers geïmplementeerd. Zelfs met de verbeterde selectors geloof ik niet dat het precies zal bereiken wat je in je voorbeeld hebt gespecificeerd.


Antwoord 12

Ik weet dat de OP op zoek was naar een CSS-oplossing, maar het is eenvoudig te bereiken met jQuery. In mijn geval moest ik de bovenliggende tag <ul>vinden voor een <span>-tag in de onderliggende <li>. jQuery heeft de :hasselector, dus het is mogelijk om een ouder te identificeren aan de hand van de kinderen die het bevat:

$("ul:has(#someId)")

selecteert het ulelement dat een onderliggend element heeft met id someId. Of om de oorspronkelijke vraag te beantwoorden, iets als het volgende zou het lukken (niet getest):

$("li:has(.active)")

Antwoord 13

Dit is het meest besproken aspect van de specificatie Selectors Level 4.
Hiermee kan een selector een element stylen volgens zijn kind door een uitroepteken te gebruiken na de gegeven selector (!).

Bijvoorbeeld:

body! a:hover{
   background: red;
}

zal een rode achtergrondkleur instellen als de gebruiker over een anker zweeft.

Maar we moeten wachten op de implementatie van browsers 🙁


Antwoord 14

Je zou kunnen proberen om de hyperlink als bovenliggend element te gebruiken, en dan de binnenste elementen bij het aanwijzen te veranderen. Zoals dit:

a.active h1 {color:red;}
a.active:hover h1 {color:green;}
a.active h2 {color:blue;}
a.active:hover h1 {color:yellow;}

Op deze manier kun je de stijl in meerdere binnentags wijzigen, gebaseerd op de rollover van het bovenliggende element.


Antwoord 15

Hier is een hack met behulp van pointer-eventsmet hover:

<!doctype html>
<html>
    <head>
        <title></title>
        <style>
/* accessory */
.parent {
    width: 200px;
    height: 200px;
    background: gray;
}
.parent, 
.selector {
    display: flex;
    justify-content: center;
    align-items: center;
}
.selector {
    cursor: pointer;
    background: silver;
    width: 50%;
    height: 50%;
}
        </style>
        <style>
/* pertinent */
.parent {
    background: gray;
    pointer-events: none;
}
.parent:hover {
    background: fuchsia;
}
.parent 
.selector {
    pointer-events: auto;
}
        </style>
    </head>
    <body>
        <div class="parent">
            <div class="selector"></div>
        </div>
    </body>
</html>

Antwoord 16

Gewoon een idee voor een horizontaal menu…

Onderdeel van HTML

<div class='list'>
  <div class='item'>
    <a>Link</a>
  </div>
  <div class='parent-background'></div>
  <!-- submenu takes this place -->
</div>

Onderdeel van CSS

/* Hide parent backgrounds... */
.parent-background {
  display: none; }
/* ... and show it when hover on children */
.item:hover + .parent-background {
  display: block;
  position: absolute;
  z-index: 10;
  top: 0;
  width: 100%; }

Bijgewerkte demo en de rest van de code

Een ander voorbeeldhoe het te gebruiken met tekstinvoer – selecteer bovenliggende veldset


Antwoord 17

Momenteel is er geen ouderselector & het wordt zelfs niet besproken in een van de gesprekken van W3C. U moet begrijpen hoe CSS door de browser wordt geëvalueerd om daadwerkelijk te begrijpen of we het nodig hebben of niet.

Er is hier veel technische uitleg.

Jonathan Snook legt uit hoe CSS wordt geëvalueerd.

Chris Coyier over de gesprekken van Parent selector.

Harry Roberts nogmaals over het schrijven van efficiënte CSS-selectors.

Maar Nicole Sullivan heeft enkele interessante feiten op positieve trends.

Deze mensen zijn allemaal van topklasse op het gebied van front-end ontwikkeling.


Antwoord 18

Er is een plug-in die CSS uitbreidt met enkele niet-standaard functies die echt kunnen helpen bij het ontwerpen van websites. Het heet EQCSS.

Een van de dingen die EQCSS toevoegt, is een bovenliggende selector. Het werkt in alle browsers, Internet Explorer 8 en hoger. Dit is het formaat:

@element 'a.active' {
  $parent {
    background: red;
  }
}

Dus hier hebben we een elementquery geopend voor elk element a.active, en voor de stijlen binnen die query zijn dingen als $parentlogisch, omdat er een referentiepunt. De browser kan de ouder vinden, omdat deze erg lijkt op parentNodein JavaScript.

Hier is een demo van $parenten nog een $parentdemo die werkt in Internet Explorer 8, evenals een screenshot voor het geval je geen Internet Explorer 8 hebt om mee te testen.

EQCSS bevat ook meta-selectors: $prevvoor de element voor een geselecteerd element en $thisvoor alleen die elementen die overeenkomen met een elementquery, en meer.


Antwoord 19

Het is nu 2019 en de nieuwste versie van de CSS Nesting Moduleheeft eigenlijk iets zoals dit. Introductie van @nestat-rules.

3.2. De regel voor nesten: @nest

Hoewel direct nesten er mooi uitziet, is het enigszins kwetsbaar. Sommige geldige nesting selectors, zoals .foo &, zijn niet toegestaan, en het op bepaalde manieren bewerken van de selector kan de regel onverwacht ongeldig maken. Sommige mensen vinden het nesten ook een uitdaging om visueel te onderscheiden van de omringende verklaringen.

Om bij al deze problemen te helpen, definieert deze specificatie de @nest-regel, die minder beperkingen oplegt aan het geldig nesten van stijlregels. De syntaxis is:

@nest = @nest <selector> { <declaration-list> }

De @nest-regel werkt op dezelfde manier als een stijlregel: hij begint met een selector en bevat declaraties die van toepassing zijn op de elementen waarmee de selector overeenkomt. Het enige verschil is dat de selector die in een @nest-regel wordt gebruikt, nest-bevattend moet zijn, wat betekent dat er ergens een nesting selector in zit. Een lijst met selectors is nest-bevattend als alle individuele complexe selectors nest-bevattend zijn.

(Kopieer en plak van de bovenstaande URL).

Voorbeeld van geldige selectors onder deze specificatie:

.foo {
  color: red;
  @nest & > .bar {
    color: blue;
  }
}
/* Equivalent to:
   .foo { color: red; }
   .foo > .bar { color: blue; }
 */
.foo {
  color: red;
  @nest .parent & {
    color: blue;
  }
}
/* Equivalent to:
   .foo { color: red; }
   .parent .foo { color: blue; }
 */
.foo {
  color: red;
  @nest :not(&) {
    color: blue;
  }
}
/* Equivalent to:
   .foo { color: red; }
   :not(.foo) { color: blue; }
 */

Antwoord 20

Technisch is er geen directe manier om dit te doen. U kunt dat echter oplossen met jQuery of JavaScript.

U kunt echter ook zoiets doen.

a.active h1 {color: blue;}
a.active p {color: green;}

jQuery

$("a.active").parents('li').css("property", "value");

Als u dit wilt bereiken met jQuery, vindt u hier de referentie voor de jQuery parent-selector .


Antwoord 21

Het korte antwoord is NEE; we hebben op dit moment geen parent selectorin CSS, maar als je de elementen of klassen toch niet hoeft te verwisselen, is de tweede optie het gebruik van JavaScript. Zoiets als dit:

var activeATag = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {
  if(x.parentNode.tagName === 'LI') {
    x.parentNode.style.color = 'red'; // Your property: value;
  }
});

Of een kortere manier als u jQuerygebruikt in uw toepassing:

$('a.active').parents('li').css('color', 'red'); // Your property: value;

Antwoord 22

Het W3C sloot een dergelijke selector uit vanwege de enorme prestatie-impact die het zou hebben op een browser.


Antwoord 23

Enig idee?

CSS4 zal mooi zijn als het wat hakentoevoegt aan achteruit lopen. Tot die tijd is het mogelijk (hoewel nietaan te raden) om checkboxen/of radioinputs te gebruiken om de gebruikelijke manier waarop dingen met elkaar zijn verbonden te verbreken, en daardoor ook CSS in staat te stellen buiten zijn normale bereik te werken…

/* Hide things that may be latter shown */
.menu__checkbox__selection,
.menu__checkbox__style,
.menu__hidden {
  display: none;
  visibility: hidden;
  opacity: 0;
  filter: alpha(opacity=0); /* Old Microsoft opacity */
}
/* Base style for content and style menu */
.main__content {
  background-color: lightgray;
  color: black;
}
.menu__hidden {
  background-color: black;
  color: lightgray;
  /* Make list look not so _listy_ */
  list-style: none;
  padding-left: 5px;
}
.menu__option {
  box-sizing: content-box;
  display: block;
  position: static;
  z-index: auto;
}
/* &#9660; - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
  content: '\2630';
  display: inline-block;
}
*/
/* &#9660; - Down Arrow */
.menu__trigger__selection::after {
  content: "\25BC";
  display: inline-block;
  transform: rotate(90deg);
}
/* Customize to look more `select` like if you like */
.menu__trigger__style:hover,
.menu__trigger__style:active {
  cursor: pointer;
  background-color: darkgray;
  color: white;
}
/**
 * Things to do when checkboxes/radios are checked
 */
.menu__checkbox__selection:checked + .menu__trigger__selection::after,
.menu__checkbox__selection[checked] + .menu__trigger__selection::after {
  transform: rotate(0deg);
}
/* This bit is something that you may see elsewhere */
.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
  display: block;
  visibility: visible;
  opacity: 1;
  filter: alpha(opacity=100); /* Microsoft!? */
}
/**
 * Hacky CSS only changes based off non-inline checkboxes
 * ... AKA the stuff you cannot unsee after this...
 */
.menu__checkbox__style[id="style-default"]:checked ~ .main__content {
  background-color: lightgray;
  color: black;
}
.menu__checkbox__style[id="style-default"]:checked ~ .main__content .menu__trigger__style[for="style-default"] {
  color: darkorange;
}
.menu__checkbox__style[id="style-one"]:checked ~ .main__content {
  background-color: black;
  color: lightgray;
}
.menu__checkbox__style[id="style-one"]:checked ~ .main__content .menu__trigger__style[for="style-one"] {
  color: darkorange;
}
.menu__checkbox__style[id="style-two"]:checked ~ .main__content {
  background-color: darkgreen;
  color: red;
}
.menu__checkbox__style[id="style-two"]:checked ~ .main__content .menu__trigger__style[for="style-two"] {
  color: darkorange;
}
<!--
  This bit works, but will one day cause troubles,
  but truth is you can stick checkbox/radio inputs
  just about anywhere and then call them by id with
  a `for` label. Keep scrolling to see what I mean
-->
<input type="radio"
       name="colorize"
       class="menu__checkbox__style"
       id="style-default">
<input type="radio"
       name="colorize"
       class="menu__checkbox__style"
       id="style-one">
<input type="radio"
       name="colorize"
       class="menu__checkbox__style"
       id="style-two">
<div class="main__content">
  <p class="paragraph__split">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
  </p>
  <input type="checkbox"
         class="menu__checkbox__selection"
         id="trigger-style-menu">
  <label for="trigger-style-menu"
         class="menu__trigger__selection"> Theme</label>
  <ul class="menu__hidden">
    <li class="menu__option">
      <label for="style-default"
             class="menu__trigger__style">Default Style</label>
    </li>
    <li class="menu__option">
      <label for="style-one"
             class="menu__trigger__style">First Alternative Style</label>
    </li>
    <li class="menu__option">
      <label for="style-two"
             class="menu__trigger__style">Second Alternative Style</label>
    </li>
  </ul>
  <p class="paragraph__split">
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</div>

Antwoord 24

Hoewel er momenteel geen bovenliggende selector in standaard CSS is, werk ik aan een (persoonlijk) project genaamd axe(dwz Augmented CSS Selector Syntax / ACSSSS) die, onder de 7 nieuwe selectors, beide omvat:

  1. een directe bovenliggendeselector <(die de tegenovergestelde selectie van >mogelijk maakt)
  2. een elke voorouderselector^(die de tegenovergestelde selectie van [SPACE]mogelijk maakt)

axebevindt zich momenteel in een relatief vroege BETA-fase van ontwikkeling.

Bekijk hier een demo:

.parent {
  float: left;
  width: 180px;
  height: 180px;
  margin-right: 12px;
  background-color: rgb(191, 191, 191);
}
.child {
  width: 90px;
  height: 90px;
  margin: 45px;
  background-color: rgb(255, 255, 0);
}
.child.using-axe < .parent {
  background-color: rgb(255, 0, 0);
}
<div class="parent">
  <div class="child"></div>
</div>
<div class="parent">
  <div class="child using-axe"></div>
</div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>

Antwoord 25

In ieder geval tot en met CSS 3 kun je zo niet selecteren.
Maar het kan tegenwoordig vrij eenvoudig worden gedaan in JavaScript, je hoeft alleen een beetje vanille JavaScript toe te voegen, merk op dat de code vrij kort is.

cells = document.querySelectorAll('div');
[].forEach.call(cells, function (el) {
    //console.log(el.nodeName)
    if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
        console.log(el)
    };
});
<div>Peter</div>
<div><a href="#">Jackson link</a></div>
<div>Philip</div>
<div><a href="#">Pullman link</a></div>

Antwoord 26

Nee, je kunt de ouder niet alleen in CSS selecteren.

Maar aangezien u al een klasse .activelijkt te hebben, zou het gemakkelijker zijn om die klasse te verplaatsen naar de li(in plaats van de a). Op die manier heb je alleen via CSS toegang tot zowel de lials de a.


Antwoord 27

Er is geen css (en dus in css-preprocessors) bovenliggende selector vanwege “De belangrijkste redenen waarom de CSS-werkgroep eerder voorstellen voor bovenliggende selectors afwees, houden verband met browserprestaties en problemen met incrementele weergave.”


Antwoord 28

Het wijzigen van het bovenliggende element op basis van het onderliggende element kan momenteel alleen gebeuren als we een <input>element in het bovenliggende element hebben. Wanneer een invoer focus krijgt, kan het bijbehorende bovenliggende element worden beïnvloed door CSS.

Het volgende voorbeeld helpt je het gebruik van :focus-withinin CSS te begrijpen.

.outer-div {
  width: 400px;
  height: 400px;
  padding: 50px;
  float: left
}
.outer-div:focus-within {
  background: red;
}
.inner-div {
  width: 200px;
  height: 200px;
  float: left;
  background: yellow;
  padding: 50px;
}
<div class="outer-div">
  <div class="inner-div">
    I want to change outer-div(Background color) class based on inner-div. Is it possible?
    <input type="text" placeholder="Name" />
  </div>
</div>

Antwoord 29

Ik zou wat JavaScript-code inhuren om dat te doen. Als u bijvoorbeeld in Reageren een array herhaalt, voegt u een andere klasse toe aan de bovenliggende component, die aangeeft dat deze uw kinderen bevat:

<div className={`parent ${hasKiddos ? 'has-kiddos' : ''}`}>
    {kiddos.map(kid => <div key={kid.id} />)}
</div>

En dan gewoon:

.parent {
    color: #000;
}
.parent.has-kiddos {
    color: red;
}

Antwoord 30

Probeer dit…

Deze oplossing gebruikt gewone CSS2-regels zonder Javascript en werkt in alle browsers, oude en nieuwe. Wanneer erop wordt geklikt, activeert de onderliggende anchor-tag zijn activepseudo-klassegebeurtenis. Het verbergt zichzelf dan gewoon, waardoor de active-gebeurtenis kan opborrelen naar de bovenliggende li-tag, die vervolgens zichzelf restylet en zijn ankerkind opnieuw onthult met een nieuwe stijl. Het kind heeft de ouder gestyled.

Uw voorbeeld gebruiken:

<ul>
    <li class="listitem">
        <a class="link" href="#">This is a Link</a>
    </li>
</ul>

Pas deze stijlen nu toe met de activepseudo-klasse op aom de bovenliggende li-tag opnieuw op te maken wanneer op de link wordt geklikt:

p>

a.link {
    display: inline-block;
    color: white;
    background-color: green;
    text-decoration: none;
    padding: 5px;
}
li.listitem {
    display: inline-block;
    margin: 0;
    padding: 0;
    background-color: transparent;
}
/* When this 'active' pseudo-class event below fires on click, it hides itself,
triggering the active event again on its parent which applies new styles to itself and its child. */
a.link:active {
    display: none;
}
.listitem:active {
    background-color: blue;
}
.listitem:active a.link {
    display: inline-block;
    background-color: transparent;
}

Je zou moeten zien dat de link met een groene achtergrond nu verandert in de blauwe achtergrond van het lijstitem als je erop klikt.

voer hier de afbeeldingsbeschrijving in

gaat over naar

voer hier de afbeeldingsbeschrijving in

op klik.

Other episodes