86

A team that I am working on has gotten into the habit of using <script> tags in random places in the body of our HTML pages. For example:

<html>
    <head></head>
    <body>
        <div id="some-div">
            <script type="text/javascript">//some javascript here</script>
        </div>
    </body>
</html>

I had not seen this before. It seems to work in the few browsers that I've tested. But as far as I know, it's not valid to put script tags in places like this.

Am I wrong? How bad is it that we are putting script tags within div tags like this? Are there any browser compatibility issues I should be aware of?

Kara
  • 5,650
  • 15
  • 48
  • 55
Andrew
  • 196,883
  • 184
  • 487
  • 673
  • 1
    Is it doing `document.writes` there or is there no particular reason for it to be where it is? – Martin Smith May 14 '10 at 22:07
  • 9
    Script are legal to occur anywhere in the body. There's nothing wrong with that. It has its implications (timing, maintainability, intermixing of code and layout, personal preference), but otherwise it's okay. – Tomalak May 14 '10 at 22:12
  • @earlz - see my answer as to why it's bad. just trying to save a life here. and i am correct. – Jason May 14 '10 at 22:27

17 Answers17

90

It's perfectly valid.

You wouldn't want to put great big blocks of code mixed up in the markup there (better to use external scripts), but it can be useful to:

  • add extra binding information for progressive-enhancement (where that data is difficult to fit into a classname or other approach to hiding extended information in attributes); or

  • where it's necessary to kick off a scripted enhancement as quickly as possible (rather than waiting for window-load/document-ready). An example of this would be autofocus, which can irritate if fired too late.

You may be thinking of <style> elements, which aren't allowed in <body> (although most browsers allow it nonetheless).

bobince
  • 498,320
  • 101
  • 621
  • 807
  • 12
    +1 for the autofocus; sometimes I'm on a slow connection and it's not fun to be already somewhere else (in the worst case: typing a password) when being put back to the first field. – Marcel Korpel May 14 '10 at 22:50
  • 2
    However, embedding JS can be useful when there is only one page and to reduce server lookups. Same story to embedded CSS. But normally it is better to separate javascript code and css in separated files to reduce page load times (with using a valid cache header) when using a template with the same javascript and css requirements. – Codebeat Nov 05 '12 at 17:43
16

Actually, it's quite common. For example Google's analytics tracking code uses just this syntax:

<script type="text/javascript">
  var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
  document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>

If it's good enough for Google...

Keltex
  • 25,524
  • 11
  • 74
  • 110
  • 39
    -1 - just because Google is doing it does not mean it is good practice. Common != good. – Jason May 14 '10 at 22:14
  • 3
    Google Analytics is overly convoluted anyway and their usage of JavaScript for tracking is actually a good example of overengineering. – Esko May 14 '10 at 22:18
  • also, they recommend that you put the script at the bottom of the page, not in the middle, which is where scripts should be placed if you have to place them. NOT in the header where people usually put them – Jason May 14 '10 at 22:19
  • 2
    Off-topic aside: I'm always irritated by Google's needless and bizarre use of `unescape`, given that `escape`/`unescape` Is Evil (and that `\x3C` would have been a much simpler way of doing it). – bobince May 14 '10 at 22:24
  • 3
    @Keltex: The code isn't invalid, however claiming that it's good practice just because some people use it is not a valid argument. – Matti Virkkunen May 14 '10 at 22:27
  • @bobince - nothing prevents you from "hardcoding" the script tag with reference to ga.js yourself. After all this shows just how apt to cut-n-past developers are without thinking about what is actually going on. – Peter Lillevold May 15 '10 at 12:16
4

It is valid and, depending on your server-side framework and the nature of the code, sometimes very difficult to avoid.

Pointy
  • 371,531
  • 55
  • 528
  • 584
4

As several people mentioned, it's valid, it works, and it is widely used.

Best practices as far as semantics recommend (or at least used to recommend) is placing script tags inside of the header.

More modern best practices which take performance into account recommend placing script tags (external and inline) at the bottom right before the body tag, to allow the markup to render completely before any JavaScript code executes.

For easier to understand and maintainable code, "unobtrusive JavaScript" is recommended, where the code is in an external file and binds events to the DOM (Google unobtrusive JavaScript).

One case where it's useful to have JavaScript inline is to initialize variables with values that only exists server side, which will then later be used by the external JavaScript code.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Gal
  • 3,861
  • 1
  • 19
  • 20
3

It is valid!

You can use:

<script type="text/javascript">
    //<![CDATA[

    // Some JavaScript code that perfectly validates in the W3C validator

    //]]>
</script>

I don't think you can say if it is a bad practice in general. You have to tell in the case. But sure is that it is good to have all your JavaScript code at the same place. It's a little messy if you have little pieces of JavaScript code all over your HTML file.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
meo
  • 28,823
  • 17
  • 81
  • 121
  • 2
    it is a bad practice in general. – Jason May 14 '10 at 22:15
  • ok just read you post, good to know. I never do it anyway, but never though that it could make hang your browser... ...how it comes? – meo May 14 '10 at 22:20
  • 1
    Any JavaScript can hang your browser (sometimes I still get those alert boxes in Firefox with an ‘Abort script’ and a ‘Continue script’ option). – Marcel Korpel May 14 '10 at 22:47
  • this is true, any JS can hang your browser. however, if you're going to hang it (obv never recommended), better to do it once the page has fully rendered with content and the user can begin reading/interacting with the page. the reason why JS hangs your browser is because it runs synchronously, meaning that the browser must wait until the JS is completely executed before it continues rendering, since it doesn't know what the JS is going to do. While it's waiting, it is not rendering, making it look like it's hanging. – Jason May 14 '10 at 23:22
  • Don't use that CDATA thing -- it's a nonsense. Only XML-validating parsers understand CDATA sections, so if your pages are served as HTML, it makes no functional difference. However if your pages are served as XML, then it will render the "//" before the opening tag. – brothercake Aug 27 '13 at 12:59
3

I prefer to put references to external scripts into the head, and scripts that start things up and initialize widgets and whatnot into the body.

An issue that's very easy to run into is that a script element in the body cannot access elements that come after it. Also, a related nasty browser compatibility issue is the fact that IE doesn't allow script elements to modify the element they're in. So if you have this:

<div id="foo">
  <script type="text/javascript">
    document.getElementById("foo")... // do something to it
  </script>
</div>

IE is not going to like your page. Old versions of IE used to give very cryptic error messages for this or even blank the entire page, but IE8 seems to give a descriptive error message.

As long as you make sure that your scripts only access DOM that's safe to access, I don't think it's evil to put script elements into the body. In fact, IMHO, putting scripts that initialize widgets after the related elements can be more readable than putting everything in one place (and I believe this might also make them run earlier, which makes stuff jump around less as the page loads).

Matti Virkkunen
  • 58,926
  • 7
  • 111
  • 152
2

I had not seen this before. It seems to work in the few browsers that I've tested. But as far as I know, it's not valid to put script tags in places like this.

It's valid, but not a good (or recommended) practice.

Am I wrong? How bad is it that we are putting script tags within div tags like this? Are there any browser compatibility issues I should be aware of?

There's no problem placing a <script> under any other elements (but it should be inside <head> or <body>). There's also no issue in terms of browser compatibility, however, embedding JS scripts on web pages presents serious disadvantages (how/why they are considered bad):

  1. Adds page weight
  2. Difficulty (or probably impossible) for minification
  3. Cannot be migrated or be used for other pages
  4. Cannot be cached (needs to be downloaded every time the page is loaded)
  5. No separation of concerns (harder to maintain)
2

However, it's also good in that you know the JavaScript code needed for a section of HTML is going to be there for it. Rather than having to assert and build up some inclusion at the top of the file.

So, rather than "if you're going to use this HTML, make sure you import xyz.js" you can just include the HTML and be done with it.

So, it's not necessarily horrible evil. Perhaps not spectacularly awesome, but not utterly terrible either. It kind of depends on the intent.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Will Hartung
  • 107,347
  • 19
  • 121
  • 195
2

See the Yahoo UI for best practice: http://developer.yahoo.com/performance/rules.html (JavaScript at the bottom of the page)

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Jonathan Lebrun
  • 1,214
  • 3
  • 19
  • 39
  • big +1! So many answers, but none of them mention that scripts in the HEAD can block other elements (like images! which can mess up the layout on a slow connection) – David J Jul 25 '16 at 22:15
1

It's certainly legal; I've seen it on a few pages here on Exforsys for example.

Now this is a tutorial site showing the basics of HTML and JavaScript so in that context it's perfectly understandable. However, I wouldn't like to see it in production code for anything more than a simple statement or two. Without seeing what you've replaced by // Some JavaScript code here I wouldn't like to comment.

There shouldn't be any browser issues with this though.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
ChrisF
  • 127,439
  • 29
  • 243
  • 315
1

It is perfectly valid, though it might hurt maintainability. See also Where should I put <script> tags in HTML markup? and Why does the call to this jQuery function fail in Firefox?.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
thSoft
  • 19,314
  • 5
  • 82
  • 97
1

It's one of many, many best practices that's as much about improving performance as it is about improving your approach to programming.

Ultimately in web development, getting the product out matters the most!

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
heydenberk
  • 197
  • 10
1

I assume that your team is doing this either because they want to insert a script dynamically, or that they are writing a script that will fire at page load.

I wouldn't say there's anything wrong with doing this when ABSOLUTELY NECESSARY, (as long as it's in a CDATA block), but outside of that, I would recommend to your team that they use a script library like Prototype or jQuery, and keep the scripts external to the page. This is usually cleaner, and libraries will sometimes force a bit of cleanliness to the code, which I would bet isn't happening currently.

I also wouldn't run any time-consuming functions in inline script tags, as these happen on page load, and as Jason stated above, could slow the load of the page. All script libraries have neat functions that allow you to do things on load of the page, and will give you the option of when in the page load to fire them, such as after the DOM is loaded.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Jesse
  • 9,712
  • 9
  • 60
  • 79
1

It is valid to add <script> in body, but Internet Explorer really doesn't likes it. So to be on the safer side, make sure you have your scripts inside the <head> tag.

That was really creating havoc (especially for Internet Explorer) in the project which we are working on.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
paddy
  • 11
  • 1
0

A few things:

  1. It's completely valid code-wise.
  2. It's completely unrecommended.

Doing this slows down your page load considerably as the JavaScript code must execute before any of the rest of the page can render. If you're doing a lot of work in that JavaScript code, your browser could hang. You should try to (whenever possible) load your JavaScript code dynamically and at the end of your page (preferably before the </body> tag).

Purchase and read High Performance JavaScript. It will change the way you write JavaScript code.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Jason
  • 47,815
  • 37
  • 122
  • 180
  • 3
    Not my downvotes, but when I think Yahoo, I think `YAHOO.util.Event.addListener`, not efficient/concise javascript. I wouldn't read a book and treat it as gospel, sometimes you **must** have javascript in the page itself, e.g. a variable dynamically rendered, something you can't do in an external `.js`. – Nick Craver May 15 '10 at 10:25
  • 2
    have you read the book? if you had, you'd know that it teaches optimization techniques. things like `YAHOO.xx.xx.xx` are cached locally. on occasion, yes it's ok to render a variable on the page, but that can usually be done externally anyways if you just set a hidden input value from the server. but i said it is *unrecommended* not *wrong*. also, nicholas zakas, the author, knows his shit, regardless of who his employer is. – Jason May 16 '10 at 01:28
  • 2
    "Loading dinamically" and "loading at the end of the page" are different things, and it's highly improbable that there are any performance gains from using them both. "Have you read the book?" and "I am correct" are also not the best way to start a constructive conversation. Also the original question can be answered with "because it eventually chokes on IE", since some operations are only supported if script is a direct child of body. – Nacho Coloma Jan 20 '14 at 07:42
0

The oft-stated recommendation that scripts should be kept in the header is to ensure that the script is loaded before it is called. This is only an issue for certain event handlers. For other types of script, it doesn't matter, and for some types (such as document.write), it doesn't make any sense.

Tor Haugen
  • 18,547
  • 8
  • 40
  • 59
0

If you have an editor that can handle both HTML and JavaScript syntax simultaneously. And if you like to first read a few lines of HTML and then JavaScript cpde...sure. Go for it.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Cheery
  • 21,751
  • 13
  • 55
  • 80
  • Sounds like Visual Studio and razor views which can handle both. This can be quite convenient in some cases (all the code you need to edit in one place). Of course too much javascript in in the view can make reading and understanding the code difficult and there is also the problem of bloating the output html. – jahu Feb 18 '15 at 16:38