The HTML script element embeds or loads JavaScript code to make static markup interactive. JavaScript lets your page validate forms, fetch live API data, update text dynamically, and respond to button clicks or keyboard shortcuts.
You can place short snippets directly inside script tags, or keep code cleanly organized in external .js files linked via script src="app.js". External scripts allow browser caching and keep HTML templates easy to read.
Notice that even when referencing an external file with src, script is not a void element—you must always include the closing script tag.
Where you place script tags affects page load speed. A plain script src="app.js" inside head pauses HTML parsing while the browser downloads and runs the script. Adding defer downloads the file in parallel and executes it safely after the HTML document finishes parsing.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML JavaScript Demo</title>
<script src="/js/analytics.js" async></script>
<script src="/js/app.js" defer></script>
</head>
<body>
<h2 id="status-heading">Waiting for interaction</h2>
<button id="toggle-btn" type="button">Activate Status</button>
<script>
const btn = document.getElementById('toggle-btn');
const heading = document.getElementById('status-heading');
btn.addEventListener('click', () => {
heading.textContent = 'Status Active!';
});
</script>
<noscript>
<p>Please enable JavaScript to use interactive controls on this page.</p>
</noscript>
</body>
</html>
Use defer for application scripts that depend on DOM elements or execution order, and async for independent third-party analytics scripts. Include noscript when critical navigation or widgets require JavaScript.
head without defer or DOMContentLoaded returns null from document.getElementById().script src="app.js" tags: HTML parsers ignore self-closing slashes on script, causing the rest of the page to break.onclick="..." handlers everywhere: Attach events cleanly via addEventListener inside your JavaScript file.Both download scripts without blocking HTML parsing, but async runs immediately when downloaded (in any order), while defer waits until HTML parsing finishes and preserves script order.
Putting script src="..." defer in head is modern best practice because the browser starts downloading the script earlier without blocking rendering.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.