Menu Search
Jump to the content X

Thinking Inside The Box With Vanilla JavaScript


During the past four or five years of blogging regularly and doing research for other writing projects, I’ve come across probably thousands of articles on JavaScript.

To me, it seems that a big chunk of these articles can be divided into two very general categories:

  1. jQuery;
  2. Theory and concept articles focused on things like IIFEs1, closures2 and design patterns3.

Yes, I’ve likely stumbled upon a ton of other articles that don’t fall into either of these categories or that are more specific. But somehow it feels that most of the ones that really get pushed in the community fall under one of the two categories above.

I think those articles are great, and I hope we see more of them. But sometimes the simplest JavaScript features are sitting right under our noses and we just haven’t had a lot of exposure to them. I’m talking about native, more-or-less cross-browser features that have been in the language for some time.

So, in this article, I won’t be talking about jQuery, and I won’t be looking at structural code concepts or patterns. Instead, I’m going to introduce you to some pure JavaScript features that you can use today and that you might not have ever considered before.

insertAdjacentHTML() Link

Years ago, Microsoft introduced a method called insertAdjacentHTML() as a way to insert a specified string of text as HTML or XML into a specific place in the DOM. This feature has been available in Internet Explorer (IE) since version 4. Let’s see how it works.

Suppose you have the following HTML:

<div id="box1">
    <p>Some example text</p>
<div id="box2">
    <p>Some example text</p>

And suppose you want to insert another snippet of HTML between #box1 and #box2. You can do this quite easily using insertAdjacentHTML():

var box2 = document.getElementById("box2");
box2.insertAdjacentHTML('beforebegin', '<div><p>This gets inserted.</p></div>');

With that, the generated DOM ends up like this:

<div id="box1">
    <p>Some example text</p>
<div><p>This gets inserted.</p></div>
<div id="box2">
    <p>Some example text</p>

The insertAdjacentHTML() method takes two parameters. The first defines where you want to place the HTML, relative to the targeted element (in this case, the #box2 element). This may be one of the following four string values:

  • beforebegin
    The HTML would be placed immediately before the element, as a sibling.
  • afterbegin
    The HTML would be placed inside the element, before its first child.
  • beforeend
    The HTML would be placed inside the element, after its last child.
  • afterend
    The HTML would be placed immediately after the element, as a sibling.

Again, these are string values, not keywords, so they must be placed inside of single or double quotes.

The second parameter is the string you want to insert, also placed in quotes (or else it would be a variable holding a string that was previously defined). Note that it should be a string, not a DOM element or element collection; so, it could just be text, with no actual markup.

insertAdjacentHTML() has, as outlined in a post on Mozilla Hacks5, a couple of advantages over something more conventional, like innerHTML(): It does not corrupt the existing DOM elements, and it performs better.

And if you’re wondering why this one hasn’t received a lot of attention so far, despite being well supported in all in-use versions of IE, the reason is probably that, as mentioned in the Mozilla Hacks article, it was not added to Firefox until version 8. Because all other major browsers support this, and Firefox users have been auto-updating since version 5, it’s quite safe to use.

For more on this method:

getBoundingClientRect() Link

You can obtain the coordinates and, by extension, the dimensions of any element on the page using another lesser-known method, the getBoundingClientRect() method.

Here’s an example of how it might be used:

var box = document.getElementById('box'),
    x, y, w;

x = box.getBoundingClientRect().left;
y = box.getBoundingClientRect().top;

if (box.getBoundingClientRect().width) {
  w = box.getBoundingClientRect().width; // for modern browsers
} else {
  w = box.offsetWidth; // for oldIE

console.log(x, y, w);

Here, we’ve targeted an element with an ID of box, and we’re accessing three properties of the getBoundingClientRect() method for the #box element. Here’s a summary of six fairly self-explanatory properties that this method exposes:

  • top
    How many pixels the top edge of the element is from the topmost edge of the viewport
  • left
    How many pixels the left edge of the element is from the leftmost edge of the viewport
  • right
    How many pixels the right edge of the element is from the leftmost edge of the viewport
  • bottom
    How many pixels the bottom edge of the element is from the topmost edge of the viewport
  • width
    The width of the element
  • height
    The height of the element

All of these properties are read-only. And notice that the coordinate properties (top, left, right and bottom) are all relative to the top-left of the viewport.

What about the if/else in the example from above? IE 6 to 8 don’t support the width and height properties; so, if you want full cross-browser support for those, you’ll have to use offsetWidth and/or offsetHeight.

As with insertAdjacentHTML(), despite the lack of support for width and height, this method has been supported in IE since ancient times, and it has support everywhere else that’s relevant, so it’s pretty safe to use.

I will concede something here: Getting the coordinates of an element using offset-based values (such as offsetWidth) is actually faster than using getBoundingClientRect()9. Note, however, that offset-based values will always round to the nearest integer, whereas getBoundingClientRect()’s properties will return fractional values.

For more info:

The <table> API Link

If you’ve ever manipulated elements on the fly with JavaScript, then you’ve likely used methods such as createElement, removeChild, parentNode and related features. And you can manipulate HTML tables in this way, too.

But you may not realize that there is a very specific API for creating and manipulating HTML tables with JavaScript, and it has very good browser support. Let’s take a quick look at some of the methods and properties available with this API.

All of the following methods are available to be used on any HTML table element:

  • insertRow()
  • deleteRow()
  • insertCell()
  • deleteCell()
  • createCaption()
  • deleteCaption()
  • createTHead()
  • deleteTHead()

And then there are the following properties:

  • caption
  • tHead
  • tFoot
  • rows
  • rows.cells

With these features, we can create an entire table, including rows, cells, a caption and cell content. Here’s an example:

var table = document.createElement('table'),
    tbody = document.createElement('tbody'),
    i, rowcount;


for (i = 0; i <= 9; i++) {
  rowcount = i + 1;
  tbody.rows[i].cells[0].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 1'));
  tbody.rows[i].cells[1].appendChild(document.createTextNode('Row 1, Cell 2'));
  tbody.rows[i].cells[2].appendChild(document.createTextNode('Row 1, Cell 3'));

table.caption.appendChild(document.createTextNode('A DOM-Generated Table'));


The script above combines some customary core DOM methods with methods and properties of the HTMLTableElement API. The same code written without the table API might be considerably more complex and, thus, harder to read and maintain.

Once again, these table-related features have support all the way back to IE 7 (and probably earlier) and everywhere else that’s relevant, so feel free to use these methods and properties where you see fit.

For more info:

Wrapping Up Link

This discussion of specific native JavaScript features has been a reminder of sorts. We can easily become comfortable with the features of a language that we know well, without looking deeper into the language’s syntax for simpler and more maintainable ways to solve our problems.

So, from time to time, look inside the box, so to speak. That is, investigate all that vanilla JavaScript has to offer15, and try not to rely too much on plugins and libraries, which can unnecessarily bloat your code.

(Credits of image on front page: nyuhuhuu16)

(al ea)

Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4,js,output
  5. 5
  6. 6
  7. 7
  8. 8,js,output
  9. 9
  10. 10
  11. 11
  12. 12,js,output
  13. 13
  14. 14
  15. 15
  16. 16

↑ Back to top Tweet itShare on Facebook

Louis Lazaris is a freelance web developer and author based in Toronto, Canada. He blogs about front-end code on Impressive Webs and curates Web Tools Weekly, a weekly newsletter for front-end developers.

  1. 1

    Thanks a lot for this article; it helps showing the pure power of JavaScript instead of that magic library we all use. I have the feeling that a more and more people know jQuery, but actually forget what is happening under the hood. Nice read!

    • 2

      I really hope people do not use these tools. They are outdated, cumbersome, not always cross browser friendly, and for goodness sake, no one should be building markup with javascript in modern times.

      jQuery may irk purists, but it is generally way easier to maintain, and in our fast moving tech world, that is priority one.

      • 3

        “for goodness sake, no one should be building markup with javascript in modern times”

        When you say this — do you mean people should use jQuery to build markup and not bother to know how to do it in the base language, or that markup should not be generated client-side at all?

      • 4

        Yeah. Let’s all add 90k (compressed) to our page size BEFORE we’ve even written any code…

        Most of that 90k, you won’t even use.

        • 5

          90k if it’s not already in your browser’s cache, which it might very well be if you i.e. use the google hosted jquery versions or another global cdn. For mobile (where 90k is a lot more than for desktops) we use stripped versions like zepto which can be as small as 9k. And yes, you might very well decide this BEFORE writing any code, with techniques like caching that is not a bad practice ;)

          • 6

            You’ve got to remember that JQuery et al are free as in speech (not beer) ;)

            Yes, you can (and should cache) static resources, but you don’t control the end users cache (

            Network performance isn’t the only consideration. What about memory consumption and battery life? How many objects is that 90k of javascript creating in the device’s memory?

            There is also technical debt and maintainability to consider (personally I don’t like the way JQuery is written – in my experience is makes hard to read code that is painful to maintain).

            Mindlessly including any JS Library because “that’s what everyone else does” (I refer to the millions of JQuery/Javascript how to articles or the “Look a CSS only…” articles that loads up 1Mb of JS) is only going to lead to trouble – what happens when your users discover a bug in code that comes from the library, who fixes it…?

        • 7

          I don’t like using JQuery either but there is a way to build a JQuery file that includes only the modules that you use. For example if you only use the css and ajax modules => 28kb minified+gziped file, it’s still crappy but at least 1/3rd smaller.

          There are CLIs like `npm install -g jquery-builder` and there are websites like for it

    • 8

      Very true Sander. I’ve come across a lot of people who when they started their career, learnt jQuery first and even today aren’t very comfortable with native JavaScript. Have seen situations where 1kb of native JavaScript is enough to achieve the desired result but people go ahead and include a 90Kb plus file instead.

    • 9

      Thanks for digging up some useful functionality in the DOM. Vanilla JS is the best.

  2. 10

    Great examples! I often use jQuery in my projects, but I know that it’s not always necessary – in many cases things can be done with better performance in pure JS.

    Here is some other examples with jQuery vs pure JS and comparisons of performance:

  3. 11

    It’s important to draw the line between the JavaScript language itself and the DOM API. These features belong to the DOM, rather than the language – but I agree it’s useful to be aware of them (and others)

    • 12

      Agreed — good point. Thanks for adding that clarification. For example, these features are not mentioned in the ECMA spec. I guess this is more about the fact that these can be used natively, without a library or framework, in all browsers.

  4. 13

    I didn’t know that those thing actually exist. Thanks a lot!

    • 14

      Don’t worry. I think the most of people didn’t know it, including me =).
      Great article!

  5. 15

    Great article! I admit I am a jQuery addict, and often forget the raw power of the native JS library. I’ve used some of these features in the past, but never the table API which I never realised existed to this extent.

    I really should look towards achieving functionality using barebones JS before screaming in horror and running to grab the nearest JS library.


  6. 16

    You made me happy. I’m one of those developers who respect the power of jQuery but at the same time, prefer vanilla JavaScript.

    I found the insertAdjacentHTML() and getBoundingClientRect() really interesting.

    Thanks a lot for such a great article and I would like to see more articles on DOM or vanilla JavaScript from you.


  7. 17

    Izrada web stranica

    October 7, 2013 3:34 am

    Nice examples of vanilla js. Good article bro. Keep going! :)

  8. 18

    Great read. Thanks. I often struggle to find simple solutions when searching on the internet that don’t use jquery. I love pure JS without extra libraries, such as mootools, scriptaculous, prototype and jquery etc. Thanks for the article.

  9. 19

    Can this be potentially used by hackers?

  10. 21

    Good post. I’d love to see a series of these! Something showing off the raw power of javascript and how so many of the features that we rely on from libraries are really just wrappers or worse for features that are already in browsers. Thanks again!

  11. 22

    wow…. getting right and bottom of elements really awesome.

  12. 23

    A problem many developers have is to be set with the language they learned (even the current iteration) and not allow themselves to progress and take in the benefits and functions of innovations such as jQuery is to JavaScript.

    BUT, at the same time, you have to ask yourself whether the scope of what it is you want to DO with the language, warrant the load of this new tech. It’s a fine line between hopping on the bandwagon for the same of something new vs. staying with what you know for fear of learning something new.

    The solution here is to just apply what is necessary to meet the requirements, and nothing more. If good ol’ JavaScript is what we need, it would be reckless to just “add jQuery” because it provides so much functionality that, in this case, would be wasted.

    Good article; as developers, we need only apply functionality the meets the need, rather than exceed it. It’s not an argument of declaring that “Just adding jQuery makes the application instantly future-proofed and scale-able.” In this world of mobile-heavy device usage, we need to remain ever-mindful of the load being put on the devices that access our projects.

  13. 24

    I do agree that often native JS functions go under-appreciated and or under-used but one thing I’d mention from an enterprise POV is that throughout a project we strive for consistency to ease new developers picking up project.

    Since many things are easier via a library/framework chosen for that project, we try to avoid mixing too many approaches.

    As a result, I’d typically say that if the project uses native JS, use it throughout, similarly if we’re using jQuery use it throughout. We recently wrote a Win8 app with WinJS and intentionally didn’t use jQuery as we wanted both exposure to, and consistency of approach and syntax.

    My only point being, for larger apps, if there a lot of areas where libraries are used, it can be slightly confusing to see native JS if it’s not expected. “Is this page old?/new?” , “Was there some reason why it’s not the same?”. So in summary I totally support the usage of native functions, as long as it’s not inconsistent with usage of libraries to perform the same function.

    • 25

      Something equally underappreciated would be comments in JS code (or code in general) which would solve all problems concerning confusion you mentioned and help with various mainetance issues – but that’s another story.

  14. 26

    Nice, thank you!

  15. 27

    The main problem here is the IDs everywhere. IDs are notoriously bad unless used very sparingly since they need to be unique, so using raw JS, you either have to 1) put IDs everywhere to stick with native JS, or 2) add in some css selector engines on top to give you the DOM traversal/selection power of jquery without jquery (which essentially means you have jquery anyway).

    Personally, I don’t use jquery just for little things like appending and adding table rows, etc. I use it for DOM traversal excellence and accept that it has things like .append() along the way.

    • 28

      If you don’t require IE6/7 support, which is becoming more likely every month, then you can use querySelector/querySelectorAll, which is supported in IE8. You just have to remember that you can’t use CSS3 selectors when using qs/qsa in IE8.

    • 29

      You can also just include sizzle, which is the selector engine used by jQuery, so you get the ease of jquery selecting without the bulk of jquery. only 4kb!!

    • 30

      To add on the comments of the previous commentators: You could also easily use getElementByClass. This is supported by all browsers except our favorite douchebag Internet Exploiter.

      For this nasty old wheezer you just use some workarounds. Nonetheless, knowing your way around the JS world WITHOUT having to rely on some huge framework just to get some simple stuff done – that gives you quite the good felling in your tummy ;)

      cu, w0lf.

      ps: Why use stuff like append and prepend? That is just a simple wrapper of jQuery for DOM traversal in combination with its selector engine. No need to use THAT bit for simple JS handiwork.

      cu, w0lf.

  16. 31

    Thanks for this nice article and clever point of view: never forget the basics.

  17. 32

    Hi Louis, really nice outside the box article.. Many times we focus on using frameworks and forget to check if a “native” technique already exists to do the same thing… Especially I like very much the Table API features you have listed.. Thanks to share the post!

  18. 33

    Ricardo Muniz Crespo

    October 7, 2013 11:26 pm

    A really bad habit of mine consist out of using jQuery for every little piece, which could usually be replaced with basic JavaScript. Unfortunately importing the library each and every single time adds a huge load to the websites I built, although it is not necessary. Thank you for sharing, I will check out the sources.

  19. 34

    Awesome post. Thanks.

  20. 35

    Just learned about getBoundingClientRect last week and it’s pretty useful!

    Gotta love vanilla Javascript :)

  21. 36

    Thanks a lot! The getBoundingClientRect() helped me hugely in one of my projects.

    What’s with all these ID selectors? Can’t we just use document.getElementsByClassName()?

  22. 37

    Someone on Twitter asked a good question: How do you create <th> elements inside a <thead>? While there is a createTHead method, there doesn’t seem to be a way to create a cell that’s not a <td>.

    The best I can think of is to use createTHead with something like innerHTML, which seems to work okay:

    The fact that the spec doesn’t mention the ability to create <th> elements seems to be an oversight. I’ll try to contact someone working on the spect to see if there’s something I’m missing here.

  23. 38

    And the whole article was about the DOM.
    Most of the functionality was already in IE5.5+, it was the ‘standards commity’ that brought us most of the trouble as everything Microsoft made was deemed not good and had to be done different. Now more then ten years later we starting to get the functionality of IE5.5 back.
    The only real progress is made with CSS and the HTML5.
    But i already see signs that different browsers are going in different directions again and a new browser war is forming. So things like jquery which should actually not exist has new fertile ground to grow.
    In these environments it is better to use a framework abstraction even when ‘plain vanilla’ is working now. The framework will keep it working in the future.

    • 39

      I don’t see that happening at all. Standards are a lot higher profile, no browser supports the whole standard, some browsers have proprietary features, but each is now trying to make everything that they do support, standards compliant.

      IE5.5 -did- suck, and they had lots of proprietary methods of doing things which often ended up with horrible code (not just JS, the filter rule in IE CSS seems to be the fix for everything in IE).

      I think it’s pretty well acknowledged now that if you don’t want to have issues, you don’t use the proprietary or non-standard features (if possible) and you either shim the browsers that don’t support certain standard features or you avoid them if there’s an alternative.

      If a browser was to turn around now and start implementing parts of the standard with a different syntax or with different behaviour, or if it began implementing non-standard features which are otherwise covered in the standard, the community would make an issue of it, or it just wouldn’t be allowed into the browser in the first place. Experimental features are allowed in, but usually they’re based on something missing from the spec (though sometimes with a proposal), and it’s either prefixed or only available to developers that explicitly enable the features.

      I certainly don’t see browser vendors removing support for parts of the current standard which are already implemented in previous versions of browsers.

      Adding ~30kb of overhead “just in case”, always seems like a bizarre argument to me, support for future changes won’t be baked into the current version of that library, and to upgrade the library (to get the future support) you usually have update your code in order to support the changes the library themselves have made (regularly removing and exchanging functionality between methods). After all that, you’ve saved no time because you’ve still had to update code…

  24. 40

    These functions are not “raw” or “vanilla” javascript, these are DOM API methods. Nothing to do with JS.
    JS != DOM API. Rename your post as “Vanilla DOM API”.

    • 41

      Yes, that was addressed in another comment. While it is technically correct, it’s a non-issue, since JavaScript is pretty much the only client-side language that is used to manipulate the DOM. Most of the meat of what happens in JavaScript is via the DOM API. At this stage in web development history, and considering the dominance of JavaScript, it’s hard to say that the DOM API has “nothing to do with JS”. If there was another client-side language that was real competition for JavaScript, then it would matter.

      That being said, I suppose it’s a good thing for all to understand, even if it has no practical value that I can think of.

      Like I mentioned before, the main point here is that, pending browser support, you can do a lot without a library.

  25. 42

    I’m surprised no one else brought this up — there is no mention of specific browsers that support these methods. If you’re going to steer us away from libraries (which I see no problem with, at all), at least give us an idea of which browsers support these. Calling them “…more-or-less cross-browser features…” then only mentioning that IE supports some of them isn’t very comforting to me.

    • 43

      Jeff, it seems you didn’t read the post, or else you’re expecting a chart or something. For each section in this article, I stated the browser support. To repeat what I said: In a nutshell, all of these features are supported in all in-use browsers, even going back to IE6.

      The only reason I said “more or less cross-browser” is because I can’t guarantee these aren’t buggy in some older browsers. Besides, even if I said these have 100%, bug-free support, I doubt you’d take my word for it anyhow. A good developer tests and tests again — regardless of what the support charts/articles say. :)

  26. 44

    This is something that is good to know but not important to build a maintainable code unless your main job is to build libraries on top of JS.

  27. 45

    Great post Louis,

    A lot of really good small tips in here, I never read about insertAdjacentHTML before. The comments are pretty amusing as well, I think any time you put “vanilla JS” in a blog headline you are bound to get a bunch of funny and/or ridiculous comments :-)

  28. 46

    awesome stuff – I frequently use these myself except i never knew about getBoundingClientRect.

    You might be a JavaScript wizz but you miss some key things on your site. If you do not mind me giving some friendly pointers (excuse the tone).

    1) either put the “Leave a comment” area below the article but above the comments OR at least have a link in the said spot that jumps to the form (basically at the footer).

    2) use the damn target=”_blank” on your anchors!!! so frustrating when I am reading an article and click on links that do not open separately.. Or better still #3;

    3) use the embed feature – not only will it make the article and example usable together on the page it lets me forgive you about (or it prevents) #2.

    4) When the sub-heading, or section speaks about a function or api – provide a link to its definition! in the case of JavaScript W3schools or Moz are great choices.

    Though thanks for your effort sharing this with the community, it was written well and the example demos are solid.
    Keep up the great work!

  29. 47

    People getting JavaScript confused with the DOM. JavaScript is the language, the DOM is that horrible API you use (generally from JavaScript) to manipulate elements on your page.

  30. 48

    why you are using javascript’s without plugins when using plugins such as jQuery are more comfortable than using with out them??


↑ Back to top