What is Inline JavaScript?
There are two main ways to write inline JavaScript:
Script Tag
Write JS inside a script tag anywhere in your HTML file.
Event Attributes
Write JS directly on an HTML element like onclick to run code on click.
When to Use Inline JS
Inline JS is great for small projects, quick tests, and learning. For real projects, always use external JS files instead.
The Script Tag
1<!DOCTYPE html>2<html>3 <head>4 <title>My Page</title>5 </head>6 <body>7 <h1>Hello World</h1>89 <script>10 console.log("JavaScript is running!");11 alert("Welcome to my page!");12 </script>13 </body>14</html>
No Extra Files Needed
With the script tag, you just open one HTML file in your browser and it works. Perfect for learning and testing.
Where to Put the Script Tag
Inside the Head Tag
1<!DOCTYPE html>2<html>3 <head>4 <script>5 // This runs BEFORE the page loads6 // So document.getElementById won't find anything yet!7 let btn = document.getElementById("myBtn");8 console.log(btn); // null — element doesn't exist yet9 </script>10 </head>11 <body>12 <button id="myBtn">Click Me</button>13 </body>14</html>
Script in Head Runs Too Early
When a script runs in the head, the page body has not loaded yet. So you cannot access HTML elements. This is a very common beginner mistake.
At the Bottom of Body Tag
1<!DOCTYPE html>2<html>3 <head>4 <title>My Page</title>5 </head>6 <body>7 <button id="myBtn">Click Me</button>89 <!-- Script goes LAST, before closing body tag -->10 <script>11 // Page is fully loaded, so this works perfectly12 let btn = document.getElementById("myBtn");13 btn.addEventListener("click", function() {14 alert("Button clicked!");15 });16 </script>17 </body>18</html>
Put Scripts at the Bottom
Placing script tags just before the closing body tag means all HTML is already loaded. Your JavaScript can safely find and work with any element on the page.
| Location | When It Runs | Can Access HTML? | Recommended? |
|---|---|---|---|
| head tag | Before page loads | No | No (unless using defer) |
| End of body | After page loads | Yes | Yes — safest option |
| head with defer | After page loads | Yes | Yes — modern approach |
The defer and async Attributes
The defer Attribute
1<!DOCTYPE html>2<html>3 <head>4 <!-- defer = download script now, run it AFTER page loads -->5 <script defer>6 let btn = document.getElementById("myBtn");7 btn.addEventListener("click", function() {8 alert("Deferred script works!");9 });10 </script>11 </head>12 <body>13 <button id="myBtn">Click Me</button>14 </body>15</html>
The async Attribute
1<!DOCTYPE html>2<html>3 <head>4 <!-- async = download AND run as soon as possible, don't wait -->5 <script async>6 console.log("This runs as soon as it downloads!");7 // Warning: page might not be fully loaded yet8 </script>9 </head>10 <body>11 <p>Page content here...</p>12 </body>13</html>
async is Unpredictable
With async, the script runs the moment it downloads — even if the page has not finished loading. Avoid async for scripts that need to access HTML elements.
| Attribute | Downloads | Runs When | Best For |
|---|---|---|---|
| None (in body) | When browser reaches the tag | Immediately | Most inline scripts |
| defer | In parallel with HTML | After HTML is parsed | Scripts that need the DOM |
| async | In parallel with HTML | As soon as downloaded | Independent scripts like analytics |
Inline Event Handlers
1<!-- onclick runs JS when button is clicked -->2<button onclick="alert('Hello!')">Click Me</button>34<!-- onmouseover runs JS when mouse hovers -->5<p onmouseover="this.style.color = 'red'">Hover over me!</p>67<!-- onchange runs JS when input value changes -->8<input type="text" onchange="console.log(this.value)" />910<!-- You can call a function too -->11<button onclick="sayHello()">Say Hello</button>1213<script>14 function sayHello() {15 alert("Hello from a function!");16 }17</script>
Inline Event Handlers Are Not Recommended
Inline event attributes mix HTML and JavaScript together. This makes your code hard to read and maintain. Use addEventListener in a script tag or external file instead.
Better Alternative to Inline Events
<button onclick="alert('Hello')">Click Me</button>
<button id="greetBtn">Click Me</button><script>document.getElementById("greetBtn").addEventListener("click", function() {alert("Hello!");});</script>
<button onclick="alert('Hello')">Click Me</button>
<button id="greetBtn">Click Me</button><script>document.getElementById("greetBtn").addEventListener("click", function() {alert("Hello!");});</script>
Multiple Script Tags
1<!DOCTYPE html>2<html>3 <body>4 <h1>My Page</h1>56 <script>7 // First script runs first8 let name = "Alice";9 console.log("First script: name is " + name);10 </script>1112 <p>Some content in between...</p>1314 <script>15 // Second script runs second16 // It can use variables from the first script!17 console.log("Second script: still " + name);18 name = "Bob";19 </script>2021 <script>22 // Third script runs third23 console.log("Third script: now it is " + name);24 </script>25 </body>26</html>
Scripts Share the Same Scope
All script tags on the same page share the same global scope. A variable declared in one script tag is available in all later script tags.
Real Example: Interactive Counter
Here is a full working example of inline JavaScript making a page interactive. It uses a counter with increment and reset buttons.
1<!DOCTYPE html>2<html>3 <head>4 <title>Counter</title>5 <style>6 body { font-family: sans-serif; text-align: center; padding: 40px; }7 #count { font-size: 72px; font-weight: bold; color: #333; }8 button { font-size: 18px; padding: 10px 24px; margin: 8px; cursor: pointer; }9 </style>10 </head>11 <body>12 <h1>Counter</h1>13 <div id="count">0</div>14 <br />15 <button id="addBtn">+ Add</button>16 <button id="resetBtn">Reset</button>1718 <script>19 let count = 0;20 let countDisplay = document.getElementById("count");2122 document.getElementById("addBtn").addEventListener("click", function() {23 count++;24 countDisplay.textContent = count;25 });2627 document.getElementById("resetBtn").addEventListener("click", function() {28 count = 0;29 countDisplay.textContent = count;30 });31 </script>32 </body>33</html>
Pros and Cons of Inline JavaScript
Inline JavaScript is useful for small projects but has real downsides when projects grow. Here is an honest look at both sides.
| Pros | Cons |
|---|---|
| No extra files needed | Harder to reuse code across pages |
| Easy to get started | Mixes structure (HTML) and logic (JS) |
| Works in any browser | Gets messy as projects grow |
| Great for learning | Hard to maintain long term |
| Quick to test ideas | No caching — redownloads every page visit |
Use Inline JS for Learning
When you are learning JavaScript, inline scripts are perfect. When you start building real apps, move your code to external .js files.
Quick Quiz
Where is the safest place to put a script tag without using defer?
What does the defer attribute do?
What is wrong with inline event attributes like onclick?
If you declare a variable in one script tag, can you use it in a later script tag on the same page?
Which attribute should you use when a script needs to access HTML elements and is placed in the head?
Key Takeaways
- 1Put script tags just before the closing body tag to safely access all HTML elements.
- 2Use the defer attribute if you must place your script in the head.
- 3Avoid async unless the script is completely independent of the page content.
- 4Avoid inline event attributes like onclick — use addEventListener instead.
- 5All script tags on the same page share global scope — variables from one are visible in another.
- 6Inline JavaScript is perfect for learning and small projects, but switch to external files for real apps.
Try it in the Javascript Compiler
Run and experiment with Javascript code right in your browser — no setup needed.