Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › CSS

How to Use wp_enqueue_scripts to Load CSS and JavaScript in WordPress

By Freedom251 Team · · 10 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use the wp_enqueue_scripts action for front-end assets, then call wp_enqueue_style() and wp_enqueue_script() from the callback attached to that action. WordPress uses each asset’s handle, URL, dependencies, version, and loading options to print files in the correct place and order.

What wp_enqueue_scripts does

wp_enqueue_scripts is the front-end action for registering and enqueuing stylesheets and JavaScript. It runs while WordPress prepares the public-facing page, so it is the right context for assets used by posts, pages, archives, templates, and other visitor-facing requests.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The WordPress Developer Resources hook reference describes it as “the proper hook to use when enqueuing scripts and styles that are meant to appear on the front end.” Enqueuing is preferable to writing <link> or <script> tags directly into a theme because WordPress can then track handles, resolve dependencies, avoid duplicate registrations, add version strings, and apply loading strategies.

Choose the hook that matches the request

Where the asset is used Hook Typical examples
Public site wp_enqueue_scripts Theme CSS, front-end interactions, block enhancements
WordPress administration admin_enqueue_scripts Editor or settings-screen CSS and JavaScript
Login screen login_enqueue_scripts Login-page branding or behavior

Putting an administration asset on wp_enqueue_scripts, or a front-end asset on admin_enqueue_scripts, does not move it to the other context. Attach the callback to the hook that actually runs where the file is needed.

A minimal theme implementation

Add one callback to your theme’s PHP code, preferably in the theme’s main setup file or a dedicated enqueue file. The following example loads a stylesheet and a classic JavaScript file on every front-end request:

<?php
function mytheme_enqueue_assets() {
    wp_enqueue_style(
        'mytheme-main',
        get_parent_theme_file_uri( 'assets/css/main.css' ),
        array(),
        wp_get_theme()->get( 'Version' ),
        'all'
    );

    wp_enqueue_script(
        'mytheme-main',
        get_parent_theme_file_uri( 'assets/js/main.js' ),
        array(),
        wp_get_theme()->get( 'Version' ),
        array(
            'strategy'  => 'defer',
            'in_footer' => true,
        )
    );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_assets' );

The stylesheet and script use different queues internally, so reusing the same handle text in this isolated example is technically possible, but distinct handles such as mytheme-main-style and mytheme-main-script make the code easier to audit and prevent confusion. In a real theme, give every asset a unique handle prefixed with the theme or plugin slug.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What this example assumes

  • assets/css/main.css and assets/js/main.js exist in the theme location returned by the helper.
  • The active theme eventually calls wp_head() and wp_footer(). Those template calls are required for normal output of enqueued assets.
  • The code runs in a front-end request. It is not an admin or login-screen enqueue.
  • The theme version in its metadata changes when you want a new version query string for both files.

Understanding every enqueue argument

Knowing what each argument controls makes it easier to diagnose missing files, cache problems, and incorrect load order.

Argument wp_enqueue_style() wp_enqueue_script()
Handle A unique identifier for the stylesheet. A unique identifier for the script.
Source The asset URL, or a path relative to the WordPress root where accepted. The asset URL, or a path relative to the WordPress root where accepted.
Dependencies Registered style handles that must be available first. Registered script handles that must be available first.
Version Version query-string value used for cache invalidation. Version query-string value used for cache invalidation.
Media or loading options A media value such as all, screen, print, or a media query. Modern arguments include in_footer, strategy => 'defer', and strategy => 'async'.

Handles

A handle is WordPress’s name for an asset. It is not the filename and does not need to match the filename. Use a stable, specific name such as mytheme-navigation rather than a generic value such as custom. A collision can cause another component’s registration to win and leave your URL or dependencies ignored.

Source URLs and theme helpers

Hard-coded site URLs break when a site changes domains, uses a different protocol, or runs in another environment. Theme file URL helpers construct the URL from the active installation. The minimal example uses get_parent_theme_file_uri() with a path relative to the parent theme. Keep the path aligned with the actual file and capitalization on the server.

Dependencies

Dependencies are arrays of registered handles. WordPress resolves them before the asset that depends on them. For example, a script that uses a library can declare that library’s handle:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php
function mytheme_register_assets() {
    wp_register_script(
        'mytheme-interactions',
        get_parent_theme_file_uri( 'assets/js/interactions.js' ),
        array( 'jquery' ),
        '1.0.0',
        array( 'strategy' => 'defer', 'in_footer' => true )
    );

    wp_enqueue_script( 'mytheme-interactions' );
}
add_action( 'wp_enqueue_scripts', 'mytheme_register_assets' );

Here, jquery must already be registered. If a dependency handle is unresolved, WordPress cannot establish the required relationship and the dependent asset may not be output. Check spelling and registration order before changing the JavaScript itself.

Versions and cache invalidation

An explicit version is useful when a file changes. Browsers and intermediate caches can treat a changed query string as a new resource. Passing wp_get_theme()->get( 'Version' ) ties the asset to the installed theme version, as shown above.

  • false uses the installed WordPress version as the version value.
  • null omits the version query string entirely.
  • A string such as '1.4.2' or a build-generated value gives you direct control over cache invalidation.

Do not use a changing value on every request merely to bypass caching; that defeats useful browser caching. Change the version when the file or its generated output changes.

CSS media

The final style argument defaults to all. Use screen for screen-only rules, print for print rules, or a valid media query when a stylesheet should be considered only under a specific condition. Media controls when the browser applies the stylesheet; it does not conditionally prevent WordPress from generating the link element for a request.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Register first or enqueue directly?

wp_enqueue_script() can register a script when you provide a source and enqueue it immediately. This is the simplest pattern when an asset is always needed in the callback.

Use wp_register_script() when you need to define an asset once and decide later whether to enqueue it, or when another script should list it as a dependency. Enqueuing a script whose handle has already been registered causes WordPress to include the registered asset. The same register-then-enqueue pattern is useful for styles when several pages share a common definition but only some requests need it.

<?php
function mytheme_register_shared_assets() {
    wp_register_style(
        'mytheme-gallery',
        get_parent_theme_file_uri( 'assets/css/gallery.css' ),
        array(),
        '2.1.0',
        'screen'
    );
}
add_action( 'wp_enqueue_scripts', 'mytheme_register_shared_assets' );

function mytheme_enqueue_gallery() {
    if ( is_page( 'gallery' ) ) {
        wp_enqueue_style( 'mytheme-gallery' );
    }
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_gallery' );

Keep registration and conditional enqueueing in the same front-end lifecycle unless a plugin deliberately exposes the handle for another component to use. A handle should be registered before a dependent asset asks for it.

Load assets only where they are needed

Leave the callback on wp_enqueue_scripts and put request checks inside it. Common conditional functions include is_page(), is_singular(), and checks for a custom template.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php
function mytheme_enqueue_contact_assets() {
    if ( ! is_page( 'contact' ) ) {
        return;
    }

    wp_enqueue_style(
        'mytheme-contact',
        get_parent_theme_file_uri( 'assets/css/contact.css' ),
        array(),
        '1.0.0',
        'screen'
    );

    wp_enqueue_script(
        'mytheme-contact',
        get_parent_theme_file_uri( 'assets/js/contact.js' ),
        array(),
        '1.0.0',
        array( 'strategy' => 'defer', 'in_footer' => true )
    );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_contact_assets' );

This approach keeps global assets predictable while avoiding contact-page code on unrelated requests. Apply the condition to the complete set of files that belongs together, including a stylesheet, script, and any separately registered dependency.

Footer placement, defer, and async

The modern arguments array for wp_enqueue_script() supports both placement and loading strategy:

Option Effect Use it when
in_footer => true Requests output in the footer queue instead of the normal head queue. The script does not need to execute before the page body is parsed.
strategy => 'defer' The browser can download while parsing and executes after parsing, preserving deferred ordering. The script should wait for document parsing and has dependencies whose order matters.
strategy => 'async' The browser can download and execute independently as soon as it is ready. The script is genuinely independent of other scripts and page-order timing.

Do not choose async simply because it sounds faster. An asynchronously executed file can run before a library or inline initialization code it expects. defer is generally the safer strategy for ordered application code, while footer placement is a separate decision about where WordPress prints the tag. Test both the browser console and the page behavior after changing either option.

Classic scripts versus JavaScript modules

For classic scripts, use wp_enqueue_script() with the arguments described above. Since WordPress 6.5, JavaScript modules have a dedicated wp_enqueue_script_module() function. Modules use their own dependency and import-map behavior, so do not treat a module import graph as if it were a list of classic script handles.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the module API when the compiled output is intended to run as an ES module and its imports should be handled through the module system. Keep classic and module entry points distinct; changing only the loading strategy on a classic enqueue does not convert that file into a module.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Using build-generated asset metadata

Build tools commonly emit an *.asset.php file beside a compiled JavaScript bundle. That file contains dependency and version metadata generated for the build. Pass those values to the enqueue call so the dependencies and cache key match the files that were actually compiled.

<?php
function mytheme_enqueue_build_output() {
    $asset = include get_parent_theme_file_path( 'build/app.asset.php' );

    wp_enqueue_script(
        'mytheme-app',
        get_parent_theme_file_uri( 'build/app.js' ),
        $asset['dependencies'],
        $asset['version'],
        array(
            'strategy'  => 'defer',
            'in_footer' => true,
        )
    );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_build_output' );

The generated dependency list must contain handles WordPress knows how to resolve. If a build lists a dependency that is not registered in WordPress, the browser cannot receive the intended load order merely because the name appears in the generated PHP file.

Why an enqueued file does not appear

When a stylesheet or script is missing, inspect the request in this order. It separates lifecycle errors from path, dependency, and browser errors.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Verify the context. Confirm the callback is attached to wp_enqueue_scripts for a public page. Move administration code to admin_enqueue_scripts and login code to login_enqueue_scripts.
  2. Verify that the callback runs. Check the function name in add_action(), PHP syntax, and whether an earlier fatal error stops execution. A callback that never runs cannot enqueue anything.
  3. Verify the active theme. Editing an inactive theme, or putting code in a parent theme while expecting a child-theme file path, can make a correct callback appear ineffective.
  4. Verify the handle and URL. Confirm the handle is unique and the helper points to the intended file. Open the generated URL directly and check its spelling, path, permissions, and case.
  5. Verify dependencies. Every dependency handle must be registered. An unresolved dependency can prevent the dependent asset from being output.
  6. Verify template hooks. The active theme must call wp_head() and wp_footer(). Without those calls, normal queued output has no place to print.
  7. Verify earlier registration. If another component registered the same handle first, WordPress ignores replacement parameters for an already registered handle. Rename your handle or change the original registration rather than repeatedly enqueueing the same identifier with different arguments.
  8. Inspect generated HTML. View the page source or DOM and search for the handle’s URL and version query string. If no tag exists, the problem is in PHP, context, dependency resolution, or template hooks.
  9. Inspect the network panel and console. A tag with a failed request indicates a URL, server, or permissions problem. A successful request followed by a JavaScript error indicates runtime code, dependency order, or strategy timing.

Distinguish a cache problem from an enqueue problem

If the expected tag is present but an old file is served, compare the URL’s version query string with the version you intended. Increase the explicit version or update the theme/build version when the asset changes. Passing null intentionally removes the query string; it should not be used as a cache-busting fix.

Distinguish a strategy problem from a missing-file problem

A missing tag points to registration, context, dependencies, or template output. A tag that exists but fails only at runtime points to execution timing. Temporarily remove async, use defer for ordered code, and verify that the file does not rely on inline code that executes earlier than the deferred script.

A practical implementation checklist

  • Attach front-end assets to wp_enqueue_scripts.
  • Give each style and script a unique, prefixed handle.
  • Use a theme file URL helper instead of a hard-coded site URL.
  • Declare dependencies as registered handles, not filenames or URLs.
  • Choose an explicit version, a theme version, or build-generated version deliberately.
  • Use false only when the WordPress version is the desired version value, and null only when no version query string is wanted.
  • Use conditional checks inside the callback for page-specific assets.
  • Use the modern arguments array for footer placement and defer/async.
  • Use wp_enqueue_script_module() for JavaScript modules on WordPress 6.5 and later.
  • Confirm wp_head() and wp_footer() exist in the active theme.
  • Inspect the generated HTML, network requests, and console before changing working enqueue code.

Putting the decisions together

A reliable enqueue implementation answers five questions in code: which request context needs the file, what unique handle identifies it, which URL contains the file, which registered handles must load first, and how versioning and execution timing should work. Start with a direct enqueue for an asset used everywhere, register first when conditional use or reuse demands it, and add conditions only after the unconditional version works. This keeps failures easy to localize while still giving WordPress enough metadata to manage output correctly.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

CSSJavaScriptPHPWordPressWordPress Themeswp_enqueue_scripts

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.