Question
When adding JavaScript to an HTML document, where should the <script> tags be placed? I remember hearing that placing scripts in the <head> can be problematic, but putting them at the start of the <body> can also delay rendering because the browser must parse the JavaScript before continuing. That seems to make the end of the <body> a sensible option.
So, what is the correct place to put <script> tags?
I am specifically using jQuery, but a general HTML and JavaScript explanation is also helpful.
Short Answer
By the end of this page, you will understand why script placement affects page loading, rendering, and DOM access. You will learn when to put scripts in the <head>, when to place them near the end of <body>, and how defer and async change the usual rules.
Concept
JavaScript in HTML is not just about where the code lives. It affects when the browser stops to download it, parses it, and runs it.
Why script placement matters
When the browser reads HTML, it processes the document from top to bottom. A normal <script> tag without special attributes is typically render-blocking:
- the browser pauses HTML parsing
- it may fetch the script file
- it executes the script
- only then does it continue parsing the page
That means script placement can affect:
- page rendering speed
- whether elements already exist in the DOM when your code runs
- user experience, especially on slower networks
The traditional advice
Historically, developers often placed scripts just before </body> because:
- the HTML content loads first
- the page becomes visible sooner
- scripts run after most of the DOM has already been parsed
Example:
<body>
<h1>Hello</h1>
<p>Content appears before script runs.</p>
<script src="app.js">
Mental Model
Think of the browser like someone reading instructions while building furniture.
- The HTML is the assembly guide.
- The browser reads it from top to bottom.
- A normal
<script>tag is like an urgent note saying: stop building and do this task right now.
If that note appears too early, the builder stops before the furniture is fully assembled.
Using defer is like saying: download these extra instructions now, but wait until the main assembly is done before following them.
Putting a script at the end of <body> is like placing the extra instructions after the main guide, so the builder sees them only after most of the work is already complete.
So the key idea is:
- normal scripts interrupt parsing
- deferred scripts wait until parsing finishes
- async scripts happen independently and may run at unpredictable times
Syntax and Examples
Core syntax
1. Traditional script at the end of <body>
<body>
<h1 id="title">Welcome</h1>
<script src="app.js"></script>
</body>
Use this when you want the DOM mostly available before the script runs.
2. Modern script in <head> with defer
<head>
<script src="app.js" defer></script>
</head>
This is a common best practice for application code.
3. Async script
<head>
< = >
Step by Step Execution
Consider this HTML:
<!doctype html>
<html>
<head>
<script src="app.js" defer></script>
</head>
<body>
<p id="status">Waiting...</p>
</body>
</html>
And this JavaScript:
const statusEl = document.getElementById("status");
statusEl.textContent = "Ready";
What happens step by step
- The browser starts reading the HTML document.
- It reaches
<script src="app.js" defer></script>in the<head>. - Because of
defer, the browser starts downloading but .
Real World Use Cases
Common practical uses
Application scripts
Main frontend code for a website or web app is often loaded with defer:
<script src="main.js" defer></script>
This lets the page parse first while still organizing scripts in the <head>.
UI interactions
Scripts that attach click handlers, form validation, or menu behavior usually need the DOM to exist first.
Examples:
- opening a mobile menu
- validating a signup form
- attaching event listeners to buttons
- updating text on the page
Analytics and tracking
Independent scripts are often loaded with async because execution order usually does not matter.
Examples:
- analytics
- ad scripts
- tracking pixels
- third-party widgets
Server-rendered pages
Many server-rendered applications output HTML first and then attach JavaScript after the markup is present. This can be done with:
- scripts at the end of
<body> - deferred scripts in
Real Codebase Usage
In real projects, developers usually choose script placement based on dependency order, rendering performance, and how soon code must run.
Common patterns
1. Deferred application bundles
A typical modern setup:
<head>
<script src="vendor.js" defer></script>
<script src="app.js" defer></script>
</head>
Why this is common:
- files download while HTML is parsed
- execution order is preserved for deferred scripts
- DOM is ready when the scripts run
2. Guarding against missing elements
Even when scripts load correctly, developers often protect code:
const modal = document.getElementById("modal");
if (!modal) {
return;
}
This is useful when the same script runs on multiple pages.
3. Early returns
Common Mistakes
1. Running code before the DOM exists
Broken example:
<head>
<script>
const el = document.getElementById("title");
el.textContent = "Hello";
</script>
</head>
<body>
<h1 id="title">Original</h1>
</body>
Problem:
- the script runs before the
<h1>is parsed elisnull
Fix:
- move the script to the end of
<body>, or - use
defer
2. Using async for dependent scripts
Broken example:
Comparisons
| Approach | Where placed | Blocks HTML parsing? | Keeps execution order? | Good for |
|---|---|---|---|---|
Normal <script> | <head> or <body> | Yes | Yes | Small scripts that must run immediately |
<script> at end of <body> | End of body | Less harmful to rendering | Yes | Traditional DOM-dependent scripts |
<script defer> | Usually <head> | No during parsing | Yes | Most application code |
Cheat Sheet
Quick rules
- A normal
<script>blocks HTML parsing while it loads and runs. - Scripts that touch DOM elements must run after those elements exist.
- For most modern pages, use:
<script src="app.js" defer></script>
- If you do not use
defer, place scripts near the end of<body>. - Use
asynconly when script order does not matter.
Common patterns
Modern default
<head>
<script src="app.js" defer></script>
</head>
Traditional default
<body>
<!-- page content -->
<script =>
FAQ
Should script tags go in the head or body?
For most modern application code, put them in the <head> with defer. Without defer, placing them near the end of <body> is a common choice.
Is putting scripts in the head always bad?
No. It is only a problem when scripts block parsing or run before needed DOM elements exist. Using defer solves this in many cases.
Is the end of the body still a good place for scripts?
Yes. It is still a valid and simple pattern, especially for traditional pages or small projects.
When should I use async instead of defer?
Use async for scripts that are independent and do not rely on order, such as analytics or ads.
Why does my JavaScript say an element is null?
Your script probably ran before the browser parsed that element. Use defer, move the script lower, or wait for DOM ready.
Do I still need $(document).ready() with deferred scripts?
Often no, because deferred scripts run after HTML parsing. In older jQuery codebases, however, you will still see it frequently.
Which script should come first: jQuery or my code?
jQuery must load before any script that uses it.
Should I put JavaScript inside HTML attributes like onclick?
Mini Project
Description
Build a small page that updates text and attaches a button click handler without failing due to script timing. This demonstrates correct script placement and shows how DOM-dependent JavaScript should be loaded in a practical page.
Goal
Create an HTML page where JavaScript safely updates page content and responds to a button click using a deferred script.
Requirements
- Create an HTML page with a heading, a paragraph, and a button.
- Load the JavaScript from an external file.
- Use a script-loading approach that avoids running code before the DOM is parsed.
- Change the paragraph text when the page loads.
- Show an alert or change text when the button is clicked.
Keep learning
Related questions
Can You Style Half a Character in CSS? Text Effects with CSS and JavaScript
Learn how to style half of a character using CSS and JavaScript, including overlay techniques for dynamic text effects.
Check If a Checkbox Is Checked with jQuery
Learn how to check whether a checkbox is checked in jQuery using the correct selector, with examples, mistakes, and practical patterns.
Convert HTML and CSS to PDF in PHP: Options, Limits, and Practical Approaches
Learn how HTML-to-PDF conversion works in PHP, why CSS support varies, and how to choose a practical approach for Linux web servers.