
🎯 Selectors i Elementor-widgets: komplett guide för utvecklare
Varför Elementor-utvecklare behöver selektorer och hur de fungerar
När en användare justerar widgetinställningar i editorn förväntar de sig ett omedelbart svar på skärmen. Utan selektorer skulle en utvecklare behöva skriva en JS-hanterare för varje fältändring. Med selektorer löses allt med CSS.
Parametern selectors (och dess mindre kända motsvarighet selectors_dictionary) bäddas in direkt i arrayen för add_control()-anropet. Elementor ersätter dynamiskt värden från fält till CSS-regler och skriver ut dem till postfilen, något i stil med /wp-content/uploads/elementor/css/post-1234.css. Så snart användaren lämnar editorn försvinner inline-stilarna och lämnar ren genererad CSS.
💡 Snabb översikt:
- Förstå selektorsyntax och platshållartabellen
- Se live-exempel för färg och storlekar
- Lär dig hämta värden från närliggande kontroller
- Bemästra selectors_dictionary för substitution av CSS-deklarationer
- Lägg pusslet med CSS-variabler och dolda kontroller
Var selektorer definieras
När du skapar en widget tar varje add_control()-anrop emot en inställningsarray. Det är precis där selectors finns. För gruppkontroller är syntaxen densamma, arrayen skickas in i gruppregistreringen.
Grundformat:
1 'selectors' => [ 2 '{{WRAPPER}} .my-widget-class' => 'color: {{VALUE}}', 3 ]
Nyckeln är en CSS-selektor (börjar med {{WRAPPER}} för att undvika att påverka närliggande widgets på sidan). Värdet är en eller flera CSS-deklarationer med dynamiska platshållare. Elementor tar det aktuella kontrollvärdet och ersätter det i stället för platshållaren.
Resultatet renderas till postens externa CSS-fil, stilar finns bara medan editorn är öppen och omedelbart efter sparande. Ingen inline-röra.
Tabell med klammerparentesvariabler
Ingen magi, bara sök-och-ersätt. Men variationen av platshållare öppnar dörrar till ganska smarta konstruktioner.
För selektorer (array-nyckel)
Platshållare | Vad den ersätter |
|---|---|
| Unik selektor för widgetinstans, till exempel |
| Endast widget-ID (delen efter bindestrecket, |
| Begränsar regeln till den angivna enheten. Med |
| Aktivt element i en repeater-kontroll |
För deklarationer (array-värde)
Platshållare | Vad den ersätter |
|---|---|
| Rått kontrollvärde. Kan åsidosättas av |
| Tal och måttenhet från numeriska kontroller. Används vanligtvis i par: |
| Riktningar från dimensionskontroll |
| Åtkomst till namngiven egenskap i sammansatta kontroller: till exempel returnerar Media Control en array med fälten |
| Värde från en annan kontroll via ID. Suffixen |
| Fallback: om kontrollen är tom ersätts |
Enkla exempel, från färg till bakgrundsbild
Färg från palett. Inget extra:
1 'selectors' => [ 2 '{{WRAPPER}} .elementor-svg-divider-basic-text' => 'color: {{VALUE}}', 3 ],
Numerisk kontroll med och utan enhet. Den andra egenskapen (stroke-width) är avsiktligt utan {{UNIT}}, linjetjocklek är i pixlar, utan px:
1 'selectors' => [ 2 '{{WRAPPER}} svg.sde-classic' => 3 'height: {{SIZE}}{{UNIT}}; stroke-width: {{SIZE}};', 4 ],
Mellanrum från dimensionskontroll, varje riktning separat:
1 'selectors' => [ 2 '{{WRAPPER}} .elementor-svg-divider-basic-button' => 3 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 4 ],
Bakgrundsbild för en slide i repeater-kontroll:
1 'selectors' => [ 2 '{{WRAPPER}} {{CURRENT_ITEM}} .swiper-slide-bg' => 3 'background-image: url({{URL}})', 4 ],
Villkorlig position för RTL. Samma kontroll ger olika egenskaper beroende på textriktning:
1 'selectors' => [ 2 'body:not(.rtl) {{WRAPPER}} .dialog-close-button' => 'right: {{SIZE}}{{UNIT}}', 3 'body.rtl {{WRAPPER}} .dialog-close-button' => 'left: {{SIZE}}{{UNIT}}', 4 ],
Hur man hämtar ett värde från en annan kontroll
Om två fält påverkar samma CSS, duplicera inte arrayen, referera bara till den närliggande kontrollen:
1 'selectors' => [ 2 '{{WRAPPER}} svg.sde-classic' => 3 'stroke-dasharray: {{dash_length.SIZE}} {{whitespace_length.SIZE}};', 4 ],
Här är dash_length och whitespace_length ID:n för andra kontroller i samma widget. Inga ytterligare anrop, bara punktnotation.
Responsiv version, värden hämtas med hänsyn till enheten. Verkligt exempel från 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 ],
Varje brytpunkt får sitt eget columns-värde. De övriga egenskaperna (border, SIZE) är gemensamma, de är inte knutna till enheten.
Selectors_dictionary, switch-case för CSS
Den mest underskattade funktionen. selectors_dictionary ersätter {{VALUE}} med en hårdkodad sträng, vilket i praktiken gör kontrollvärdet till en dictionary-nyckel.
Ta standardkontrollen Align med alternativen left/center/right. Utan en dictionary skulle du skriva något onaturligt:
1 'selectors' => [ 2 $sde_selector => 'margin: 0 auto; margin-{{VALUE}}: 0;', 3 ],
För center ger detta margin: 0 auto; margin-center: 0;. Egenskapen margin-center finns inte, webbläsaren ignorerar den tyst. Men det ser rörigt ut.
Dictionaryn gör samma sak rent:
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 ],
Kontrollvärde center → {{VALUE}} blir margin: 0 auto. Så enkelt är det.
Viktig begränsning: efter att du aktiverat selectors_dictionary förlorar du det ursprungliga {{VALUE}}. Om samma array har ett annat selector-declaration-par som behöver det ursprungliga värdet, kommer det att få den redan ersatta strängen. Här är ett problematiskt exempel:
1 'selectors' => [ 2 '{{WRAPPER}} .sde' => '{{VALUE}}', 3 '{{WRAPPER}}.elementor-sde-scale-the-cropped .sde-cropping-allow .sde' => 4 'transform-origin: {{VALUE}} 0;', 5 ],
Här kommer transform-origin att få margin: 0 auto 0; istället för center 0;. Lösning: bryt ut beroende deklarationer till en separat kontroll.
Dictionaryn hanterar också översättning av enskilda CSS-värden bra:
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 ],
Och även med hela uppsättningar av deklarationer, en nyckel → flera 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() och dolda kontroller, pusslet läggs
Den verkliga styrkan hos selectors visar sig i kombination. En kontroll sätter en CSS-variabel, en annan refererar till den, en tredje aktiverar/inaktiverar ett helt regelblock via ett villkor.
Scale%-reglaget skriver en variabel:
1 'selectors' => [ 2 '{{WRAPPER}} .sde' => '--sde-scale-percentage: {{SIZE}};', 3 ],
Växlingsknappen "Scale cropped" använder denna variabel på två ställen, både för transform och för att skicka vidare till 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 ],
Dold kontroll med villkor, samma transform men med en annan selector (för obeskuret läge):
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 ],
Och Gap-kontrollen använder den vidarebefordrade variabeln med fallback:
1 'selectors' => [ 2 '{{WRAPPER}} .sde' => 3 'padding: calc({{SIZE}}{{UNIT}} / (var(--sde-scale-pct-for-gap, 100) / 100)) 0;', 4 ],
Vad som händer här: Gap kompenserar för skalning. Om ett element krymps till hälften multipliceras gapet med 2 för att visuellt förbli detsamma. Utan krympning (variabeln inte satt) slår fallbackvärdet 100 in → division med 1 → gapet ändras inte. Ren CSS-matematik, utan en enda rad JS.
Transform-stapling, workaround för Edge
Konstruktionen scale(X) scale(0.01) förtjänar särskilt omnämnande. Varför inte scale(calc(var(--sde-scale-percentage) / 100))? För att Edge inte stöder calc() inuti transform. Överhuvudtaget.
Lösning: stapling. Webbläsare tillämpar transformfunktioner sekventiellt, en efter en. Därför:
1 transform: scale(var(--sde-scale-percentage)) scale(0.01);
Matematiskt ekvivalent med scale(var(--sde-scale-percentage) * 0.01), med andra ord division med 100. Användaren får en välbekant 0-100-reglage, medan värdet under huven omvandlas till en 0-1-koefficient.
Samma princip gäller för andra transformationer: rotate, translate, skew, och fungerar i alla moderna webbläsare, inklusive Edge.
⁉️🤔 Vanliga frågor
Vad hamnar egentligen i den genererade CSS-filen?
Elementor samlar in alla selektorer från registrerade widgetkontroller, ersätter aktuella värden från användarinställningarna och skriver resultatet till
/wp-content/uploads/elementor/css/post-XXXX.css. Det här är inte inline-stilar och inte dynamisk CSS i farten: det är en statisk fil som cachas av webbläsaren och lever tills nästa inställningsändring i editorn. Platshållarna i sig,{{VALUE}}{{SIZE}}och andra, är inte en del av WordPress eller Blades templatemotor: Elementor gör en vanligstr_replaceunder CSS-genereringen, itererar genom alla selektor-deklarationspar och ersätter tokens med faktiska kontrollvärden.
Hur felsöker jag selektorer om CSS inte slår igenom?
Öppna inläggets genererade CSS-fil (sökvägen syns i sidkällan) och kontrollera att regeln finns där. Om regeln saknas, leta efter ett stavfel i kontroll-ID:t eller ett syntaxfel i
selectors-arrayen. Om regeln finns men inte fungerar, kontrollera selektorns specificitet:{{WRAPPER}}ger hög prioritet, men nästlade teman kan åsidosätta med!important. AktiveraWP_DEBUGoch håll koll på PHP-loggarna: Elementor hoppar tyst över felaktiga arrayer utan att visa fel på skärmen. Använd{{WRAPPER}}ALLTID, utom när du avsiktligt riktar dig mot body eller html.
Hur skiljer sig selektorer från anpassad CSS i widgetinställningarna?
Anpassad CSS (fliken Avancerat) skrivs manuellt av användaren, det är statiska regler som inte reagerar på inställningsändringar. Selektorer kopplar dynamiskt kontroller till CSS: dra i reglaget,
widthändras, byt Justering,marginbyggs om. Användaren ser inte den här mekanismen, de får bara en liveförhandsvisning. För utvecklaren är den stora vinsten frånvaron av metoden_content_template(): utan selektorer skulle du behöva skriva JS-förhandsvisning för varje kontroll.
Behöver jag selectors_dictionary om jag redan använder selectors?
Ja, för ett kvalitativt språng i kodrenhet. Utan en ordlista bearbetar du kontrollvärdet implicit, genom märkliga CSS-egenskaper som den icke-existerande
margin-center, som webbläsaren ignorerar. Med en ordlista specificerar du uttryckligen: "om värdet är left, ersätt med margin-right: auto, om center, margin: 0 auto". Koden blir självdokumenterande, och viktigast av allt,{{VALUE}}drar inte längre in det ursprungliga kontrollvärdet i andra deklarationer i samma array.
Kan jag kombinera selectors med _content_template() i en och samma widget?
Tekniskt sett ja, men i praktiken är detta en signal att ompröva arkitekturen. Om selectors räcker för de flesta kontroller, men ett par fält kräver JS-rendering, extrahera JS-logiken till en separat metod och anropa den punktvis. Att helt överge selectors till förmån för
_content_template()innebär att du skriver en JS-kopia av all PHP-kontrollogik, och att underhålla en sådan widget blir snabbt ett problem.
Är det värt att bemästra selectors under 2026
Elementor fortsätter att utveckla atomär infrastruktur, Variables Manager, Grid- och Flexbox-containrar, globala stilar. Men grunden för widgetmekaniken har inte förändrats sedan version fyra: selectors och selectors_dictionary är fortfarande det primära sättet att koppla en kontroll till liveförhandsvisning.
Genom att bemästra den här tekniken eliminerar du en god hälft av all JS-logik i en typisk widget. Istället för hanterare för varje fält, en selectors-array per kontroll. Istället för komplex positionering i förhandsvisning, en kombination av CSS-variabler med calc() och ett par dolda kontroller. Pluginet SVG Divider for Elementor är ett levande exempel: mer än hälften av dess kontroller hanteras uteslutande genom selectors, utan ett enda _content_template()-anrop.
Huvudregeln är att inte överkomplicera. Om du kommer på dig själv med att skriva en fjärde nästlad calc() med tre variabler, stanna upp. Kanske är det enklare att lägga till en dold mellanliggande kontroll eller dela upp logiken i två separata fält. Och Elementors källkod är den bästa läroboken: metoden add_control_rules() i core/files/css/base.php visar hur selectors bearbetas internt.



