Grow your CSS skills. Land your dream job.

The Script Tag

Published by Chris Coyier

I got a great question from reader Josh Kreis:

I've noticed that on a <script> tag, there are all kinds of variations that all seem to work cross-browser. What is necessary and what isn't?

<script>
  //some javascript here
</script>

<script type="text/javascript">
  //some javascript here
</script>

<script type="text/javascript" language="javascript">
  //some javascript here
</script>

<script language="javascript">
  //some javascript here
</script>

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

This is the scoop as far as I understand it. If anyone cares to elaborate or correct me if I'm wrong, please do in the comments.

/* WAY OLD - DO NOT USE */

<script language="javascript">
  //some javascript here
</script>

There never really was a language attribute (or if there was, it's long deprecated). There is a lang attribute, but that's for an entirely different purpose: identifying human language not computer language. This syntax with the language attribute was for telling (old) browsers to identify and run the script as JavaScript. It used to work, but it was never standard.

We now have a standard way to do that:

<script type="text/javascript">
  //some javascript here
</script>

The type attribute is the standard and correct way to identify and tell the browser what kind of script the tag contains. Sometimes you'll see code that uses both the language and type attribute. As far as I know that's never necessary.

Really specific explanation from the spec, language is an "obsolete but conforming" feature:

Authors should not specify a language attribute on a script element. If the attribute is present, its value must be an ASCII case-insensitive match for the string "JavaScript" and either the type attribute must be omitted or its value must be an ASCII case-insensitive match for the string "text/javascript". The attribute should be entirely omitted instead (with the value "JavaScript", it has no effect), or replaced with use of the type attribute.

More recently, you've probably seen a lot of this:

<script>
  //some javascript here
</script>

No attributes at all. This is the HTML5 way of handling script tags that contain JavaScript. It's just assumed that the type is text/javascript. If it's not (I've never even seen a different type of script) you'll need to change it with the type attribute. I recommend this if you are using HTML5.

One more weird one:

<script type="text/javascript">
  //<![CDATA[
    $("<div />").appendTo("body"); // Some JS with HTML in it.
  //]]>
</script>

IF you are using XHTML still and IF your JavaScript has HTML in it (or even just the < character, as might be needed in greater-than logic), you'll need these CDATA comments around the script IF you care about the script passing validation (you'll get an error like: document type does not allow element "div" here). AND IF, you are putting script literally between the opening and closing script tags, not linking to a script src.

That's a lot of IF's.

Takeaways

  • If you are using HTML5, just use <script>.
  • If you are using anything older, use <script type="text/javascript">.
  • If you are writing scripts for people to use on their own sites (e.g. copy-pasteable code, WordPress plugins, etc, use <script type="text/javascript"> and CDATA.

Comments

  1. Permalink to comment#

    Thanks for clearing that up! I always wondered about that. I’m happy that HTML5 is much more simple now.

    Does anyone know of any other types used in the script tag? I, too, have never seen anything other than javascript in there.

  2. A lot of client-side templating enginges (e.g., jQuery templates) use the script tag for defining templates. See this for an example.

  3. “I’ve never even seen a different type of script”

    For what it’s worth, you can use type="text/coffeescript with the in-browser CoffeeScript interpreter. Example here: http://joshuacc.github.com/LifeForce/

  4. Francesco
    Permalink to comment#

    Great post, I’ll send people here when they tell me I MUST use the type attribute (even though I’m writing HTML5).

    For linked files… isn’t it the same exact thing, though?

  5. @Rob, yes i have seen vbscript before on some old websites.
    type=”text/vbscript”
    And I wrote some simple vbscript few years ago.

    also you can target a javascript version like that:
    type=”text/javascript1.3″
    But this I didn’t see before.

  6. Permalink to comment#

    Google’s Page Speed extension for Chrome’s web inspector takes points off for not including the type attribute on script and linked css elements. Specifying the mime type in a .htaccess file isn’t enough for it.

    Not sure if it actually has any bearing on page load times, but seeing as though Google uses page load speeds in search rankings it can’t hurt to keep adding the type attributes if it’ll make it happy!

    That said, I’m not sure Googlebot uses the same page speed scoring criteria as the web inspector extension, but I’m going to keep using them anyway.

  7. Evert
    Permalink to comment#

    I seem to remember you can escape to php with the script tag?

    • Permalink to comment#

      Maybe you’re thinking of fetching a JS script generated by a PHP file?

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

      You can, of course, use the <% … %> and <%php … php%> tags to switch to PHP parsing within a file.

    • Permalink to comment#

      Yeah, I wrote about that here:

      http://www.impressivewebs.com/php-file-html-script-tag/

      You can basically call any kind of file using the script tag, but the result must actually return JavaScript so that it can do something on the page.

  8. Dan Douglas
    Permalink to comment#

    Special interpretation of characters in CDATA sections are not related to validation . You’ll get an XML parsing error when loading the page or before validation takes place. It’s simply a shortcut so you don’t have to use entities like &lt; in your scripts. If you’re using the XML syntax then those javascript comments before the CDATA are unnecessary – which is really the only reason you would be using CDATA in the first place, unless you’re trying to write polyglot code, which has become somewhat less fashionable lately.

    Also omitted is probably the most common misunderstanding with regards to “application/javascript” versus “text/javascript”. I rarely see the language attribute these days.

  9. The only thing you need for plain JavaScript is a script element without any attributes. The mime type is not needed as JS is the standard. If you want to specify an own language, then the mime type becomes interesting. The comments inside the script nodes are totally historical, no client in use does care about content in a script node for display.

  10. Permalink to comment#

    I’ve found that I still like to use:
    script type=”text/javascript”

    EVEN when using HTML5 — this way, my code editor still knows to highlight the syntax. I’m using Coda, is there a way to have it recognize JS without adding the type=”text/javascript”?

  11. Permalink to comment#

    The most important bit of information has been left out… and that is that it’s best to put JavaScript in it’s own external .js file rather than in the (X)HTML document. So IDEALLY you would only do this:

    HTML5:
    <script src=”yourscript.js”></script>

    Everything Older:
    <script src=”yourscript.js” type=”text/javascript”></script>

    No need to even worry about that ugly CDATA stuff.

    • Permalink to comment#

      the reason html5 does away with requiring the type attribute* is that no browser** cares about it, at all. the doctype/stated html version has no bearing on this.

      * for javascript
      ** no _commonly_used_ browser
      (and most uncommon browsers too)

    • Permalink to comment#

      Right, but I would still include the type attribute for anything non-HTML5 for validation purposes. You’re correct, no browsers will care at all whether the type is there or not. But it was required in previous versions to be “valid”, so if you do any sort of validation, having the type defined will prevent validation errors.

    • Permalink to comment#

      true.
      (I suppose I care less about validation than practicality.)

    • Kim Daniel Borch
      Permalink to comment#

      “it’s best to put JavaScript in it’s own external .js file”

      Maybe semantically the best way but it’s also an extra HTTP request, so .. not always the best idea IMO.

    • Dan Douglas
      Permalink to comment#

      FWIW – minimal test omitting type on <style> and <script>. Valid according to http://syntax.whattf.org/relaxng/xhtml5.rnc and not according to http://www.w3.org/MarkUp/RELAXNG/xhtml-rdfa-1.rng

      So, old-style XHTML needs type to validate, otherwise any HTML5 is fine, and no browser should have a problem with it.

      <?xml version="1.0"?>
      <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
        <head>
          <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
          <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
          <title>type test</title>
          <style/>
          <script><![CDATA[
            "use strict";
            function main(n){
              document.getElementsByTagName("body")[0].appendChild(document.createElementNS(n, "p"));
              document.getElementsByTagName("p")[0].appendChild(document.createTextNode("hi!"));
            }
            function init(n){
              main("document.documentElement.namespaceURI");
            }
            document.addEventListener("DOMContentLoaded", init, false);
          ]]></script>
        </head>
        <body/>
      </html>

      The xhtml5 RNG chokes on the HTTP metadata but I believe that’s a bug.

  12. Don’t forget about:

    <script>
      <!--
        // some code here
      -->
    </script>

    Of course, this can be combined with all of the above options for an even more enterprisey feeling.

  13. I was just thinking about this the other day…nice timing. Thanks for clearing it up for me!

  14. Another case for the CDATA that I’ve regularly run across is when using a template engine like Genshi for Python to generate the HTML. It tends to try to be too smart and convert <>s in the javascript to &-entities.
    Same goes if you use them in CSS too. This give the funny syntax of:

    <style type="text/css">
    /* <![CDATA[ */
    .someelement:after { 
        content: ">"; 
    }
    /* ]]> */
    </style>

    BTW: Can the type=”" be dropped for style too in HTML5?

  15. Permalink to comment#

    Rather than just saying “In HTML5″ …

    It might be worth noting

    <!doctype html>

    should be the doctype when using

    <script>
    //some javasciript here
    </script>

  16. WillyWongi
    Permalink to comment#

    I’d like to point out again the case of handlebars templates, included in script tags:

    <script id="entry-template" type="text/x-handlebars-template">
      template content
    </script>

    Handlebars is being integrated in YUI3, another reason to point this out.
    Thanks again for the post!

  17. Scott Vivian
    Permalink to comment#

    I’d say always use <script> whether HTML 4 or 5. All browsers default to Javascript, since pretty much forever.

  18. Vladimir
    Permalink to comment#

    BTW: there might be type="application/dart" in future (at least at Chome)

  19. Permalink to comment#

    Just want to add (though not essential): I am a Blogger user, and I do realize that using //<![CDATA[ is important. Because if not, single quotes will be parsed into ' and quotation will be parsed into &quot;. In addition, without using //<![CDATA[ Blogger will reject the JQuery $ ('.something').append('<div></ div>');
    He expected that it is an HTML element that is placed on the <head>

  20. cnwtx
    Permalink to comment#

    Could you do your next article on the <style> tag? This one’s great, Chris!

  21. alireza
    Permalink to comment#

    سلام.خسته نباشید.من از ایران شهر ممقان هستم.
    از زحمات شما تشکر میکنم.
    ————————–
    Hello,I’m alireza From iran.State Mamaghan.
    Thanks For All.

  22. Permalink to comment#

    I think I saw another variation:

    
         
          // javascript here
     
    
  23. Permalink to comment#

    hmm, I added the pre and code tags, but didn’t work.
    Anyway, I meant sometimes there’s a charset attribute: charset=”utf-8″

  24. Permalink to comment#

    Here’s another good article on this subject:

    http://www.hixie.ch/advocacy/xhtml

  25. peter
    Permalink to comment#

    Great article! small typo in the HMLT5 part, last sentence:

    “I recommend this is you are using HTML5.”
    Should be “I recommend this if you are using HTML5.” (is / if), I guess.
    And maybe even a comma?

    Keep up the good work, this is one of the few sites I visit on a regular base, if not daily.

  26. For what it’s worth, I recall Crockford advocating removal of the type attribute because he didn’t see it changing to be anything other than text/javascript in the future – and there was no downside to doing so in modern browsers.

    The old <!– –> style inside <script> was for browsers that didn’t understand <script>, and it prevented them from rendering the contents of the block as text. (Netscape 4 with JS off, perhaps, or older/earlier versions of browsers like Mosaic? I forget.)

  27. maul.esel
    Permalink to comment#

    About other languages: with Silverlight, IronRuby & IronPython are supported, too.

  28. This is some nice and good food for thought, another good lesson, thanks again Chris !

  29. MechanisM
    Permalink to comment#

    Now I’m always using like this:

    
    <script>some script</script>
    <script src=js/somescript.js></script>
    <style>Some CSS code</style>
    <link rel=stylesheet href=css/somestyle.css>
    

    There’s not needed type or smth other. And btw server can be setup like follows:
    if direcory is css then default_type text/css; if js then default_type text/js; etc..
    Aswell as not needed to add meta tags for charset and others:
    add_header X-UA-Compatible IE=Edge,chrome=1;
    add_header charset utf-8;
    not needed all these code in html coz server can do it.

  30. I’m reasonably certain the “language” attribute was introduced by Microsoft with Internet Explorer[1] so that you could handle VBScript or JScript in addition to the common default of JavaScript (JScript had some minor enhancements over JavaScript but for all intents and purposes was JavaScript[2]). IE could also handle PerlScript which was a Perl based language as well through the use of extensions[3]. This functionality is provided through the Windows Scripting Host[4] which appears to also indicate a use of a language tag to differentiate between the various languages.

    [1] http://msdn.microsoft.com/en-us/library/aa242461(v=vs.60).aspx
    [2] http://en.wikipedia.org/wiki/JScript
    [3] http://www.xav.com/perl/Components/Windows/PerlScript.html
    [4] http://en.wikipedia.org/wiki/Windows_Script_Host

  31. logudotcom
    Permalink to comment#

    Good article

  32. Permalink to comment#

    HTML5 was only that simple. Now I know XD

  33. Permalink to comment#

    Great article….thanks Chris !

  34. Permalink to comment#

    Great article….thanks Chris !Keep writing such a valuable article…Thanx again

  35. carlos
    Permalink to comment#

    We use a script tag on the front end in the CMS we use called Umbraco. It is ASP.Net based but we use the tag and add a runat=”server” to it and are then able to add some C# code between the blocks directly within the Umbraco template.

    That is another way to use the tag. I think it is best to add the type to the tag just to be safe, no matter if in HTML5 or not. Then you always have a fall back if older browsers can’t read the HTML5 elements but still can run the Javascript on the page. Especially if your dropdown menus are ran by Javascript. Than a user can get around the site at least if they are not able to view the HTML5 elements.

    • Permalink to comment#

      runat=”server” is an ASP.NET thing. This is not part of any HTML specification and users will never see this (as it’s executed on the server). It’s usually considered a bad practice though – The proper way is to use code-behind files (.aspx.cs). Not sure if Umbraco allows this though.

    • carlos
      Permalink to comment#

      Daniel,

      We know the code behind stuff. The runat=”server” script tag is actually doing some extremely simple UA sniffing and adding /mobile to the URL. Umbraco allows alternate templates to be used for your site without having to make a completely new site or redirecting to a m.mydomain.com style site. We leverage the alternate templates by using the script runat=”server” stuff just for that.
      The rest of the site is built on Umbraco’s platform. We have a few custom controls built into it using code behind files of course.

      If you know C# or ASP.Net I would recommend at least trying it out. It is a pretty cool CMS. Very extensible. Even if you don’t know C# or ASP.Net still check it out. You don’t really need to know either one to build a site in Umbraco. Basic HTML and CSS are mainly what you need.
      But yeh.

      Was just saying that for those who don’t know that script tags can be used in ASP.Net to do server side stuff from the Client Side using runat=”server”.

  36. JoeFlash
    Permalink to comment#

    The language attribute is certainly deprecated and should never be used for current Web development. Early on the attribute was used by browsers to signify the language type and the minimum parser version required. Example: <script language="JavaScript1.5"> meant that the parse engine should support version 1.5 of the JavaScript language to run the script. If the browser could not support the version it would not run the script. Today’s browsers no longer use this type of designation. The use of try {} catch {} in JavaScript was a prime example of the need for knowing scripting support. The language and implementation was limited and still developing in the past and the code could cause rather than catch errors where it was not supported.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".