To hide a section, column, or widget when an ACF field is empty you need a visibility plugin, because Elementor on its own cannot read a custom field and decide whether to render. That is the part most tutorials skip. This guide covers the free route, the Dynamic Content for Elementor route, and the Crocoblock route, plus the two traps that make a correct-looking setup fail silently: fields that store a zero, and page caching.
Quick verdict
- Best free: Dynamic Visibility for Elementor, from the same team behind Dynamic Content for Elementor. It is the only one of the three routes here that costs nothing, and its Post Field condition already reads ACF and SCF fields.
- Best if you already build with custom fields: Dynamic Content for Elementor, Starter at EUR 69 a year for one site. You are paying for the other 150-plus features and the custom PHP condition, not for the empty check.
- If you are already on Crocoblock: JetEngine has this built in, but the obvious empty check does not work. Crocoblock’s own documentation tells you to use a Regexp condition instead. Details below.
- Skip all of this if: you expected Elementor’s native Display Conditions to do it. Its published condition list has no custom-field option at all, so no amount of clicking will get you there.
- Our call: install the free plugin, set the condition on your single post template rather than on individual posts, and read the section on zero values before you decide the plugin is broken.
First, work out whether you have ACF or Secure Custom Fields
This matters more than it used to. In October 2024, ACF was forked, and there are now two separate plugins doing the same job. Both listings are live on WordPress.org as of the check date below.
- Advanced Custom Fields, published by WP Engine, version 6.8.9, 2 million-plus active installs. The paid tier, ACF PRO, is sold from the vendor’s own site.
- Secure Custom Fields, published by WordPress.org, version 6.9.5, 90,000-plus active installs. It ships Repeater, Flexible Content, Gallery and Clone, which were ACF PRO-only field types, at no cost.
How to check: open Plugins in wp-admin and read the name. If it says Secure Custom Fields, that is the fork. Do not try to run both. SCF deliberately deactivates ACF on activation because the two define the same functions.
Why it does not change the tutorial: SCF still defines the ACF class, the ACF_PRO constant and get_field(). Visibility plugins detect ACF by checking for that class, so they see SCF and group your fields under an ACF heading in the field picker either way. Every step below works with both. Where this article says ACF field, read it as ACF or SCF field.
What the three routes cost
Some links below are affiliate links. If you buy through one, this site earns a commission at no extra cost to you, and the price you pay is unchanged.
| Route | Price | Sites | What you get for it |
|---|---|---|---|
| Dynamic Visibility for Elementor | Free | Unlimited | Post Field conditions, show/hide, fallback content |
| Dynamic Content for Elementor, Starter | €69/year | 1 | The above plus custom PHP conditions and 150+ features |
| Dynamic Content for Elementor, Expanded | €119/year | 3 | Same feature set, three activations |
| Dynamic Content for Elementor, Starter Lifetime | €189 once | 1 | All future updates; support billed €19/year after year one |
| JetEngine, one project | $75/year | 1 | Dynamic Visibility module plus post types, meta fields, listings |
| JetEngine, unlimited | $169/year | Unlimited | Same plugin, no activation cap |
| Crocoblock All-Inclusive | $199/year | 1 | All 22 JetPlugins including JetEngine |
Neither vendor publishes a discounted renewal rate. Dynamic.ooo licences renew automatically at the listed annual price, and Crocoblock lists annual prices only. Budget for the same number next year.
The free route: Dynamic Visibility for Elementor
Dynamic Visibility for Elementor is Dynamic.ooo’s free plugin, version 6.0.4, 50,000-plus active installs, tested to WordPress 7.0.4. It is the visibility engine out of the premium plugin, released on its own. If you install the paid version later, the settings you build now carry over, because it is the same code.
Say you have a text field called text_field on a post, and a section containing a heading that prints it. When an editor leaves the field blank you want the whole section gone, not an empty heading with 60px of padding around it.
Step 1: Edit the template, not the post
Set this on your single post template built with Elementor rather than on one post. Do it on a post and you will be repeating yourself 200 times. This is the single biggest time sink in the whole job.
Step 2: Select the element and open the Visibility tab
Click the section, container, column or widget you want to control. The plugin adds its own Visibility tab to the panel, alongside Layout, Style and Advanced. Turn the Visibility switch to Yes.

Step 3: Set Display mode to Show
Leave Keep HTML off so the element is removed from the page source rather than hidden with CSS. Set Display mode to Show. You are about to describe the condition under which the element should appear, which reads more naturally than describing when it should vanish.
Step 4: Narrow the triggers to Post and Page
The Triggers field starts with every trigger selected. Click Deselect All Triggers, then pick Post and Page on its own. Leaving the rest in place will not break anything, since unconfigured triggers contribute no conditions, but a panel with ten open sections is a panel you will misread in six months.
Step 5: Choose the field and the status
Open the Post and Page section that has now appeared. In Post Field, start typing your field name. ACF and SCF fields are grouped under an ACF heading in that dropdown. Pick text_field, then set Post Field Status to Not empty.
![Dynamic Visibility Post Field dropdown with Text Field [text] selected and the Post Field Status control directly underneath it](https://stylemywp.com/wp-content/uploads/2021/10/Show-or-Hide-Section-Column-or-Widget-When-ACF-Field-is-valued-or-Empty.png)
If you are following an older tutorial and hunting for an option called Valorized with any value, stop looking. Current versions relabelled that pair as Not empty and Empty or not set. Same behaviour, clearer wording.
Step 6: Verify it before you call it done
Save the template, then open two posts on the front end in a private window: one with the field filled, one with it deliberately blank. On the blank one, view source and search for a distinctive string from inside the section. If Keep HTML is off and the condition is right, that string is absent from the HTML entirely, not merely hidden. If it is present but invisible, Keep HTML is on. If it is present and visible, the condition never matched, and the field name in the dropdown is the first thing to re-check.
The paid route: Dynamic Content for Elementor
Dynamic Content for Elementor is the full plugin, and the visibility panel is identical because the free plugin is carved out of it. Buying it for the empty check alone is a waste of EUR 69. Buy it for what surrounds the check.
The condition that earns the licence is Custom Condition, a PHP snippet that returns true or false. In the free plugin that section shows an upgrade notice instead of a code box. It is the escape hatch for everything the dropdown cannot express, such as show this block only when the repeater has at least three rows and the post is older than a fortnight. The premium build also brings ACF Repeater and ACF Flexible Content widgets, which is usually why people on ACF-heavy builds end up here anyway.
One thing worth knowing before you buy: you do not need Elementor Pro to run it. Only the form extensions depend on Pro. Current tiers are on the Dynamic.ooo pricing page, and prices exclude VAT. There is a 30-day money-back guarantee on new purchases.
The Crocoblock route: JetEngine Dynamic Visibility
If you already own Crocoblock, do not install a fourth plugin. JetEngine ships a Dynamic Visibility module that covers Elementor, Gutenberg and Bricks.
- Enable it at JetEngine > JetEngine > Modules > Default Modules, where it is a toggle called Dynamic Visibility. It is off until you switch it on, which is where most people give up.
- Select your element and open Advanced > Dynamic Visibility. Turn on Enable and leave the visibility condition type as Show element if condition met.
- Set Condition to Regexp, click the Dynamic Tag icon beside the Field selector, choose Custom Field under the JetEngine group, and pick your field.
- Put
.+in the Value box. That expression matches one or more characters, so it is true for any non-empty value.
That fourth step looks like a hack, and it is, but it is Crocoblock’s own instruction. Their troubleshooting article Cannot Hide a Widget if a Meta Field Is Empty states plainly that the obvious presence check does not operate correctly and that a different condition should be used. The same page notes the Regexp approach is supported for Text, Textarea, Number, Checkbox, Select and Radio meta fields. If you are on a field type outside that list, test it properly before shipping. Pricing for JetEngine on its own and for the bundles is on the Crocoblock pricing page.
What most tutorials get wrong about Elementor’s own Display Conditions
Elementor has a feature called Display Conditions, and a lot of articles imply it can do this job. It cannot. Read Elementor’s own documentation and the complete published list of available conditions is: page parent, author, categories, tags, date modified, date of publish, login status, role, registration date, day of the week, time of day, current date, archive tags, archive categories, and referring URL.
There is no custom-field condition on that list, and therefore no ACF condition. Elementor’s ACF integration is about printing a field through a dynamic tag, which is a different feature that also requires Elementor Pro. Printing a field and branching on whether it has a value are not the same thing, and conflating them is why people spend an afternoon in the wrong panel.
The same documentation carries a warning that applies to every plugin in this article, not just Elementor’s: because these conditions are evaluated dynamically, they interact badly with caching. Elementor’s advice is to disable advanced caching where you use them. That is a heavier hammer than most sites need, but the underlying point stands, and it is covered properly below.
What breaks
A number field set to 0 counts as empty
This is the one that costs people a whole evening. The Not empty check in Dynamic Visibility is PHP’s empty() under the hood, and empty() treats the string "0", the integer 0, false, null and the empty array as empty. So an ACF Number field holding a legitimate zero, or a True/False field set to No, both read as empty and your section disappears on posts where the editor did fill the field in.
If zero is a meaningful value in your data, do not use the empty check. Use Greater than or equal to with a value of 0, or Not equal to with an empty value, and test with a real zero before you publish.
Repeaters and relationship fields are arrays
A Repeater with zero rows is an empty array and behaves as expected. A Repeater with rows is an array, so string comparisons like Contains and Starts with will not do what you assume. Stick to Not empty and the numeric comparisons for those field types, and reach for the custom PHP condition when the logic genuinely depends on what is inside the array.
Caching serves the wrong version
Conditions run on page generation. A full-page cache stores whatever the condition produced the first time and hands that HTML to everyone until the cache clears. If the condition depends only on post data, as it does here, that is fine, because the cached page belongs to that post anyway. Clear your page cache plugin after every edit, though, or you will keep testing yesterday’s HTML and concluding the plugin does not work. Conditions that depend on the visitor rather than the post, such as logged-in status, are the ones that need cache exclusions.
Keep HTML leaves the element in the source
Keep HTML hides with CSS instead of removing the markup. That helps when JavaScript inside the element needs to initialise, and it hurts when the element is heavy. A hidden video player widget may still pull its iframe, and a hidden button widget is still a link in your source that a crawler can see. Default to off, and only turn it on when something concrete breaks without it.
The condition follows the copy, not the design
Put the condition on the outermost wrapper you actually want gone. Hiding the heading widget alone still leaves the section’s padding, background and border, which is why the page looks like it has a hole in it rather than looking finished. If the same conditional block appears in more than one template, build it once as a global widget so the condition lives in one place.
Which route to pick
- One site, one condition, no budget: the free Dynamic Visibility plugin. Nothing here needs the paid tier.
- Client sites built on ACF or SCF, several conditions per template: Dynamic Content for Elementor. The custom PHP condition pays for itself the first time a client asks for logic no dropdown covers.
- Already paying Crocoblock: JetEngine, with the Regexp workaround. Adding another visibility plugin on top is a support conflict waiting to happen.
- Not committed to Elementor: check the comparison of dynamic visibility and condition plugins first, and if you are still choosing a builder, the roundup of visual page builders for WordPress covers how Bricks and the block editor handle the same problem.
Whichever you pick, it is one plugin doing one job. If you are already carrying three Elementor addons that each register their own visibility tab, remove the ones you are not using before you add another.
Frequently Asked Questions
Do I need Elementor Pro to hide a section when an ACF field is empty?
No. Dynamic Visibility for Elementor works with free Elementor, and Elementor Pro is not required for Dynamic Content for Elementor either. You will want Pro to print the field value through a dynamic tag, but the visibility condition itself does not depend on it.
Is the free plugin enough, or do I need the paid one?
The free plugin is enough for empty and not-empty checks, equality, numeric comparison and string matching on post fields. You need the paid version for the custom PHP condition, the ACF Repeater and Flexible Content widgets, and the rest of the 150-plus features.
How do I tell whether I have ACF or Secure Custom Fields?
Open the Plugins screen in wp-admin and read the plugin name. Advanced Custom Fields is published by WP Engine; Secure Custom Fields is the WordPress.org fork. Both define the same functions, so every step in this guide works with either. Never activate both at once.
Why does my section still show when the field looks empty?
Three usual causes. The field name in the dropdown does not match the meta key actually saved. The condition sits on a widget rather than the wrapper you want removed. Or a page cache is serving HTML generated before you set the condition. Clear the cache and re-test in a private window.
Why does my section disappear when the number field is 0?
Because the not-empty check uses PHP empty(), which treats zero, the string 0, false and null as empty. A Number field holding a real zero therefore reads as blank. Use greater than or equal to 0 instead of the not-empty check when zero is a valid value.
Should I use Keep HTML or let the plugin remove the element?
Remove it. Keep HTML only hides the element with CSS, so its markup, links and embedded iframes still reach the browser. Turn Keep HTML on only when something inside the element needs to initialise while hidden, such as a script that measures its container.
Does this work with a caching plugin?
Yes, when the condition depends on post data. The cached page already belongs to that post, so the stored HTML is correct. Clear the cache after editing the template. Conditions based on the visitor, such as login status or cart contents, need cache exclusions instead.
Can I set the condition once instead of on every post?
Yes, and you should. Apply it to your single post template in the theme builder rather than to individual posts. The condition then evaluates per post automatically. Setting it post by post is the most common reason this job takes an afternoon instead of five minutes.
Does it work with ACF Repeater and relationship fields?
The empty and not-empty checks do, because a Repeater with no rows is an empty array. String comparisons such as contains will not behave as you expect on array values. For logic that depends on what is inside the array, use the custom PHP condition in the paid plugin.
The call
Install the free Dynamic Visibility for Elementor plugin, put the condition on your single post template, set Post Field Status to Not empty, and leave Keep HTML off. That is the whole job for most sites, and it costs nothing.
Upgrade to Dynamic Content for Elementor when you hit logic a dropdown cannot express, not before. Stay inside JetEngine if you already pay Crocoblock, and use the Regexp workaround rather than fighting the empty check. And before you file a bug report against any of them, put a real zero in the field and see whether that was the problem all along.





[…] showing something only when a field has a value. If that is all you need, our walkthrough on how to hide a widget when an ACF field is empty covers the […]
[…] it in the layout with no PHP. The awkward part is empty fields, which leave gaps: our notes on hiding a widget when an ACF field is empty cover the fix, and the wider dynamic visibility plugins comparison covers the cases Elementor alone […]