Context: I have a div
on the top of the page that I show / hide from a button. The div
is under the button and above the content. I've used transition-group
so that the rest of the content slides up/down over the div
when it shows/hides. The content has a margin-top
so that it limits itself from the above div
that shows/hides.
Need: I want a margin on top of the div
so that when it's shown, it retains space between itself and the button.
https://imgur.com/UG5iakC
Problems: I've tried 2 ways:
1) Placing a margin-top to the hiding div
.
Because I have position:absolute
on the div
when hiding it so that the content gets over the div
, the div
resizes to the size of the content, and so the margin gets automatically smaller; so when hiding it, the margin gets smaller before it hides, and it's ugly.
GIF: https://gph.is/2QInDfj
2) Adding an hr
above the div
, inside the transition-group
. Without the hr
, the slide works just as intended, over the div
. But when I add the hr
and click to hide the div
, the slide happens just as intended but the div
and hr
disappear instantly, instead of it showing and the content sliding over it and covering it.
GIF: https://gph.is/2yd4JGt
Desired visual effect without the margin/hr on top: https://gph.is/2OPZyFV
HTML
<transition-group name="slide">
<hr class="m-0" v-if="isVisible" key='h'>
<div class="d-flex" v-if="isVisible" id="filters" key='x'>
<div class="pl-5">
<p class="filterTitles">Day</p>
<app-day-filter v-for="day in weekDay"
:key="day.index"
:day="day">
</app-day-filter>
</div>
<div class="pl-5">
<p class="filterTitles">Time of day</p>
<app-tod-filter v-for="todf in tod"
:key="tod.index"
:todf="todf">
</app-tod-filter>
</div>
</div>
<app-event v-for='(eveniment, index) in filterEvent'
:key='index'
:eveniment='eveniment'
:index='index'></app-event>
</transition-group>
CSS
.slide-enter {
opacity:0;
}
.slide-enter-active {
transition: all 1s ease-out;
}
.slide-leave-active{
transition: all 1s ease-out;
opacity: 0;
position: absolute;
}
.slide-move {
transition: transform 1s;
}
#filters {
/* border-top: 1px solid lightgrey; */
}
Suggestions?
Thanks
This is primarily a CSS concern.
If the hr
element is introduced into the layout within the transition-group
, and, the transition
CSS property is concerned with all
, and, position
is being set to absolute
during the leave-active
state (which will cause the element to "disappear" from its previous, relative position in the layout flow), then numerous elements and properties are going to be transitioned simultaneously, resulting in undesired effects.
However, given that the question seeks a solution without the margin
and hr
on top of the transition-group
, and assuming the button has an event handler, like this:
<button class="filter-button" v-on:click="toggleSlider">Filters</button>
The function toggleSlider
will toggle the isVisible
property that the animated transition depends upon:
methods: {
toggleSlider() {
this.isVisible = !this.isVisible;
}
}
And with CSS, instead of transitioning all
, merely transition the properties that will achieve the sought after effect, namely, opacity
, and with this answer, max-height
. By removing the absolute positioning altogether, and using relative position plus z-indexing with the following CSS, the desired effect is achieved.
/* put margin spacing on the bottom of the button */
.filter-button {
margin-bottom: 25px;
}
/* add relative positioning to enforce z-indexing */
.filter-group {
position: relative;
z-index: 1;
}
/* add relative positioning to enforce z-indexing */
.filter-content {
position: relative;
z-index: 2;
}
/* hidden states */
.slide-enter,
.slide-leave-to {
opacity: 0;
max-height: 0px;
}
/* shown states - max-height can be adjusted as desired */
.slide-enter-to,
.slide-leave {
opacity: 1;
max-height: 300px;
}
/* while animating during animation entry phase */
.slide-enter-active {
transition: opacity 0.75s ease-in, max-height 0.5s ease-out;
}
/* while animating during the animation departure phase */
.slide-leave-active {
transition: opacity 0.75s ease-out, max-height 0.5s ease-out;
}
/* add padding to bottom of filters section */
.pl-5 {
padding-bottom: 25px;
}
By adding margin to the bottom of the button and the filter section, the spacing between sections is preserved.
I've created a CodeSandbox to illustrate this solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With