Developer Mode: The Code Editor
title: Developer Mode: The Code Editor description: How to use Developer Mode to write and edit a Proton widget's HTML, CSS, and JavaScript directly, including CSS scoping, code scope levels, and loading external libraries.
Developer Mode gives you direct access to the HTML, CSS, and JavaScript inside any Proton widget. It is the mode for structural changes, custom interactions, Twig dynamic expressions, forms, and anything else that goes beyond updating text and images.
Opening The Code Editor
- Select a Proton widget on the Elementor canvas
- Click the Style tab in the left panel
- Click Edit Code
The code editor opens. You see three panels across the top, HTML, CSS, and JS, and the canvas on the right shows a live preview that updates as you type.
The HTML Panel
The HTML panel contains the complete markup for the section. This is the raw HTML output of the widget.
Write standard HTML. You can use:
- Any HTML5 element
- Inline styles (though CSS panel is preferred)
- Twig syntax for dynamic data (
{{ post.title }},{% for item in get_posts() %}) - The
data-atom-formattribute to make a form managed - Custom
data-*attributes for JavaScript hooks
Every time you change the HTML, Protuno re-scans it and updates the slot list in the Content tab. Adding a new <h2> means a new text slot appears for it.
The CSS Panel
The CSS panel contains all styles for the section. Write standard CSS, selectors, properties, media queries.
Auto-scoping is automatic. Every CSS rule you write is automatically namespaced to this widget's unique selector when rendered. You do not need to prefix your rules, write them as if they apply to the whole page, and Protuno handles the scoping:
/* What you write: */
h2 { font-size: 2.5rem; line-height: 1.2; }
.card { background: white; padding: 2rem; border-radius: 8px; }
/* What gets rendered (approximately): */
.proton-widget-abc123 h2 { font-size: 2.5rem; line-height: 1.2; }
.proton-widget-abc123 .card { background: white; padding: 2rem; border-radius: 8px; }
Your styles cannot leak to other elements on the page, and styles from other Proton widgets cannot affect this one.
Media queries: Write responsive breakpoints normally. Protuno automatically moves all media query blocks to the end of the rendered CSS so they cascade correctly regardless of the order you write them.
The JavaScript Panel
The JS panel is for interactive behavior: tab switchers, counters, dropdown menus, animation triggers, form logic, or anything else that requires JavaScript.
The JS runs after the widget's HTML is in the DOM. Use standard JavaScript, no build step, no module system. To reference elements in this widget, scope your selectors with a unique identifier or use this within the widget context.
Code Scope: Widget, Page, And Site
The code editor has four panels, not three. Alongside HTML/CSS/JS, there is a Scope selector with three levels:
| Scope | What it does | When to use it |
|---|---|---|
| Widget | CSS and JS that belong to this section's design | Default, use this for everything specific to this widget |
| Page | Code injected into <head> or before </body> only on pages where this widget appears | Page-specific tracking pixels, analytics events, or stylesheets needed only on that page |
| Site | Code injected into <head> or before </body> on every page of the site | Site-wide fonts, analytics scripts, global CSS utilities |
Most work happens in Widget scope. Use Page scope for a tracking pixel that only applies to one landing page. Use Site scope for a Google Fonts import or a global utility CSS file.
Loading External Libraries
For third-party JavaScript or CSS libraries (GSAP, Swiper, Alpine.js, Chart.js, etc.), use the External Dependencies panel rather than adding <script> or <link> tags in the HTML.
- In the code editor, open the Dependencies tab
- Add the CDN URL for the library
- Set whether it is a script or stylesheet
- Save
Protuno automatically deduplicates external dependencies across the page. If two Proton widgets on the same page both request the same GSAP CDN URL, it loads only once. This prevents duplicate library loads that cause JavaScript errors or performance problems.
Live Preview
The canvas on the right updates as you type. Changes are not saved to the page until you click Apply in the code editor or Update/Publish in Elementor.
If there is a syntax error in your HTML or CSS, the preview may go blank or show partial output. Fix the error and the preview recovers.
Switching Between Modes
You can switch between Developer Mode and Simple Mode at any time without losing work. The HTML/CSS/JS you edit in Developer Mode is the same code that Simple Mode reads slots from. Any change you make in the code editor immediately updates the slots available in the Content tab.
Frequently Asked Questions
Can I use a CSS framework like Tailwind inside a Proton widget? You can write any CSS. If you want to use Tailwind utility classes, add the Tailwind CDN to External Dependencies and use the classes in your HTML. Note that Tailwind's purge/JIT requires a build step, the CDN version includes all utilities and is large.
Will my JavaScript conflict with other scripts on the page?
Widget-scoped JS runs in the page's global context, so variable naming matters. Use const and let scoped inside a function or IIFE to avoid global namespace pollution:
(function() {
const button = document.querySelector('.my-widget-btn');
// your code here
})();
Does auto-scoping work with :root CSS variables?
CSS variables defined with :root are not scoped, they apply globally. This is intentional: you typically want variables defined in the Global Style manager to be available everywhere. If you define a variable in Widget scope that conflicts with a global one, the widget-specific version wins within the widget.
I need to add a <script> tag inside the HTML. Is that okay?
It works, but using the JS panel or External Dependencies is better practice. Scripts in the HTML panel are harder to maintain and cannot be deduplicated.