0

There are similar questions like this and this, but don't address this situation.

The goal is to slide a menu onto the screen with CSS translation when its parent is shown. However, showing the parent then applying the CSS class to trigger the translation happens instantly instead of over time. Effectively, there's no animation.

JavaScript could be used to slide the child element onto the screen, but the goal is to keep as much of the animation logic in CSS.

Setting the opacity to 0 doesn't work because we need the menu and its parent to not take any space or be part of the layout.

Codepen: https://codepen.io/Crashalot/pen/YzXmjYj

function toggleSidebar() {
  $("#sidebar").toggleClass("show");
}


$("#button").on("click", function() {
    toggleSidebar();
});
body {
  margin: 0;
  padding: 0;
}

#button {
  position: fixed;
  top: 0;
  left: 200px;
  width: 150px;
  height: 50px;
  background: yellow;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 8;
  cursor: pointer;
}

#sidebar {
  display: none;
}

#sidebar.show {
  display: block;
}

.overlay {
  position: fixed;
  width: 100vw;
  height: 100vh;
  background: red;
  z-index: -1;
}

.menuBox {
  width: 200px;
  height: 100vh;
  background: blue;
 transition: 0.3s ease-in-out;           
  transform: translate(-100%);
}

#sidebar.show .menuBox {
  transform: translate(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar">
  <div class="overlay"></div>
  <div class="menuBox"></div>
</div>


<div id="button">CLICK ME</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Crashalot
  • 33,605
  • 61
  • 269
  • 439

3 Answers3

2

You can't animate display: none; Set opacity to 0 and then 1 on toggle class. Here's the CodePen for you. ;)

I added a button for the toggle event. Let me know if you need any more help!

enter link description here

$(".btn").on("click", toggleSidebar);

function toggleSidebar() {
  $("#sidebar").toggleClass("show");
}
body {
  margin: 0;
  padding: 0;
}

#sidebar {
  opacity: 0;
  transition: all 300ms ease-in-out;
}

#sidebar.show {
  display: block;
  opacity: 1;

}

.overlay {
  position: fixed;
  width: 100vw;
  height: 100vh;
  background: red;
  z-index: -1;
}

.menuBox {
  width: 200px;
  height: 100vh;
  background: blue;
 transition: 300ms ease-in-out;           
  -webkit-transform: translate(-100%);
}

#sidebar.show .menuBox {
  -webkit-transform: translate(0);
}

.btn {
  position: absolute;
  top: 10px;
  left: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar">
  <div class="overlay"></div>
  <div class="menuBox"></div>
</div>

<button class="btn">Click</button>
Joel Hager
  • 2,990
  • 3
  • 15
  • 44
  • 1
    thanks for the fast response! sorry forgot to mention that the `#sidebar` element must be hidden and not take up space and be part of the layout flow. – Crashalot Apr 09 '20 at 06:53
  • opacity: 0 you seem only hide our eye but it still works any javascript event like a click, mouse event and others. you might be you 'visibility:hidden' with opacity:0. – Md. Abu Sayed Apr 09 '20 at 07:06
  • Can you clarify what you want the UX to be? On my end it seems to work as you seem to want. Maybe if you give some details as to what you'd like to see, I can modify the code for you. :) – Joel Hager Apr 09 '20 at 07:32
1

I think you should define the action for your function called. When load page or on click like below:

$(document).ready(function () {
    $('#sidebar').on('click', function () {
          $(this).toggleClass('show');
    });
});
Dung Le
  • 96
  • 4
1

You need to consider an animation. The animation will run automatically when the element appear on the screen

function toggleSidebar() {
  $("#sidebar").toggleClass("show");
}


$("#button").on("click", function() {
  toggleSidebar();
});
body {
  margin: 0;
  padding: 0;
}

#button {
  position: fixed;
  top: 0;
  left: 200px;
  width: 150px;
  height: 50px;
  background: yellow;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 8;
  cursor: pointer;
}

#sidebar {
  display: none;
}

#sidebar.show {
  display: block;
}

.overlay {
  position: fixed;
  width: 100vw;
  height: 100vh;
  background: red;
  z-index: -1;
}

.menuBox {
  width: 200px;
  height: 100vh;
  background: blue;
  transform: translate(-100%);
  animation: show 0.3s ease-in-out forwards;
}

@keyframes show {
  to {
    transform: translate(0);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar">
  <div class="overlay"></div>
  <div class="menuBox"></div>
</div>


<div id="button">CLICK ME</div>

updating display to a value other than none will start all animations applied to the element by the animation-name property, as well as all animations applied to descendants with display other than none. ref

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • thanks for this! can you explain why a CSS animation works but not animation achieved via the `transform` property? – Crashalot Apr 09 '20 at 08:17
  • 1
    @Crashalot added the part of Spec explaining why it works with animation With transition it's a bit tricky but the issue is that you aren't changing the value since initially the element isn't shown and when you add it using display:block it will be added with the new values (the old one never existed) so you will see no transition because for the browser it comes with the last value – Temani Afif Apr 09 '20 at 08:24