Skip to content

Alt om WordPress, webutvikling — og mer til

🎯 Selectors i Elementor-widgeter: komplett guide for utviklere

🎯 Selectors i Elementor-widgeter: komplett guide for utviklere

Hvorfor Elementor-utviklere trenger selektorer og hvordan de fungerer

Når en bruker justerer widget-innstillinger i editoren, forventer de en umiddelbar respons på skjermen. Uten selektorer måtte en utvikler skrevet en JS-handler for hvert felt som endres. Med selektorer løses alt med CSS.

Parameteren selectors (og dens mindre kjente motstykke selectors_dictionary) legges direkte inn i arrayet til add_control()-kallet. Elementor setter dynamisk inn verdier fra felter i CSS-regler og sender dem ut til postfilen, noe sånt som /wp-content/uploads/elementor/css/post-1234.css. Så snart brukeren forlater editoren, forsvinner inline-stiler, og etterlater ren, generert CSS.

💡 Rask oversikt:

  • Forstå selektorsyntaks og plassholdertabellen
  • Se konkrete eksempler for farge og størrelser
  • Lær å hente verdier fra tilstøtende kontroller
  • Mestre selectors_dictionary for erstatning av CSS-deklarasjoner
  • Legg puslespillet med CSS-variabler og skjulte kontroller

Hvor selektorer defineres

Når du oppretter en widget, aksepterer hvert add_control()-kall et innstillingsarray. Det er akkurat der selectors ligger. For gruppekontroller er syntaksen den samme, arrayet sendes inn i grupperegistreringen.

Grunnformat:

1'selectors' => [
2 '{{WRAPPER}} .my-widget-class' => 'color: {{VALUE}}',
3]

Nøkkelen er en CSS-selektor (starter med {{WRAPPER}} for å unngå å påvirke tilstøtende widgets på siden). Verdien er én eller flere CSS-deklarasjoner med dynamiske plassholdere. Elementor tar den aktuelle kontrollverdien og setter den inn i stedet for plassholderen.

Resultatet rendres til postens eksterne CSS-fil, stiler eksisterer bare mens editoren er åpen og umiddelbart etter lagring. Ikke noe inline-rot.

Tabell over variabler med krøllparenteser

Ingen magi, bare søk og erstatt. Men variasjonen av plassholdere åpner dører for ganske smarte konstruksjoner.

For selektorer (array-nøkkel)

Plassholder

Hva den erstatter

{{WRAPPER}}

Unik widget-instans-selektor, for eksempel .elementor-50 .elementor-element.elementor-element-092e113. Brukes nesten alltid

{{ID}}

Kun widget-ID-en (delen etter bindestreken, 092e113)

(desktop) / (tablet) / (mobile)

Begrenser regelen til den angitte enheten. Med + betyr det «fra denne oppløsningen og opp»: (tablet+) = nettbrett og bredere

{{CURRENT_ITEM}}

Aktivt element i en repeater-kontroll

For deklarasjoner (array-verdi)

Plassholder

Hva den erstatter

{{VALUE}}

Rå kontrollverdi. Kan overstyres av selectors_dictionary

{{SIZE}} og {{UNIT}}

Tall og måleenhet fra numeriske kontroller. Opptrer vanligvis i par: {{SIZE}}{{UNIT}}

{{TOP}} / {{LEFT}} / {{RIGHT}} / {{BOTTOM}}

Retninger fra dimensjonskontroll

{{URL}} eller annet navn

Tilgang til navngitt egenskap i sammensatte kontroller: for eksempel returnerer Media Control et array med feltene url id alt

{{other.SIZE}}

Verdi fra en annen kontroll etter ID. Suffiksene _tablet og _mobile gir responsive data

{{setting.SIZE \|\| 5}}

Fallback: hvis kontrollen er tom, settes 5 inn. Fungerer med strenger i anførselstegn og med en annen kontrolls DEFAULT

Enkle eksempler, fra farge til bakgrunnsbilde

Farge fra palett. Ikke noe ekstra:

1'selectors' => [
2 '{{WRAPPER}} .elementor-svg-divider-basic-text' => 'color: {{VALUE}}',
3],

Numerisk kontroll med og uten enhet. Den andre egenskapen (stroke-width) er bevisst uten {{UNIT}}, strektykkelse er i piksler, uten px:

1'selectors' => [
2 '{{WRAPPER}} svg.sde-classic' =>
3 'height: {{SIZE}}{{UNIT}}; stroke-width: {{SIZE}};',
4],

Avstand fra dimensjonskontroll, hver retning separat:

1'selectors' => [
2 '{{WRAPPER}} .elementor-svg-divider-basic-button' =>
3 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
4],

Bakgrunnsbilde av et lysbilde i repeater-kontroll:

1'selectors' => [
2 '{{WRAPPER}} {{CURRENT_ITEM}} .swiper-slide-bg' =>
3 'background-image: url({{URL}})',
4],

Betinget posisjon for RTL. Samme kontroll gir ulike egenskaper avhengig av tekstretning:

1'selectors' => [
2 'body:not(.rtl) {{WRAPPER}} .dialog-close-button' => 'right: {{SIZE}}{{UNIT}}',
3 'body.rtl {{WRAPPER}} .dialog-close-button' => 'left: {{SIZE}}{{UNIT}}',
4],

Hvordan hente en verdi fra en annen kontroll

Hvis to felter påvirker samme CSS, ikke dupliser arrayet, bare referer til den tilstøtende kontrollen:

1'selectors' => [
2 '{{WRAPPER}} svg.sde-classic' =>
3 'stroke-dasharray: {{dash_length.SIZE}} {{whitespace_length.SIZE}};',
4],

Her er dash_length og whitespace_length ID-er til andre kontroller i samme widget. Ingen ekstra kall, bare punktnotasjon.

Responsiv versjon, verdier hentes basert på enheten. Ekte eksempel fra Elementor Pro:

1'selectors' => [
2 '(desktop).elementor-msie {{WRAPPER}} .elementor-portfolio-item' =>
3 'width: calc( 100% / {{columns.SIZE}} ); border: {{SIZE}}px solid transparent',
4 '(tablet).elementor-msie {{WRAPPER}} .elementor-portfolio-item' =>
5 'width: calc( 100% / {{columns_tablet.SIZE}} ); border: {{SIZE}}px solid transparent',
6 '(mobile).elementor-msie {{WRAPPER}} .elementor-portfolio-item' =>
7 'width: calc( 100% / {{columns_mobile.SIZE}} ); border: {{SIZE}}px solid transparent',
8],

Hvert brytningspunkt får sin egen columns-verdi. De resterende egenskapene (border, SIZE) er felles, de er ikke knyttet til enheten.

Selectors_dictionary, switch-case for CSS

Den mest undervurderte egenskapen. selectors_dictionary erstatter {{VALUE}} med en hardkodet streng, og gjør i praksis kontrollverdien om til en ordboknøkkel.

Ta standardkontrollen for Justering med alternativene venstre/midt/høyre. Uten en ordbok ville du skrevet noe unaturlig:

1'selectors' => [
2 $sde_selector => 'margin: 0 auto; margin-{{VALUE}}: 0;',
3],

For center produserer dette margin: 0 auto; margin-center: 0;. Egenskapen margin-center finnes ikke, nettleseren ignorerer den i stillhet. Men det ser rotete ut.

Ordboken gjør det samme på en ryddig måte:

1'selectors_dictionary' => [
2 'left' => 'margin-right: auto',
3 'center' => 'margin: 0 auto',
4 'right' => 'margin-left: auto',
5],
6'selectors' => [
7 '{{WRAPPER}} .sde' => '{{VALUE}}',
8],

Kontrollverdi center{{VALUE}} blir til margin: 0 auto. Det er alt.

Viktig begrensning: etter at du har aktivert selectors_dictionary mister du den opprinnelige {{VALUE}}. Hvis den samme matrisen har et annet selector-declaration-par som trenger den opprinnelige verdien, vil det motta den allerede substituerte strengen. Her er et problematisk eksempel:

1'selectors' => [
2 '{{WRAPPER}} .sde' => '{{VALUE}}',
3 '{{WRAPPER}}.elementor-sde-scale-the-cropped .sde-cropping-allow .sde' =>
4 'transform-origin: {{VALUE}} 0;',
5],

Her vil transform-origin motta margin: 0 auto 0; i stedet for center 0;. Løsning: trekk ut avhengige deklarasjoner til en separat kontroll.

Ordboken håndterer også oversettelse av enkeltstående CSS-verdier godt:

1'selectors_dictionary' => [
2 'top' => 'flex-start',
3 'middle' => 'center',
4 'bottom' => 'flex-end',
5],
6'selectors' => [
7 '{{WRAPPER}} .elementor-price-table__currency' => 'align-self: {{VALUE}}',
8],

Og til og med med hele sett av deklarasjoner, én nøkkel → flere CSS-egenskaper:

1'selectors_dictionary' => [
2 'left' => 'right: auto; left: 0',
3 'right' => 'left: auto; right: 0',
4],
5'selectors' => [
6 '{{WRAPPER}}.elementor-wc-products ul.products li.product span.onsale' => '{{VALUE}}',
7],

CSS-variabler, calc() og skjulte kontroller, puslespillet legges

Den virkelige kraften i selektorer avsløres i kombinasjon. Én kontroll setter en CSS-variabel, en annen refererer til den, en tredje aktiverer/deaktiverer en hel blokk med regler gjennom en betingelse.

Glidebryteren for Skala% skriver en variabel:

1'selectors' => [
2 '{{WRAPPER}} .sde' => '--sde-scale-percentage: {{SIZE}};',
3],

Veksleren "Skala beskåret" bruker denne variabelen to steder, både for transform og for å sende den videre til Gap-kontrollen:

1'selectors' => [
2 '{{WRAPPER}} .sde' =>
3 'transform: scale(var(--sde-scale-percentage)) scale(0.01);
4 --sde-scale-pct-for-gap: var(--sde-scale-percentage);',
5],

Skjult kontroll med betingelse, samme transform men med en annen selektor (for ubeskåret tilstand):

1'condition' => [
2 'scale_the_cropped!' => 'cropped',
3],
4'selectors' => [
5 '{{WRAPPER}} .sde svg' =>
6 'transform: scale(var(--sde-scale-percentage)) scale(0.01);',
7],

Og Gap-kontrollen bruker den videresendte variabelen med fallback:

1'selectors' => [
2 '{{WRAPPER}} .sde' =>
3 'padding: calc({{SIZE}}{{UNIT}} / (var(--sde-scale-pct-for-gap, 100) / 100)) 0;',
4],

Det som skjer her: Gap kompenserer for skalering. Hvis et element krympes til det halve, multipliseres gapet med 2 for å visuelt forbli det samme. Uten krymping (variabel ikke satt) slår fallback-verdien 100 inn → divisjon med 1 → gapet endres ikke. Ren CSS-matematikk, uten en eneste linje JS.

Transform-stabling, løsning for Edge

Konstruksjonen scale(X) scale(0.01) fortjener spesiell omtale. Hvorfor ikke scale(calc(var(--sde-scale-percentage) / 100))? Fordi Edge ikke støtter calc() inne i transform. I det hele tatt.

Løsning: stabling. Nettlesere bruker transform-funksjoner sekvensielt, én etter én. Derfor:

1transform: scale(var(--sde-scale-percentage)) scale(0.01);

Matematisk ekvivalent med scale(var(--sde-scale-percentage) * 0.01), med andre ord divisjon med 100. Brukeren får en velkjent 0-100-glidebryter, mens verdien under panseret gjøres om til en koeffisient på 0-1.

Det samme prinsippet gjelder for andre transformasjoner: roter, translate, skew, og fungerer i alle moderne nettlesere, inkludert Edge.

⁉️🤔 Ofte stilte spørsmål

Hva havner egentlig i den genererte CSS-filen?

Elementor samler alle selektorer fra registrerte widget-kontroller, setter inn gjeldende verdier fra brukerinnstillingene og skriver resultatet til /wp-content/uploads/elementor/css/post-XXXX.css. Dette er ikke innebygde stiler og ikke dynamisk CSS i sanntid: det er en statisk fil som bufres av nettleseren og lever til neste innstillingsendring i editoren. Selve plassholderne {{VALUE}} {{SIZE}} og andre er ikke en del av WordPress eller Blade-malmotoren: Elementor gjør en vanlig str_replace under CSS-generering, itererer gjennom alle selektor-deklarasjonspar og erstatter tokens med faktiske kontrollverdier.

Hvordan feilsøker jeg selektorer hvis CSS ikke slår inn?

Åpne innleggets genererte CSS-fil (banen er synlig i sidekilden) og sjekk at regelen er der. Hvis regelen mangler, se etter en skrivefeil i kontroll-ID-en eller en syntaksfeil i selectors-arrayet. Hvis regelen er der, men ikke virker, sjekk selektorspesifisitet: {{WRAPPER}} gir høy prioritet, men nestede temaer kan overstyre gjennom !important. Aktiver WP_DEBUG og følg med på PHP-loggen: Elementor hopper lydløst over feilaktige arrays uten å vise feil på skjermen. Bruk {{WRAPPER}} ALLTID, unntatt ved bevisst målretting mot body eller html.

Hvordan skiller selektorer seg fra tilpasset CSS i widget-innstillinger?

Tilpasset CSS (Avansert-fanen) skrives manuelt av brukeren, dette er statiske regler som ikke reagerer på innstillingsendringer. Selektorer kobler kontroller dynamisk med CSS: dra i slideren, width endres, bytt Justering, margin bygges om. Brukeren ser ikke denne mekanismen, de får bare en live forhåndsvisning. For utvikleren er hovedgevinsten fraværet av _content_template()-metoden: uten selektorer måtte du skrevet JS-forhåndsvisning for hver enkelt kontroll.

Trenger jeg selectors_dictionary hvis jeg allerede bruker selectors?

Ja, for et kvalitativt sprang i kode-ryddighet. Uten en ordbok behandler du kontrollverdien implisitt, via merkelige CSS-egenskaper som den ikke-eksisterende margin-center, som nettleseren ignorerer. Med en ordbok spesifiserer du eksplisitt: «hvis verdien er left, sett inn margin-right: auto, hvis center, margin: 0 auto». Kode blir selvdokumenterende, og viktigst av alt, {{VALUE}} drar ikke lenger med seg den opprinnelige kontrollverdien inn i andre deklarasjoner i samme array.

Kan jeg kombinere selectors med _content_template() i én widget?

Teknisk sett ja, men i praksis er dette et signal om å revurdere arkitekturen. Hvis selectors er nok for de fleste kontroller, men et par felter krever JS-rendring, trekk ut JS-logikken i en egen metode og kall den presist. Fullstendig avvisning av selectors til fordel for _content_template() betyr at du skriver en JS-duplikat av all PHP-kontrollogikk, og vedlikehold av en slik widget blir raskt et problem.

Er det verdt å mestre selektorer i 2026

Elementor fortsetter å utvikle atomisk infrastruktur, Variables Manager, Grid- og Flexbox-containere, globale stiler. Men grunnmekanikken i widgets har ikke endret seg siden versjon fire: selectors og selectors_dictionary forblir den primære måten å koble en kontroll med live forhåndsvisning.

Ved å mestre denne teknikken eliminerer du en god halvpart av all JS-logikk i en typisk widget. I stedet for handlere for hvert felt, ett selectors-array per kontroll. I stedet for kompleks posisjonering i forhåndsvisning, en kombinasjon av CSS-variabler med calc() og et par skjulte kontroller. SVG Divider for Elementor-pluginen er et levende eksempel: mer enn halvparten av kontrollene styres utelukkende gjennom selektorer, uten et eneste _content_template()-kall.

Hovedregelen er ikke overkompliser. Hvis du tar deg selv i å skrive en fjerde nestet calc() med tre variabler, stopp. Kanskje er det enklere å legge til en skjult mellomkontroll eller dele logikken i to separate felter. Og Elementors kildekode er den beste læreboken: add_control_rules()-metoden i core/files/css/base.php viser hvordan selektorer behandles internt.