The reliable WordPress method is to enqueue assets with wp_enqueue_style() and wp_enqueue_script() from the hook that matches where they are needed. This lets WordPress, themes and plugins resolve dependencies, control loading order and avoid duplicate or hard-coded tags in templates.
Use the enqueue system instead of hard-coding tags
Do not normally paste <link> or <script> tags into header.php or a template file. Enqueue each file with a unique handle, its URL, dependencies and a version. WordPress then prints the appropriate tags when the page is generated.
| Asset | Function | Typical hook |
|---|---|---|
| CSS stylesheet | wp_enqueue_style() |
wp_enqueue_scripts |
| Classic JavaScript | wp_enqueue_script() |
wp_enqueue_scripts |
| Admin CSS or JavaScript | The same enqueue functions | admin_enqueue_scripts |
| JavaScript module | wp_enqueue_script_module() |
Use the appropriate front-end or admin enqueue flow |
Registration and enqueueing are different: wp_register_script() or wp_register_style() records an asset for later use, but registration alone does not put it in the page output.
Enqueue theme CSS and JavaScript
For front-end theme files, attach one callback to wp_enqueue_scripts. The following example assumes the files are stored in assets/css/main.css and assets/js/main.js.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
<?php
function example_theme_assets() {
wp_enqueue_style(
'example-theme-main',
get_theme_file_uri( 'assets/css/main.css' ),
array(),
'1.0.0'
);
wp_enqueue_script(
'example-theme-main',
get_theme_file_uri( 'assets/js/main.js' ),
array(),
'1.0.0',
array( 'in_footer' => true )
);
}
add_action( 'wp_enqueue_scripts', 'example_theme_assets' );
Replace the handles, paths and version with values for your project. Handles must be unique within the WordPress installation; prefixing them with a theme or company name helps prevent collisions.
Where to put the code
Put theme-specific enqueue code in the theme’s PHP code, commonly functions.php or an included file. A child theme should enqueue its own files from the child theme rather than editing the parent theme. The theme’s style.css remains the required stylesheet containing theme metadata; additional styles should still be managed through the enqueue API.
Add dependencies and preserve order
The third argument is an array of dependency handles. If your script uses WordPress’s registered jQuery handle, for example, declare it instead of loading a second copy:
wp_enqueue_script(
'example-interactions',
get_theme_file_uri( 'assets/js/interactions.js' ),
array( 'jquery' ),
'1.0.0',
array( 'in_footer' => true )
);
WordPress uses the dependency graph to determine order. A dependency handle that has not been registered cannot be loaded for the dependent script, so check the handle name and ensure the dependency is available.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Enqueue plugin assets correctly
A plugin should use its own front-end callback and build the URL from the plugin location rather than assuming a theme path.
<?php
function example_plugin_assets() {
wp_enqueue_style(
'example-plugin-public',
plugins_url( 'assets/css/public.css', __FILE__ ),
array(),
'1.0.0'
);
wp_enqueue_script(
'example-plugin-public',
plugins_url( 'assets/js/public.js', __FILE__ ),
array(),
'1.0.0',
array( 'in_footer' => true )
);
}
add_action( 'wp_enqueue_scripts', 'example_plugin_assets' );
If the plugin file is in a different directory, adjust the path passed to plugins_url() so it resolves to the real asset location. Keep plugin assets separate from theme assets because a plugin can remain active when the site’s theme changes.
Load CSS and JavaScript only in the admin
Use admin_enqueue_scripts for dashboard screens. Its callback receives the current screen hook suffix, which lets you avoid loading files on every admin page.
<?php
function example_plugin_admin_assets( $hook_suffix ) {
if ( 'settings_page_example-plugin' !== $hook_suffix ) {
return;
}
wp_enqueue_style(
'example-plugin-admin',
plugins_url( 'assets/css/admin.css', __FILE__ ),
array(),
'1.0.0'
);
wp_enqueue_script(
'example-plugin-admin',
plugins_url( 'assets/js/admin.js', __FILE__ ),
array(),
'1.0.0',
array( 'in_footer' => true )
);
}
add_action( 'admin_enqueue_scripts', 'example_plugin_admin_assets' );
Use the actual screen hook for your page. Conditional loading reduces unnecessary requests and prevents admin code from affecting unrelated screens.
Rank #3
Choose a version and cache-busting method
The version argument is appended to the asset URL as a version query value. Set it to your release or build version so browsers can fetch a changed file after deployment. Avoid leaving a changing development timestamp in production unless you deliberately accept a cache miss on every request.
Build systems can provide dependency and version metadata alongside compiled files. Use that generated metadata when available rather than manually maintaining a dependency list that can become stale.
Control script execution with footer, defer and async
Passing array( 'in_footer' => true ) asks WordPress to print a classic script in the footer location. It does not by itself make the script asynchronous.
Since WordPress 6.3, wp_enqueue_script() also accepts a strategy value of defer or async:
Rank #4
wp_enqueue_script(
'example-deferred',
get_theme_file_uri( 'assets/js/deferred.js' ),
array(),
'1.0.0',
array(
'in_footer' => true,
'strategy' => 'defer',
)
);
| Strategy | Execution behavior | Use when |
|---|---|---|
defer |
Downloads without blocking parsing, then executes after parsing while preserving document order. | The script depends on another script or on the parsed document. |
async |
Executes as soon as downloading finishes; order relative to other asynchronous scripts is not guaranteed. | A self-contained script has no ordering requirement. |
WordPress evaluates the dependency tree when applying a requested strategy and may choose a more conservative result to protect dependencies. Do not use async for code that must run after another asset or that assumes the DOM is ready.
Use JavaScript modules when the project requires them
For module-based builds, WordPress 6.5 identifies wp_enqueue_script_module() as the preferred module-enqueue function. This is a specialized path; ordinary browser scripts should continue to use wp_enqueue_script(). Confirm that the project’s minimum WordPress version supports the API before adopting it.
Add small inline configuration safely
For a short configuration value or snippet that belongs to an enqueued file, enqueue the file first and attach the inline code to its handle:
wp_enqueue_script(
'example-app',
get_theme_file_uri( 'assets/js/app.js' ),
array(),
'1.0.0',
array( 'in_footer' => true )
);
wp_add_inline_script(
'example-app',
'window.exampleSettings = ' . wp_json_encode( array(
'mode' => 'production',
) ) . ';',
'before'
);
Use wp_add_inline_style() for CSS associated with an already enqueued stylesheet:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
wp_enqueue_style(
'example-theme-main',
get_theme_file_uri( 'assets/css/main.css' ),
array(),
'1.0.0'
);
wp_add_inline_style(
'example-theme-main',
'.notice { margin-block: 1rem; }'
);
These helpers keep inline code attached to a declared asset. They are better suited to small, generated or page-specific additions than placing reusable files directly in template output.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Load assets conditionally when their scope is limited
Global assets are appropriate for code used throughout the site. For a page, block or feature used only in some contexts, wrap the enqueue call in a condition such as a page check, post-type check or screen check. Block themes and block-based builds can enqueue block-specific styles selectively, avoiding a site-wide stylesheet for a single block.
Keep the condition next to the enqueue logic and test both the condition’s true and false paths. A misplaced conditional is a common reason for a script appearing on every page or not appearing where it is needed.
Common failures and fixes
- Nothing appears in the page source: confirm that the callback is attached to the correct hook and that you called an enqueue function, not only a register function.
- The browser reports a 404: inspect the generated URL and correct the theme or plugin path passed to
get_theme_file_uri()orplugins_url(). - A dependency runs too late or is missing: use the dependency’s registered handle and verify that it is registered before the dependent asset is resolved.
- Changes do not show: increment the asset version or use the build-generated version so caches recognize the new file.
- Code breaks after adding
async: remove the asynchronous strategy or switch todeferwhen execution order matters. - Admin styles affect the public site: move admin-only code to
admin_enqueue_scripts; move public assets towp_enqueue_scripts.
A practical decision checklist
- Identify whether the file belongs to a theme, a plugin, the public front end or an admin screen.
- Choose a unique handle and the correct WordPress hook.
- Build the URL from the asset’s real theme or plugin location.
- Declare every registered dependency and choose a meaningful version.
- Decide whether the asset is global, conditional or block-specific.
- Use footer placement,
deferorasynconly when its execution behavior matches the code’s requirements. - Attach small inline code with
wp_add_inline_script()orwp_add_inline_style()after enqueueing the parent asset. - Test the generated URL, browser console, dependency order and cache behavior in both logged-in and logged-out contexts.
Bottom line
Proper WordPress asset loading means declaring CSS and JavaScript through the enqueue APIs, using the hook that matches the execution context, naming dependencies explicitly and selecting loading strategies deliberately. This approach works with WordPress’s asset manager instead of competing with it, while keeping theme, plugin and admin code maintainable.
Quick Recap
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.

