Tanasos
Tanasos

Reputation: 4098

Animate div positioning rearrangement

I am building a simple push-down effect which affects the position of two containers. So far I have managed to achieve a near-desired effect using fixed positioning for the hidden container while changing its position to a relative for the opened state.

I want to apply a smooth transition to the blue main div, which is being pushed down by the hidden div with a class of .sub-header. How can I bypass the choppy rearrangement of the containers and is there a more elegant way of doing this instead of switching positioning on click? (e.g. fixed to a relative in this case)

Currently, when I switch the positioning from fixed to a relative as expected - there is a gap being produced, which is the .sub-header's height.

NOTE: The heights of the current divs are fixed values, but I need this to be able to handle dynamic changes in the .sub-header height.

NOTE: This should be achieved by adding a custom class, not using jQuery's nested effects like .slideToggle etc.

Here is the Fiddle.

And the simple jQuery function needed for the Fiddle share:

$('.trigger').click(function() {
  $('.sub-header').toggleClass('opened');
}).stop();

Upvotes: 1

Views: 93

Answers (3)

wscourge
wscourge

Reputation: 11291

Correct me if I misunderstood your question, but I guess there's much simpler approach to what you're trying to achieve. Try changing corresponding classes in your CSS code:

.sub-header {

  background: gainsboro;
  height: 0;
  -webkit-transition: height .3s linear;
  transition: height .3s linear;
}

.opened {
  height: 150px;
}

Here's the fiddle. My approach does not cover all bases, as you can see there is still text visible in the hidden container, which is going to need some additional workaround in your js or css, but I guess it is simpler than yours, considering that your .sub-container has fixed height.

EDIT

For non fixed height, there is workaround in my approach:

.sub-header {

   background: gainsboro;
   height: auto;
   max-height: 0px;
   -webkit-transition: max-height .3s linear;
   transition: max-height .3s linear;
}

.opened {
   max-height: 400px;
}

but it still needs to be adjusted - when you set .opened's max-height to the lower value, transition is going to be slower. It is not perfect, thought it covers cases, where .sub-containers' heights are relatively similar.

Upvotes: 1

RizkiDPrast
RizkiDPrast

Reputation: 1725

please check this out. we can use margin for styling and keep position the same relative

$('.trigger').click(function() {
  $('.sub-header').toggleClass('opened');
}).stop();
body {
  font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

header,
.sub-header,
main {
  display: flex;
  justify-content: center;
  align-items: center;
  align-content: center;
  flex-direction: column;
  font-weight: bold;
  text-transform: uppercase;
  color: #fff;
  transition: all .5s ease-in-out;
}

header {
  height: 100px;
  background: tomato;
  z-index: 1000;
  position: relative;
}

.sub-header {
  height: 150px;
  background: gainsboro;
  transform: translateY(-200%);  
  left: 0;
  right: 0;
  z-index: 10;
  /*play with position and margin*/
  position: relative;
  margin-bottom:-200px;
}

.opened {  
  transform: translateY(0%);
  margin-bottom:0;
}

main {
  height: 250px;
  background: deepskyblue;    
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<header>Header content <a href="#" class="trigger">TRIGGER</a></header>
<div class="sub-header">
  <p>Sub Header content</p>
</div>
<main>Main Content</main>

Upvotes: 0

jafarbtech
jafarbtech

Reputation: 7015

Make position: relative; and do margin top for animating

$('.trigger').click(function() {
  $('.sub-header').toggleClass('opened');
}).stop();
body {
  font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

header,
.sub-header,
main {
  display: flex;
  justify-content: center;
  align-items: center;
  align-content: center;
  flex-direction: column;
  font-weight: bold;
  text-transform: uppercase;
  color: #fff;
  transition: all .5s ease-in-out;
}

header {
  height: 100px;
  background: tomato;
  z-index: 1000;
  position: relative;
}

.sub-header {
  height: 150px;
  background: gainsboro;/*
  transform: translateY(-200%);*/
  margin-top:-150px;
  left: 0;
  right: 0;
  z-index: 10;
  position: relative;
}

.opened {/*
  transform: translateY(0%);*/
  margin-top:0;
}

main {
  height: 250px;
  background: deepskyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>Header content <a href="#" class="trigger">TRIGGER</a></header>
<div class="sub-header">Sub Header content</div>
<main>Main Content</main>

Update:-

As to get -100% you have make it float and set all width to 100%

$('.trigger').click(function() {
  $('.sub-header').toggleClass('opened');
}).stop();
body {
  font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

header,
.sub-header,
main {
  display: flex;
  justify-content: center;
  align-items: center;
  align-content: center;
  flex-direction: column;
  font-weight: bold;
  text-transform: uppercase;
  color: #fff;
  transition: all .5s ease-in-out;
}

header {
  width:100%;
  height: 100px;
  background: tomato;
  z-index: 1000;
  position: relative;
}

.sub-header {
  height: 150px;
  width:100%;
  background: gainsboro;/*
  transform: translateY(-200%);*/
  margin-top:-100%;
  left: 0;
  right: 0;
  z-index: 10;
  float:left;
}

.opened {/*
  transform: translateY(0%);*/
  margin-top:0;
}

main {
  width:100%;
  height: 250px;
  background: deepskyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>Header content <a href="#" class="trigger">TRIGGER</a></header>
<div class="sub-header">Sub Header content</div>
<main>Main Content</main>

Upvotes: 2

Related Questions