Val av föräldraelement med CSS och jQuery

Det har varit tillfällen där jag har önskat att jag kunde välja ett föräldraelement med CSS-och jag är inte ensam i den här frågan. Det finns emellertid inte sånt som a Parent Selector i CSS, så det är helt enkelt inte möjligt för tillfället.

I denna handledning kommer vi att gå igenom några fall där det kan vara bra att ha en CSS-förälderväljare tillsammans med några möjliga lösningar. Låt oss börja!

Vänta, vad är en föräldraväljare?

CSS-väljare tillåter oss att rikta in element, flytta ner och över DOM-trädet, bli mer specifika när vi gör det. Här är ett exempel på vilken typ av väljare du kan hitta i Bootstrap-den reser ner DOM-trädet från nav.navbar-mörker element till ul, de li, då äntligen a.nav-länk.

.navbar-dark. navbar-nav. nav-item. nav-link 

 En förälderväljare ger oss möjlighet att resa tillbaka upp DOM, riktade mot överordnade element i vissa saker. Vi skulle till exempel kunna rikta in mot föräldern till .nav-länk element genom att använda:

.nav-länk :: förälder 

Notera: detta exempel är ren pseudokod, den existerar inte eller föreslår den bästa möjliga syntaxen!

Fall 1: Styling Legacy Content

Styling äldre innehåll, med daterad markup och struktur, är en klassisk utmaning när du redesigner en webbplats. Innan HTML5, till exempel, kan en bild typiskt ha blivit inslaget med en p, div, eller ibland med a spänna tillsammans med en kapslad p brukade vikla bildtexten. Det fanns inget vanligt sätt att paketera en bild och bildtext. Senare antog vi figur och figcaption element, vilket gör vår dokumentstruktur mer semantisk.

Vi vill att bilderna från det äldre innehållet ska visas som ovan. Men eftersom det kan finnas mer div taggar i vårt dokument, de som inte innehåller bilder alls, skulle följande stildeklarationer vara helt opraktiska.

.sidinnehåll div padding: 15px; bakgrundsfärg: # f3f3f3; marginal: 10px 0 20px;  .sida-innehåll div img marging: 0 0 10px;  .sida-innehåll div.img-caption color: # 999; fontstorlek: 12px; text-align: center; Wisplay: block; 

Det skulle applicera bakgrundsfärgen, vadderingen och marginalerna till alla div-element i innehållet. Vi vill faktiskt tillämpa dessa stilar uteslutande på div element som wrap en bild och en bildtextion.

Fall 2: Underhålla videoförhållande

Ett annat exempel ser på att upprätthålla inbäddad video (som från Youtube eller Vimeo), såväl som att göra videovätska. Dessa dagar, till stor del tack vare utredningsarbetet av Dave Rupert och pals, är det allmänt accepterat att det bästa sättet är att tillämpa padding-top eller padding-botten till moderelementet.

Kod snippet från CSS-tricks: Vätska bredd video

I en verklig värld kan vi dock inte veta vilket element som innehåller videon. Vi kan hitta några inbäddade videor insvept inom en div eller a p utan ett identifierbart klassnamn, vilket gör det svårt att välja rätt element för att tillämpa stilar. 

Därför är det igen opraktiskt att deklarera stilar enligt följande, eftersom det kommer att påverka alla delarna inom .page-innehåll inklusive de som inte innehåller en inbäddad video.

.sidinnehåll bredd: 560px; marginal-höger: auto; marginal-vänster: auto; marginal-topp: 30px;  .page-content div position: relative; padding-bottom: 56,25%;  .page-content div iframe position: absolute; topp: 0; bredd: 100%; höjd: 100%; 

Hur underbart det är att direkt välja videoens grundelement!

Fall 3: Svar på formulärinmatning

I det här exemplet har vi en form med flera ingångar. När vi fokuserar på en av ingångarna får den en mer framträdande gränsvärde, som markerar användarens position i formuläret.

Ibland kan du också stöta på situationen där inte bara gränsvärgen, men elementet som inmatar inmatningen är markerat, vilket gör ingången ännu mer framträdande:

Inmatningsform fokus.

Moderelementet kan vara a div eller a p. Så, hur kan vi väl välja föräldraelementet baserat på vissa stater av sina efterkommande?

Möjliga lösningar

Som vi har täckt finns det ingen sådan sak som en förälderväljare, så att välja en förälder är inte möjligt. Vi kanske frestas att undanröja problemet genom att helt ompröva designen så att val av förälder undviks. Men om det inte är möjligt så är det här några potentiella tillvägagångssätt.

Använda CSS : Har () Väljare 

De : har väljaren kallas officiellt som relationell pseudoklass. Den matchar element baserat på deras efterkommande, vilka definieras mellan parenteserna. 

I följande exempel gäller det a bakgrundsfärg till någon div innehållande en bildtextning. Detta hänvisar till synes fall 1.

.sidinnehåll div: har (.img-caption) padding: 15px; bakgrundsfärg: #ccc; 

Eller om vi vill vara mer specifika kan vi skriva om det för att matcha alla div tagga med .img-bildtext som den direkt ättling.

.sidinnehåll div: har (> .img-caption) padding: 15px; bakgrundsfärg: #ccc; 

Denna väljare är utarbetad för CSS Selector Level 4, men ingen webbläsare implementerar den än. Vi måste vänta lite längre innan den här väljaren kommer fram. Fram till dess, ta en titt på följande videokurs med titeln CSS of the Future för att få reda på hur väljaren fungerar:

  • Den: har pseudoklass
  • Kombinera: har och: inte

Använda jQuery Parent Selector

Ingen enda CSS-lösning kan fixa våra problem här, så låt oss se vad JavaScript kan göra för oss istället. I det här exemplet kommer vi att använda jQuery för dess robusta API, bekvämlighet och webbläsarkompatibilitet. Vid skrivningstillfället tillhandahåller jQuery tre metoder för att välja överordnade element.

förälder(); den här metoden väljer den omedelbara föräldern för det inriktade elementet. Vi kan utnyttja denna metod för att ta itu med alla våra användningsfall som nämnts tidigare i handledningen.

Bildstruktur i äldre innehåll.

Till exempel kan vi använda förälder() att lägga till en specialklass till omslaget av bilderna i innehållet.

$ (".img-caption") .parent () .addClass ("har-img-caption"); 

Ovanstående kod kommer att välja det omedelbara elementet som omsluter bilden, oavsett elementtyp, lägger till har-img-bildtext klass för att ge oss mer kontroll över elementvalet och stilerna, enligt följande.

Bildstruktur i äldre innehåll med en extra klass.

föräldrar() notera pluralformen av denna metod. Med den här metoden kan vi välja överordnade element från omedelbar, upp till roten i dokumentet, såvida inte a väljare anges som argumentet.

$ (".img-caption") .parents () .addClass ("har-img-caption"); 

Med tanke på ovanstående exempel, föräldrar() Metoden väljer hela vägen från div tagg som omedelbart sveper bilden, nästa div, och slutligen html, lägger till har-img-bildtext klass till alla delar.

Klassen has-img-caption tillämpas med metoden parents ().

Sådan överkill är överflödig. Det enda elementet som sannolikt kommer att behöva få klassen tillagt, är i detta fall den omedelbara div element. Därför överför vi det i metodargumentet.

$ (".img-caption") .parents ("div") .addClass ("har-img-caption"); 

Här, den föräldrar() Metoden kommer att resa genom förfader träd av bilden, välja någon div hittade och ge den har-image-caption klass.

Om det fortfarande är överdrivet kan du begränsa valet till ett enda element genom att ange indexet. I följande exempel tillämpar vi endast klassen på den första div.

var $ föräldrar = $ (".caption") .parents ("div"); $ föräldrar [0] .addClass ("har-img-caption"); // välj den första div add lägg till klassen. 

parentsUntil (); den här metoden väljer moderelementen upp till men inte inklusive det element som anges i parenteserna.

$ (".caption") .parentsUntil (".page-content") .addClass ("har-img-caption"); 

Med ovanstående kod kommer det att tillämpas har-img-bildtext klass till alla moderelementen förutom elementet med .page-innehåll.

I vissa fall, där du har gazillion-kapslade element, använder du parentsUntil () Metoden är att föredra. Det är jämförbart snabbare än föräldrar() metod eftersom det undviker att använda jQuery-väljarmotorn (Sizzle) för att resa över hela DOM-trädet upp till dokumentrotten.

Avslutar

Kommer vi sannolikt att ha en CSS Parent Selector vid någon tidpunkt i framtiden?

Antagligen inte. Den typ av förälderväljare som vi har diskuterat ovan har föreslagits flera gånger, men den har aldrig gått igenom W3C-utkastet av flera anledningar. Dessa anledningar fokuserar i stor utsträckning på webbläsarens prestanda på grund av hur webbläsare utvärderar och gör sidor. Det närmaste som vi kommer att ha i framtiden är relationsväljaren, : Har ().

Men sedan : Har () är ännu inte tillämpligt, JavaScript och jQuery är för närvarande det mest pålitliga tillvägagångssättet. Tänk på att DOM Traversal är en kostsam operation som kan påverka din webbplatss prestationsförmåga väldigt. Undvik att använda föräldrar() eller parentsUntil () med andra tunga operationer som animera(), FadeIn () eller tona ut()

Bättre än, undersök HTML-strukturen när det är möjligt för att se om valet av moderelementet kan undvikas helt!

Ytterligare resurser

  • CSS nivå 4 väljare för att se upp för
  • CSS-väljare för: förälderinriktning (tack)
  • Varför vi inte har en förälderväljare