0

I'm starting out with divs arranged the following way. Two divs, main-top and main-bottom start out hidden and I want them to appear after they've been moved into the right spot. I want to move main-top to appear after header, and move main-bottom to appear before footer, and after they're moved, show the divs. How do you move these divs with jQuery? The final order should be header, main-top, main-bottom, footer

<div id='main'>

    <div id='main-top'>Main Top</div>
    <div id='main-bottom'>Main Bottom</div>

    <div id='header'>Header</div>

    <div id='footer'>Footer</div>

</div>

<style>
    #main-top {display: none;}
    #main-bottom {display: none;}
<style>

<script>
    //*Move 'main-top' to appear after 'header'*
    $('#main-top').show(); // Show div after it's moved

    //*Move 'main-bottom' to appear before 'footer'*
    $('#main-bottom').show(); // Show div after it's moved
</script>
Reddy
  • 21
  • 5

2 Answers2

0

You can use insertBefore and insertAfter funstions

$('#main-top').insertAfter('#header').show();
$('#main-bottom').insertBefore('#footer').show();
#main-top {display: none;}
#main-bottom {display: none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='main'>
    <div id='main-top'>Main Top</div>
    <div id='main-bottom'>Main Bottom</div>
    <div id='header'>Header</div>
    <div id='footer'>Footer</div>
</div>
Yosef Tukachinsky
  • 5,570
  • 1
  • 13
  • 29
0

This problem can be solved in a couple of ways, one way – with caveats – using CSS (with either CSS flex-box or Grid layouts) and another with JavaScript/jQuery.

First, with CSS flexbox:

/* we use flexbox layout on the element which
   contains the elements you wish to rearrange,
   which causes them to become flex-items, and
   this allows us to use the 'order' property
   to visually arrange them: */
#main {
  display: flex;
  flex-direction: column;
}

/* here we select the elements and use the
   'order' property with a numerical value
   to place them in the correct order within
   their parent element:  */

#header {
  order: 1;
}

#main-top {
  order: 2;
}

#main-bottom {
  order: 3;
}

#footer {
  order: 4;
}
<div id='main'>

  <div id='main-top'>Main Top</div>
  <div id='main-bottom'>Main Bottom</div>

  <div id='header'>Header</div>

  <div id='footer'>Footer</div>

</div>

and, with CSS Grid:

/* we use grid layout on the element which
   contains the elements you wish to rearrange,
   which causes them to become grid-items, and
   this allows us to use the 'order' property
   to visually arrange them: */
#main {
  display: grid;
  grid-auto-flow: row;
}

/* here we select the elements and use the
   'order' property with a numerical value
   to place them in the correct order within
   their parent element:  */
#header {
  order: 1;
}

#main-top {
  order: 2;
}

#main-bottom {
  order: 3;
}

#footer {
  order: 4;
}
<div id='main'>

  <div id='main-top'>Main Top</div>
  <div id='main-bottom'>Main Bottom</div>

  <div id='header'>Header</div>

  <div id='footer'>Footer</div>

</div>

There's a third CSS approach, again using CSS Grid layout, but taking advantage of the grid-template-areas and grid-area properties:

/* we use flexbox layout on the element which
   contains the elements you wish to rearrange,
   which causes them to become flex-items, and
   this allows us to use the 'order' property
   to visually arrange them: */
#main {
  display: grid;
  /* here we name several grid areas; each quoted string
     names the areas in that row, here we have four named
     rows and each row has only one column: */
  grid-template-areas:
    "header"
    "main-top"
    "main-bottom"
    "footer";
}

/* here we select the elements and use the
   'grid-area' property to place them each
   in the correct grid-area: */
#header {
  grid-area: header;
}

#main-top {
  grid-area: main-top;
}

#main-bottom {
  grid-area: main-bottom;
}

#footer {
  grid-area: footer;
}
<div id='main'>

  <div id='main-top'>Main Top</div>
  <div id='main-bottom'>Main Bottom</div>

  <div id='header'>Header</div>

  <div id='footer'>Footer</div>

</div>

The caveat of these approaches is that they affect only the visual presentation; the DOM is untouched and the positioned elements – whether using order or grid-area – remain in their original order for those users using alternative means of consumption (such as screen-readers).

Using native JavaScript, which does modify the DOM order:

// we retrieve, and cache, the <div id="header"> element,
// and then its parentNode:
const header = document.getElementById('header'),
      parent = header.parentNode;

// here we use the parentNode.insertBefore() method to
// place the 'header' before the 'parent' Node's
// first-child:
parent.insertBefore(header, parent.firstChild);
#main-top,
#main-bottom {
  display: none;
}

#header+#main-top,
#header+#main-top+#main-bottom {
  display: block;
}
<div id='main'>

  <div id='main-top'>Main Top</div>
  <div id='main-bottom'>Main Bottom</div>

  <div id='header'>Header</div>

  <div id='footer'>Footer</div>

</div>

This is functionally equivalent to your request, however your question specifically asks about:

  1. moving the #main-top element after the #header element, and
  2. moving the #main-bottom element before the #footer element.

With this in mind, if you really wish to move two elements instead of just the one, then the following should address your need in relation to the elements you wish to position alongside:

// retrieving and caching all elements using destructuring assigment:
const [parent, mainTop, mainBottom, header, footer] = document.querySelectorAll('div');

parent.insertBefore(mainTop, header.nextSibling);
parent.insertBefore(mainBottom, footer);
#main-top,
#main-bottom {
  display: none;
}

#header+#main-top,
#header+#main-top+#main-bottom {
  display: block;
}
<div id='main'>

  <div id='main-top'>Main Top</div>
  <div id='main-bottom'>Main Bottom</div>

  <div id='header'>Header</div>

  <div id='footer'>Footer</div>

</div>

Finally, of course, using jQuery if you wish to do so:

$('#header').after($('#main-top'));
$('#footer').before($('#footer'));
#main-top,
#main-bottom {
  display: none;
}

#header+#main-top,
#header+#main-top+#main-bottom {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='main'>

  <div id='main-top'>Main Top</div>
  <div id='main-bottom'>Main Bottom</div>

  <div id='header'>Header</div>

  <div id='footer'>Footer</div>

</div>
David Thomas
  • 249,100
  • 51
  • 377
  • 410