Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Diagram illustrating how to embed a modern Lightning component into a classic Visualforce page using Lightning Out.
Visualforce

Add a Lightning component in Visualforce using Lightning Out

You do not need a full rewrite to put modern UI on a legacy page. Lightning Out drops a Lightning component straight into an existing Visualforce page, and this post covers the wrapper app, the markup, and the mistakes that stop it loading.

The short answer

Lightning Out lets you embed Aura components and Lightning web components in a legacy Visualforce page without rewriting it. You need an Aura app wrapper that extends ltng:outApp, the apex:includeLightning tag on the page, and a script that calls $Lightning.use and then $Lightning.createComponent.

Key takeaways Deploy My Domain in both your sandbox and production orgs before you try Lightning Out. Set access="GLOBAL" on the Aura application and its components, or you get 403 Forbidden and 404 errors. Create an Aura app that extends ltng:outApp and declares an aura:dependency, which can point at an Aura component or a Lightning web component. Match the third parameter of $Lightning.createComponent to the exact ID of the target container div in Visualforce. Wrap the component container in an slds-scope class when Visualforce styles start fighting with the Salesforce Lightning Design System.

Why you'd want to put a Lightning component in Visualforce

If you still maintain legacy pages, you have probably wondered how to embed a Lightning component in Visualforce without doing a full rewrite. The setup is always the same: a big, complicated Visualforce page that works perfectly well, and a piece of modern UI or a feature that only exists in Lightning. Instead of migrating the whole thing, we use Lightning Out.

Older orgs hit this constantly. You might be halfway through a transition to Lightning Experience, or stuck in Classic for a specific business reason. Either way, dropping a Lightning component in Visualforce lets you build the new feature with modern tools and leave the old page working.

A mockup of a modern Lightning component embedded in a classic Salesforce Visualforce page layout.

A mockup of a modern Lightning component embedded in a classic Salesforce Visualforce page layout.

The step-by-step guide to adding a Lightning component in Visualforce

Lightning Out is the bridge that lets you run Lightning components outside the standard Lightning container. A couple of things have to be right before you start writing code. First, you need My Domain enabled. If you don't have that set up, stop right here and go do it, because nothing else will work.

Second, your component and your application need to be accessible, which means access="GLOBAL" on your Aura components. I've watched plenty of developers miss that and spend an hour wondering why their scripts are throwing 404 errors.

1. Create the Aura app wrapper

Visualforce can't call a component directly, so you need an Aura app to act as the host. That app extends ltng:outApp and declares which components it's going to use. A minimal c:myLightningApp.app file looks like this:

<aura:application extends="ltng:outApp" access="GLOBAL">
    <aura:dependency resource="markup://c:myComponent" />
</aura:application>

force:slds isn't strictly required in the app if you're already using it in the component, though it doesn't hurt. The tag that matters is aura:dependency. It tells Salesforce to pre-load your component so it's ready when the Visualforce page asks for it.

2. Writing the Visualforce page

On the Visualforce side, the <apex:includeLightning /> tag brings in the JavaScript libraries, and a small script block initializes the app and creates the component.

<apex:page standardController="Account">
    <apex:includeLightning />
    
    <div id="lightning-container" />

    <script>
        $Lightning.use("c:myLightningApp", function() {
            $Lightning.createComponent(
                "c:myComponent",
                { "recordId": "{!Account.Id}" },
                "lightning-container",
                function(cmp) {
                    console.log('Component is live!');
                }
            );
        });
    </script>
</apex:page>

The third parameter in $Lightning.createComponent trips people up. It's the ID of the HTML element where you want the component to land, here the div with the ID lightning-container. Get that ID wrong and your component never shows up.

3. What about Lightning Web Components (LWC)?

You can use an LWC too, and you still need that Aura app wrapper. Point the aura:dependency to your LWC instead of an Aura component. For anything new I'd go the LWC route and treat the Aura wrapper as the delivery vehicle. On more complex work it's worth reading up on how communication between Lightning web components works so you can pass data back and forth.

I've seen teams spend hours debugging why their component won't load, only to realize 'My Domain' wasn't deployed in the sandbox. Check that first. It's the most common point of failure for Lightning Out.

Troubleshooting your Lightning component in Visualforce

The most common failure is the "white screen of death" where nothing loads at all, and it's usually a permissions issue. Check your browser console: 403 Forbidden errors point straight back at that access="GLOBAL" attribute.

CSS clashing is the other regular offender. Visualforce has its own styles and SLDS (Salesforce Lightning Design System) has its own, and they don't always play nice. If your buttons look weird or your spacing is off, wrap your container in a <div class="slds-scope"> so the Lightning styles stay where they belong. A Chrome extension for Salesforce helps here, since you can inspect the DOM and see which styles are winning the fight.

Keep an eye on the session as well. If the user's session expires, or they're coming from a different domain, Lightning Out gets cranky. In an Experience Cloud site, make sure you're passing the correct site prefix or community URL.

Key takeaways

  • My Domain has to be active before any of this works.
  • Both the Aura app and the component need access="GLOBAL".
  • The container is an Aura app extending ltng:outApp.
  • The ID in your JavaScript has to match the ID of your div.
  • LWCs work too, wrapped in an Aura dependency.

Adding a Lightning component in Visualforce isn't as scary as it sounds. Follow the boilerplate, watch your access levels, and you'll have modern components running on your old pages without the risk of a total page rebuild.

Frequently asked questions

How do you embed a Lightning component in a Visualforce page?

Add the <apex:includeLightning /> tag to your Visualforce page, load an Aura application wrapper extending ltng:outApp using $Lightning.use, and render the component into a target DOM element with $Lightning.createComponent.

Can you use Lightning Web Components in Visualforce?

Yes. You can use an LWC by referencing it inside the <aura:dependency> tag of an Aura app wrapper and loading that app via Lightning Out on the Visualforce page.

Why is a Lightning Out component not rendering in Visualforce?

Components typically fail to render when My Domain is not deployed, the access="GLOBAL" attribute is missing, the target DOM element ID in $Lightning.createComponent does not match the page markup, or the user session has expired.

How do you fix CSS conflicts between Visualforce and SLDS?

Wrap your component's target container div with the slds-scope class to isolate Salesforce Lightning Design System styling and prevent Visualforce styles from interfering.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment