How to Add JavaScript to HTML: Internal, External and defer

JavaScript can work with an HTML page only after the browser loads your JavaScript code.

You can add JavaScript to HTML in two common ways:

  1. Write JavaScript inside a <script> element.
  2. Put JavaScript in a separate .js file and connect that file to the HTML.

For most real websites, an external JavaScript file is the better choice because it keeps your HTML cleaner and your JavaScript easier to manage.

In this lesson, you will learn each method, where the <script> element belongs, what src does, and when to use defer.

What You Will Learn

By the end of this lesson, you will know how to:

  • write JavaScript inside HTML
  • create an external .js file
  • connect JavaScript to HTML
  • use the src attribute correctly
  • choose where to place <script>
  • understand why script placement matters
  • use the defer attribute
  • recognize common file-path mistakes
  • check whether your JavaScript file loaded correctly

You should already understand the basic role of JavaScript. If not, start with What Is JavaScript? How It Works With HTML and CSS.

The HTML <script> Element

HTML uses the <script> element to load or contain JavaScript.

The smallest example is:

<script>
    console.log("Hello JavaScript");
</script>

Everything between the opening and closing <script> tags is treated as JavaScript.

Open the browser Console and you should see:

Hello JavaScript

The <script> element gives the browser access to your JavaScript code.

Method 1: Add JavaScript Directly Inside HTML

JavaScript written directly inside an HTML document is often called internal JavaScript.

Here is a complete example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Internal JavaScript</title>
</head>
<body>

    <h1 id="title">Hello</h1>

    <script>
        const title = document.querySelector("#title");
        title.textContent = "Hello JavaScript";
    </script>

</body>
</html>

What happens here?

This HTML creates a heading:

<h1 id="title">Hello</h1>

Then JavaScript finds it:

const title = document.querySelector("#title");

Finally:

title.textContent = "Hello JavaScript";

changes the text displayed on the page.

The browser now shows:

Hello JavaScript

When Is Internal JavaScript Useful?

Internal JavaScript can be useful for:

  • very small examples
  • learning JavaScript
  • quick testing
  • tiny single-page demos

For a real website with several pages or larger scripts, external JavaScript files are usually easier to maintain.

Method 2: Use an External JavaScript File

An external JavaScript file stores your code separately from the HTML.

For example, your project could contain:

my-project/
│
├── index.html
└── script.js

The HTML remains in:

index.html

Your JavaScript goes in:

script.js

Step 1: Create the HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>External JavaScript</title>
</head>
<body>

    <button id="button">Click Me</button>

    <script src="script.js"></script>

</body>
</html>

Step 2: Create script.js

const button = document.querySelector("#button");

button.addEventListener("click", () => {
    console.log("Button clicked");
});

Now open index.html.

When you click the button, the browser Console should display:

Button clicked

What Does src Mean?

In this code:

<script src="script.js"></script>

src means source.

It tells the browser where the JavaScript file is located.

Here:

script.js

is in the same folder as the HTML file.

The browser loads that file and executes its JavaScript.

Why Use External JavaScript?

External files make projects easier to organize.

Instead of mixing everything together:

<h1>...</h1>

<style>
    ...
</style>

<script>
    ...
</script>

you can separate the project:

index.html
style.css
script.js

Each file has one clear job.

  • HTML stores page structure.
  • CSS stores styles.
  • JavaScript stores behavior.

This becomes much more important as a website grows.

Beginners often run into problems when script.js is inside another folder.

Suppose your project looks like this:

my-project/
│
├── index.html
└── js/
    └── script.js

This will not work:

<script src="script.js"></script>

because script.js is not beside index.html.

Use:

<script src="js/script.js"></script>

The path tells the browser:

Open the js folder, then load script.js.

Going Up One Folder

Consider:

project/
│
├── js/
│   └── script.js
│
└── pages/
    └── about.html

From about.html, the JavaScript file is outside the current folder.

You can use:

<script src="../js/script.js"></script>

../ means:

Go up one folder.

Understanding file paths is important because many beginner JavaScript errors are actually path errors.

Where Should the <script> Tag Go?

There are two common locations:

  • inside <head>
  • near the end of <body>

The location can affect when the browser executes your JavaScript.

JavaScript at the End of <body>

A traditional approach is:

<!DOCTYPE html>
<html>
<head>
    <title>Example</title>
</head>
<body>

    <button id="button">Click Me</button>

    <script src="script.js"></script>
</body>
</html>

Here, the browser reaches the button before it reaches the JavaScript file.

That means the HTML element already exists when your JavaScript tries to find it.

This is why older tutorials often tell beginners:

Put your JavaScript before </body>.

That approach still works.

However, modern HTML gives us another useful option: defer.

What Is the defer Attribute?

You can place an external script inside <head> and add defer.

<head>
    <script src="script.js" defer></script>
</head>

A complete example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript defer Example</title>

    <script src="script.js" defer></script>
</head>
<body>

    <button id="button">Click Me</button>

</body>
</html>

script.js:

const button = document.querySelector("#button");

button.addEventListener("click", () => {
    console.log("Button clicked");
});

This works even though the <script> appears before the button in the HTML source.

What Does defer Do?

With a normal external script in <head>, the browser can pause HTML parsing while it loads and executes that script.

For example:

<script src="script.js"></script>

With:

<script src="script.js" defer></script>

the browser can continue parsing the HTML while the external JavaScript file is being downloaded.

The deferred script executes after the HTML document has been parsed.

For many normal website scripts, this makes defer a useful beginner-friendly choice.

For most examples in this JavaScript course, use:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>My JavaScript Project</title>

    <link rel="stylesheet" href="style.css">

    <script src="script.js" defer></script>
</head>
<body>

    <h1>My JavaScript Project</h1>

</body>
</html>

Your files:

project/
│
├── index.html
├── style.css
└── script.js

This structure is simple, clean and suitable for many beginner projects.

What Happens Without defer?

Look at this HTML:

<head>
    <script src="script.js"></script>
</head>
<body>

    <button id="button">Click Me</button>

</body>

Imagine script.js contains:

const button = document.querySelector("#button");

console.log(button);

If the script executes before the browser has parsed the button, button may not contain the element you expect.

This is one reason script timing matters.

Using:

<script src="script.js" defer></script>

helps avoid that problem for external classic scripts loaded in the document head.

defer vs Putting JavaScript Before </body>

Both approaches can work.

Option 1

<head>
    <script src="script.js" defer></script>
</head>

Option 2

<body>

    ...

    <script src="script.js"></script>
</body>

For this tutorial series, I recommend the first pattern:

<script src="script.js" defer></script>

It keeps your stylesheet and JavaScript references together in <head> while allowing the HTML to be parsed before the deferred script executes.

What About async?

You may also see:

<script src="script.js" async></script>

async and defer are not the same.

A simple beginner distinction is:

defer

  • downloads while HTML continues parsing
  • runs after HTML parsing is complete
  • preserves execution order among deferred classic scripts

async

  • downloads while HTML continues parsing
  • executes when it finishes downloading
  • does not wait for all HTML parsing to finish
  • does not guarantee order between multiple async scripts

For scripts that depend on page elements or on one another, defer is often easier to reason about.

You do not need async for the basic examples in this course.

External Module Scripts

Later, when you learn JavaScript modules, you may see:

<script type="module" src="app.js"></script>

Module scripts behave differently from normal classic scripts and are deferred by default.

Do not worry about modules yet.

They will have their own lesson after you understand functions, arrays, objects and other fundamentals.

Can You Use src and JavaScript Inside the Same <script>?

Avoid doing this:

<script src="script.js">
    console.log("Hello");
</script>

When a <script> element uses src, put the JavaScript in the external file.

Use:

<script src="script.js"></script>

and inside script.js:

console.log("Hello");

Keep the two approaches separate.

Do You Need type="text/javascript"?

You may see older examples like this:

<script type="text/javascript" src="script.js"></script>

For normal JavaScript in modern HTML, you do not need:

type="text/javascript"

This is enough:

<script src="script.js" defer></script>

Do not copy unnecessary syntax from old tutorials.

Inline JavaScript Attributes

You may also encounter HTML like:

<button onclick="alert('Hello')">Click Me</button>

This is JavaScript written directly in an HTML attribute.

It works, but it mixes behavior with markup.

For learning modern frontend development, prefer:

<button id="button">Click Me</button>

and:

const button = document.querySelector("#button");

button.addEventListener("click", () => {
    alert("Hello");
});

This keeps your HTML and JavaScript easier to organize.

Real Website Example: Mobile Menu

Imagine this HTML:

<button id="menuButton">Menu</button>

<nav id="menu" hidden>
    <a href="/">Home</a>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
</nav>

Connect your JavaScript:

<script src="script.js" defer></script>

Then use:

const menuButton = document.querySelector("#menuButton");
const menu = document.querySelector("#menu");

menuButton.addEventListener("click", () => {
    menu.hidden = !menu.hidden;
});

What happens?

This line:

const menuButton = document.querySelector("#menuButton");

finds the button.

This line:

const menu = document.querySelector("#menu");

finds the navigation menu.

Then:

menuButton.addEventListener("click", () => {

waits for a click.

Finally:

menu.hidden = !menu.hidden;

switches the hidden state.

If the menu is hidden, it becomes visible.

If it is visible, it becomes hidden.

This is a small example of how an external JavaScript file can add real website behavior.

How to Check Whether Your JavaScript File Loaded

Suppose nothing happens when you click your button.

Start with:

console.log("script loaded");

Put that at the top of script.js.

Then open the browser Console.

If you see:

script loaded

the file is being loaded.

If you do not see it, check:

  • file name
  • folder name
  • src path
  • spelling
  • browser Console errors

This simple check can save a lot of time.

Common Beginner Mistakes

Wrong File Name

HTML:

<script src="script.js" defer></script>

But your actual file is:

scripts.js

Those are different names.

The path must match exactly.

Wrong Folder Path

Your file is:

js/script.js

but HTML says:

<script src="script.js"></script>

Use:

<script src="js/script.js"></script>

Using a Selector That Does Not Exist

HTML:

<button id="sendButton">Send</button>

JavaScript:

document.querySelector("#submitButton");

The IDs do not match.

Use the same value in both files.

Forgetting defer When Loading a Script in <head>

If your script needs page elements, loading a normal classic script too early can cause problems.

Use:

<script src="script.js" defer></script>

for the examples in this series.

Writing JavaScript Outside <script>

This will not work correctly inside normal HTML:

<body>

const name = "Riya";

</body>

JavaScript inside an HTML document needs a <script> element:

<script>
    const name = "Riya";
</script>

or an external file.

Adding <script> Tags Inside .js Files

Do not put:

<script>

inside script.js.

The .js file contains JavaScript only:

console.log("Hello");

The <script> element belongs in HTML.

Best Practices

For beginner projects:

  • keep JavaScript in a separate .js file
  • use descriptive file names
  • use defer for normal external scripts loaded in <head>
  • keep folder paths simple
  • check the Console when something fails
  • avoid inline onclick handlers in new projects
  • keep HTML, CSS and JavaScript responsibilities clear

A clean beginner project might look like:

my-project/
│
├── index.html
├── css/
│   └── style.css
└── js/
    └── script.js

Then your HTML can contain:

<link rel="stylesheet" href="css/style.css">
<script src="js/script.js" defer></script>

Beginner Exercise

Create this folder:

button-project/
│
├── index.html
└── script.js

Add this to index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Button Project</title>

    <script src="script.js" defer></script>
</head>
<body>

    <h1 id="message">Waiting...</h1>
    <button id="button">Click Me</button>

</body>
</html>

Add this to script.js:

const button = document.querySelector("#button");
const message = document.querySelector("#message");

button.addEventListener("click", () => {
    message.textContent = "JavaScript is connected!";
});

Open the HTML file.

Click the button.

The heading should change from:

Waiting...

to:

JavaScript is connected!

Challenge Exercise

Add another button:

<button id="resetButton">Reset</button>

Make that button change the heading back to:

Waiting...

Your HTML should remain separate from your JavaScript.

Try to solve it before looking for another example.

Frequently Asked Questions

How do I add JavaScript to HTML?

You can put JavaScript inside a <script> element or connect an external .js file using the src attribute.

Use:

<script src="script.js" defer></script>

Make sure the path matches the actual file location.

Where should JavaScript go in HTML?

A common modern approach is to load an external script in <head> with defer.

Another valid approach is to place a normal script near the end of <body>.

What does src do in a script tag?

src tells the browser where the external JavaScript file is located.

What does defer mean in JavaScript?

defer allows an external classic script to download while the browser continues parsing HTML. The script then runs after the HTML document has been parsed.

Should beginners use defer?

For the standard external scripts used throughout this tutorial series, yes. It provides a clear and practical loading pattern.

Is async the same as defer?

No.

Both can download scripts without waiting for normal HTML parsing to finish, but their execution behavior differs. defer waits until parsing is complete and preserves order among deferred classic scripts. async executes when its download finishes.

Do I need type="text/javascript"?

Not for normal JavaScript in modern HTML.

Use:

<script src="script.js" defer></script>

Can I have more than one JavaScript file?

Yes.

For example:

<script src="js/menu.js" defer></script>
<script src="js/form.js" defer></script>

As projects become larger, separating code into logical files can make maintenance easier.

Why is my JavaScript file not working?

Common reasons include:

  • wrong file path
  • wrong filename
  • JavaScript syntax error
  • selector does not match the HTML
  • script executes before the required HTML exists

Check the browser Console first.

Summary

There are two main beginner-friendly ways to add JavaScript to HTML.

You can write JavaScript inside:

<script>
    // JavaScript
</script>

or connect an external file:

<script src="script.js" defer></script>

For real projects, external files are usually easier to organize.

You also learned that:

  • src points to your JavaScript file
  • file paths must match your project folders
  • script timing matters
  • defer is useful for external scripts loaded in <head>
  • async has different execution behavior
  • inline event attributes are usually unnecessary in modern projects
  • the browser Console helps you find loading and coding error.
James Parker

James Parker

James Parker is a technology writer and WordPress enthusiast who shares practical guides on SEO, web development, AI tools, and digital growth. He focuses on creating easy-to-follow tutorials that help beginners and professionals build better websites and improve their online presence.