Every earlier example in this section wrote a plain <link> or <script> tag directly, to keep the focus on one idea at a time. A real theme never does this — CSS and JavaScript get loaded through wp_enqueue_style() and wp_enqueue_script() instead.
WordPress sites routinely run a dozen or more plugins, each with their own CSS and JS. Hardcoded tags have no way to know about any of that — a plugin might load the same library twice, or your theme's script might run before a library it depends on has loaded. Enqueuing puts every stylesheet and script through one shared system that can track dependencies and avoid duplicates automatically.
<?php
function mytheme_enqueue_assets() {
$uri = get_template_directory_uri();
$dir = get_template_directory();
wp_enqueue_style( 'mytheme-style', $uri . '/css/style.css', [], filemtime( $dir . '/css/style.css' ) );
wp_enqueue_script( 'mytheme-main', $uri . '/js/main.js', [ 'jquery' ], filemtime( $dir . '/js/main.js' ), true );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_assets' );Both functions take roughly the same arguments: a unique handle, the file's URL, an array of dependency handles, a version number, and (for scripts) whether to load it in the footer.
| Argument | What it's for |
|---|---|
| handle | A unique name other code can reference — 'jquery' as a dependency above refers to WordPress's own bundled copy, so it loads first automatically |
| src | Built with get_template_directory_uri(), never a hardcoded path — this keeps the theme portable if it's ever renamed or moved |
| deps | An array of handles that must load first — WordPress sorts the final load order for you |
| version | filemtime() (the file's last-modified time) is a common trick: it changes automatically every time the file is edited, which busts browser caches without hand-bumping a version number |
| in_footer (scripts only) | true loads the script near wp_footer() instead of in <head> — almost always what you want, since it doesn't block the page from rendering while the script downloads |
Not admin_enqueue_scripts
wp_enqueue_scripts is the correct hook for the public-facing site. It's easy to mix up with admin_enqueue_scripts (for wp-admin screens) — using the wrong one means your assets simply never load, with no error to explain why.
With assets loading properly, the next lesson covers the other thing every theme needs from functions.php — registering and outputting navigation menus.