24

How would I go about reordering divs without altering the HTML source code?

example, I want divs to appear in order #div2, #div1, #div3, but in the HTML they are:

<div id="#div1"></div>  
<div id="#div2"></div>  
<div id="#div3"></div>

Thanks!

isherwood
  • 58,414
  • 16
  • 114
  • 157
Alexandre
  • 5,035
  • 7
  • 29
  • 36
  • Thank you for your answers. My current solution does what a lot of you recommended, it messes around with the HTML. I was wondering if there was a reliable way to do the sorting without touching the HTML, and I guess you guys have answered: no. I appreciate your help! – Alexandre Feb 17 '09 at 22:00

6 Answers6

24

There is no catch-all way of reordering elements with css.

You can inverse their order horizontally by floating them all to the right. Or you can position them absolutely relative to the body or some other containing element - but that comes with severe limitations regarding the size of the elements, and positioning relative to other elements on the page.

Short answer: You can only achieve this in a very limited set of circumstances. Reordering elements is best done in markup.

If you have no control over the html, you could use javascript. Here using jQuery:

$("#div2").insertAfter("#div3");
$("#div1").prependTo("#div2");

I certainly don't recommend that unless your hands are tied. It will be harder to maintain, and for your end users it will make your page "jerk around" while its setting up the page.

Magnar
  • 28,550
  • 8
  • 60
  • 65
  • 1
    Your wording is unfortunate, because you're starting with a false statement. ***There is*** a catch-all way of reordering elements with CSS: [order](https://developer.mozilla.org/en-US/docs/Web/CSS/order). It basically does not matter in what order they are in DOM, they will be displayed in the order specified by the element's `order` CSS prop, when this prop is specified (and valid). – tao Dec 13 '21 at 21:18
  • Note: `order` only works inside elements with a `display` value of `flex` or `grid` (or their `inline-*` variants). – tao Dec 13 '21 at 21:28
  • @tao While this is true visually, it's worth nothing that the CSS `order` property doesn't affect things like tab order between form fields. – Sandwich Dec 14 '22 at 12:11
  • @Sandwich, quite true. Tab order navigates elements in the order of `tabindex`. Elements with the same `tabindex` value are navigated in the order they are found in DOM tree. CSS `order` allows re-ordering sibling elements in a different order than they are found in DOM tree. – tao Dec 14 '22 at 13:00
16

Since now flexbox is widely supported you can also use it to reorder divs using only css:

<div id="container">
    <div id="div1">1</div>  
    <div id="div2">2</div>  
    <div id="div3">3</div>
</div>

And css:

#container{
  display: flex;
  flex-direction: column;
}

#div2{
  order:2
}

#div3{
  order:1
}

It would display:

1
3
2

You can try it on this fiddle.

Krzysztof Atłasik
  • 21,985
  • 6
  • 54
  • 76
  • 1
    Interesting! Using Javascript to change the CSS order attribute does not redraw the elements (e.g., element.style.order = 20;). Great. So it is possible to reorder elements without redraw! – There Mar 19 '20 at 16:53
  • 2
    Unfortunately MDN says you shouldn't to this if changing up the order is more than just a visual distraction ie. it actually has some meaning like in search results for example, because it isn't picked up on by screen readers: *Since order is only meant to affect the visual order of elements and not their logical or tab order. order must not be used on non-visual media such as speech.* https://developer.mozilla.org/en-US/docs/Web/CSS/order – math2001 Mar 14 '21 at 22:50
15

I would use Javascript to traverse the nodes accordingly. If you want to use a library like jQuery, you can use the above suggestions. If you'd prefer not to have the bloat, use the following simple and minimalistic solution...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Test</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <script type="text/javascript">
      function swapSibling(node1, node2) {
        node1.parentNode.replaceChild(node1, node2);
        node1.parentNode.insertBefore(node2, node1); 
      }

      window.onload = function() {
        swapSibling(document.getElementById('div1'), document.getElementById('div2'));
      }
    </script>
  </head>
  <body>
    <div id="div1">1</div>
    <div id="div2">2</div>
    <div id="div3">3</div>
  </body>
</html>

Best regards...

EDIT: Changed function name from swapNode to swapSibling, as I am fairly certain this will only work with nodes that have the same parent.

Josh Stodola
  • 81,538
  • 47
  • 180
  • 227
11

In jQuery, you can do the following:

$("#div1").insertAfter("#div2");

That will move the element with id 'div1' to after element with id 'div2'. This assumes that you eliminate the '#' from your id attributes.

jonstjohn
  • 59,650
  • 8
  • 43
  • 55
5

You could do, in Javascript:

function reOrder() {
  divOne = document.getElementById('#div1');
  divTwo = document.getElementById('#div2');
  divThree = document.getElementById('#div3');
  container = divOne.parentNode;
  container.appendChild(divTwo);
  container.appendChild(divOne);
  container.appendChild(divThree);
}

Edit: Fixed typo in IDs.

user64640
  • 93
  • 2
0

Since you tagged jQuery, you could use javascript to remove the elements and then re-insert them although that may not be all too flexible.

Having a bit more context would net you better answers I think.

Tom Ritter
  • 99,986
  • 30
  • 138
  • 174