Suggest an editImprove this articleRefine the answer for “The defer attribute in script”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`defer` tells the browser to download the script in parallel with the HTML but to execute it only after the whole document has been parsed, that is, right before `DOMContentLoaded`.** HTML parsing is never blocked, so the page appears sooner. Several `defer` scripts download in parallel but run strictly in the order they appear in the markup, unlike `async`, where the order is not guaranteed. This is the correct way to include your main application scripts straight from `<head>`. ```html <head> <script src="main.js" defer></script> </head> ``` **Key point:** `defer` means "download now, run later, in order, after the DOM is ready".Shown above the full answer for quick recall.Answer (EN)Image**`defer` is a `<script>` attribute that tells the browser: download this script in parallel with the HTML, but execute it only after the whole HTML document has been loaded and parsed.** Execution happens before the `DOMContentLoaded` event, so by that point the DOM is fully built. ## Theory ### TL;DR - With no attributes a `<script>` halts HTML parsing while the file is downloaded and executed. - `defer` downloads the script in parallel with HTML parsing and never blocks it. - Execution is postponed until the DOM is built and happens right before `DOMContentLoaded`. - Several `defer` scripts run in the order they appear in the markup; with `async` the order is arbitrary. - `defer` in `<head>` is the standard way to include the main application scripts. - `defer` only applies to external scripts with `src`; for inline code it is ignored. ### Quick example ```html <head> <!-- downloads in parallel with the HTML, runs on a ready DOM --> <script src="main.js" defer></script> </head> <body> <p>Hello!</p> </body> ``` ### Normal behaviour without `defer` ```html <script src="app.js"></script> ``` What happens: 1. The browser starts loading the HTML. 2. It meets a `<script>`. 3. It **stops parsing the HTML** in order to: - download `app.js`, - execute it. 4. Only then does it continue building the page. As a result the page **loads more slowly**, because JS blocks the HTML. That is exactly why scripts used to be placed at the end of `<body>`. ### What `defer` does ```html <script src="app.js" defer></script> ``` Now the browser: 1. Starts loading **HTML and JS in parallel**. 2. **Does not block** HTML parsing. 3. Executes `app.js` **only after the DOM is fully built**, but **before the `DOMContentLoaded` event**. So the sequence is: - the HTML is parsed, - the script downloads in the background, - the DOM is ready, - the script runs, - `DOMContentLoaded` fires. **An example of the difference** ```html <!-- Without defer --> <script src="slow.js"></script> <p>Hello!</p> <!-- With defer --> <script src="slow.js" defer></script> <p>Hello!</p> ``` With `defer` the text "Hello!" appears immediately while the script is still downloading. Without `defer` the page freezes until `slow.js` has loaded. ### When there are several scripts ```html <script src="a.js" defer></script> <script src="b.js" defer></script> ``` Scripts with `defer`: - download **in parallel**; - but execute **in the order they appear in the HTML**, that is `a.js` first, then `b.js`. This is the main difference from `async`, where the order is **not guaranteed**: whichever file arrives over the network first runs first. That is why only `defer` is suitable for pieces of code that depend on each other. ### How `defer` differs from `async` | Attribute | When it downloads | When it executes | Guaranteed order | Typical use | | --- | --- | --- | --- | --- | | *(no attribute)* | Immediately when met | Immediately (blocks HTML) | Yes | Legacy JS in `<head>` | | **async** | In parallel with HTML | Right after download (does not wait for the DOM) | No | Analytics, ads, widgets | | **defer** | In parallel with HTML | After the DOM is built | Yes | The main application scripts | The overall table: | Property | **No attribute** | `async` | `defer` | | --- | --- | --- | --- | | Downloads the script | Immediately (blocks HTML) | In parallel | In parallel | | Executes the script | Right after download | Right after download | After HTML parsing | | Execution order | In order | Arbitrary | In order | | Blocks HTML | Yes | No | No | | Waits for the DOM | No | No | Yes | ### Compatibility and the effect on `DOMContentLoaded` `defer` works in all modern browsers. Putting the script in `<head>` is the **most correct way** to include JS: ```html <head> <script src="main.js" defer></script> </head> ``` The browser does not block page loading and guarantees that your code runs when the DOM is already there. `DOMContentLoaded` fires **after** all `defer` scripts have executed. So inside a handler for that event you can be sure your scripts have already run and registered everything they needed to. It is also worth remembering that `<script type="module">` behaves like `defer` by default, so for modules the attribute does not need to be written at all. ### Common mistakes - **Putting `defer` on an inline script.** Without `src` the attribute is simply ignored and the code runs immediately. - **Expecting an execution order from `async`.** If `b.js` depends on `a.js`, `async` breaks it with a random order; you need `defer`. - **Thinking `defer` delays the download.** The file is fetched right away and in parallel, only execution is postponed. - **Deferring code that must run as early as possible.** An anti-flicker theme script, for instance, is better left as a synchronous inline snippet. - **Mixing `defer` with scripts that call `document.write()`.** In a deferred script that call is simply ignored. - **Still keeping scripts at the end of `<body>` "because it is faster".** With `defer` in `<head>` the browser starts downloading earlier and the result is better.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.