If you want to improve lcp wordpress elementor metrics, you must address how Elementor handles DOM generation, asset loading, and image prioritization. This guide provides five direct, developer-tested fixes to optimize your Largest Contentful Paint (LCP) and pass Core Web Vitals without stripping away your layout.
Quick answer
- Fix the Hero Image: Disable lazy-loading for the first image on the page and preload it using a custom header link or hook.
- Eliminate CSS Bloat: Enable Elementor's "Improved Asset Loading" and "Inline Font Icons" experiments, then dequeue unused global stylesheets.
- Prevent Web Font Delay: Set
font-display: swapfor all Google Fonts and local fonts, and preload the primary body font file. - Optimize DOM Depth: Avoid nesting columns inside sections inside inner sections; use CSS Grid or Flexbox containers instead.
- Reduce TTFB: Implement page caching, use object caching for database queries, and route traffic through a CDN with Edge caching.
1. Prioritize the above-the-fold hero image
By default, WordPress and performance plugins lazy-load all images. This is a major mistake for your hero image or featured banner. When the browser has to wait for JavaScript to calculate if the hero image is in the viewport before fetching it, your LCP score tanks.
To fix this, you must programmatically exclude the first image (usually the LCP candidate) from lazy-loading and preload it.
Exclude the hero image from lazy-loading
If you are using WordPress core lazy-loading, you can use the wp_img_animation_and_lazy_loading_choices or wp_get_attachment_image_attributes filter to disable the loading="lazy" attribute on the first image.
Add this code to your child theme's functions.php file:
function custom_exclude_hero_from_lazy_load( $attributes, $attachment ) {
// Replace 1234 with your actual hero image attachment ID
if ( isset( $attachment->ID ) && 1234 === $attachment->ID ) {
$attributes['loading'] = 'eager';
$attributes['fetchpriority'] = 'high';
}
return $attributes;
}
add_filter( 'wp_get_attachment_image_attributes', 'custom_exclude_hero_from_lazy_load', 10, 2 );
Preload the hero image in the document head
Preloading tells the browser to fetch the image immediately, even before it parses the CSS and discovers the image tag. Add this hook to inject a preload link tag into your site's header:
function custom_preload_hero_image() {
if ( is_front_page() || is_home() ) {
$hero_image_url = 'https://example.com/wp-content/uploads/hero-banner.webp';
echo '<link rel="preload" fetchpriority="high" as="image" href="' . esc_url( $hero_image_url ) . '" type="image/webp">' . "\n";
}
}
add_action( 'wp_head', 'custom_preload_hero_image', 1 );
Using fetchpriority="high" alongside the preload link instructs modern browsers to prioritize this asset above stylesheets and scripts, drastically reducing LCP.
2. Eliminate Elementor CSS bloat and unused assets
Elementor loads a large suite of stylesheets on every page, regardless of whether you use the corresponding widgets. This blocks the main thread and delays the rendering of the LCP element.
Enable Elementor performance experiments
Navigate to Elementor > Settings > Features in your WordPress dashboard. Turn on these features:
- Improved Asset Loading: Loads widget-specific JS/CSS files only when those widgets are used on the page.
- Inline Font Icons: Replaces the heavy Font Awesome icon library stylesheet with inline SVG icons.
- Optimized Gutenberg Loading: Prevents Gutenberg block styles from loading where they are not needed.
Dequeue unused styles programmatically
If you do not use certain Elementor features, dequeue their stylesheets. For example, if you do not use Elementor's global animations or frontend icons, dequeue them with this snippet:
function custom_dequeue_elementor_bloat() {
// Dequeue Elementor icons if you use SVGs instead
wp_dequeue_style( 'elementor-icons' );
// Dequeue animations if you do not use entry animations
wp_dequeue_style( 'elementor-animations' );
}
add_action( 'wp_enqueue_scripts', 'custom_dequeue_elementor_bloat', 20 );
Keep in mind that dequeuing styles can break layouts if you accidentally target an active style. Always test these changes on a staging environment first.
3. Optimize web font loading to prevent layout shifts
When a browser loads web fonts, it often hides the text until the font file is fully downloaded (Flash of Invisible Text, or FOIT), or it displays a fallback system font and then jumps when the custom font loads (Flash of Unstyled Text, or FOUT). Both delay LCP and degrade your Cumulative Layout Shift (CLS) score.
Apply font-display: swap
To ensure text renders immediately using a system font while the custom font loads, add font-display: swap to your font declarations.
If you use Google Fonts through Elementor, add this filter to your functions.php file to append the display=swap query parameter to the Google Fonts API request URL:
function custom_add_subsets_to_google_fonts( $url ) {
if ( strpos( $url, 'fonts.googleapis.com' ) !== false ) {
$url = add_query_arg( 'display', 'swap', $url );
}
return $url;
}
add_filter( 'style_loader_src', 'custom_add_subsets_to_google_fonts', 10, 1 );
Preload local fonts
If you host your fonts locally (which is recommended for GDPR compliance and speed), preload the primary font file used for your body text and headings. Add this to your header:
function custom_preload_local_fonts() {
$font_url = get_stylesheet_directory_uri() . '/assets/fonts/main-font.woff2';
echo '<link rel="preload" href="' . esc_url( $font_url ) . '" as="font" type="font/woff2" crossorigin>' . "\n";
}
add_action( 'wp_head', 'custom_preload_local_fonts', 1 );
4. Flatten your DOM structure
Elementor historically created deeply nested HTML structures (e.g., div > div > div > div). A deep DOM tree increases memory usage, slows down style calculations, and delays rendering of the LCP element.
Switch to Flexbox and Grid Containers
If your site still uses the legacy Section/Column structure, convert your layouts to Flexbox Containers.
- Go to Elementor > Settings > Features and ensure Flexbox Container is active.
- Open your pages in the Elementor editor.
- Click on a legacy Section and click the Convert button in the sidebar panel.
- Delete the old Section once you verify the new Container replica looks correct.
This single change can reduce your DOM depth by up to 40%, allowing the browser to parse and paint the LCP element much faster.
5. Reduce server response time (TTFB)
Your LCP can never load faster than your initial HTML document. If your Time to First Byte (TTFB) is 1.2 seconds, your LCP will inevitably be poor. Elementor sites require robust hosting and caching strategies to keep TTFB under 200ms.
Implement page caching and object caching
Ensure you have a page caching layer active. If your host does not provide server-level caching (like Nginx FastCGI cache or LiteSpeed Cache), use a plugin like WP Rocket or Cache Enabler.
Additionally, enable Redis or Memcached on your server to cache database queries. This prevents Elementor from querying the database for global settings and page metadata on every single request.
Optimize your database
Elementor saves a new revision every time you update a page. Over time, these revisions clutter your database, slowing down queries. Run this WP-CLI command to clean up old revisions:
wp post delete $(wp post list --post_type=revision --format=ids) --force
Alternatively, limit the number of revisions WordPress keeps by adding this line to your wp-config.php file:
define( 'WP_POST_REVISIONS', 5 );
Checklist
- Identify the LCP element using PageSpeed Insights or Chrome DevTools Performance panel.
- Exclude the hero image from lazy-loading using the
wp_get_attachment_image_attributesfilter. - Preload the hero image URL in the document head using
fetchpriority="high". - Turn on "Improved Asset Loading" and "Inline Font Icons" in Elementor Features.
- Dequeue unused Elementor stylesheets and icon libraries using PHP hooks.
- Apply
font-display: swapto all custom and Google fonts. - Preload your primary local font files in WOFF2 format.
- Convert legacy Elementor Sections and Columns to Flexbox Containers.
- Clean up the WordPress database by limiting and deleting old post revisions.
- Verify that your TTFB is under 200ms using a server-level caching solution.
Frequently asked questions
Why is my Elementor LCP so high even with optimization plugins?
Optimization plugins often apply blanket rules like lazy-loading to all images or delaying all JavaScript. If your hero image is lazy-loaded, or if critical CSS is delayed, your LCP score will drop. You must target the specific LCP element and exclude it from generic optimization scripts.
Does converting to Flexbox containers actually improve LCP?
Yes. Flexbox containers reduce the number of nested HTML tags (DOM depth) by up to 40%. A lighter DOM means the browser spends less time parsing HTML and calculating styles, which directly accelerates the rendering of your LCP element.
How do I find out which element is triggering my LCP?
Run your page through Google PageSpeed Insights or Chrome DevTools Lighthouse. Under the 'Diagnostics' section, look for 'Largest Contentful Paint element'. It will highlight the exact HTML element (usually an image or heading) that you need to optimize.
- Web Vitals (web.dev)Web Vitals (web.dev)
- Lighthouse overviewLighthouse overview
Drafted with AI assistance. Code targets current WordPress, WooCommerce and Next.js APIs; test changes on a staging site before production.