I am using purely CSS to create a dynamically opening and closing sidebar based on the view-port with of the page. I have a couple issues with my code however:
How can I prevent an animation when the screen first loads? That is, I simply want the sidebar to be opened or closed on first loading, and then animated when the view-port is adjusted.
Why do I have to have two separate animations? Notice I have two identical keyframes toggle and toggle1, which are used for closing and opening respectively. If I try to use just toggle for both animations, the animation occurs instantly. Any workaround without duplicated code?
body {
margin: 0;
padding: 0;
overflow: hidden;
}
#sidebar {
position: absolute;
width: 200px;
background-color: #123456;
height: 100vh;
}
#media (min-width: 500px) {
#sidebar {
animation: toggle 200ms ease-in 1 reverse forwards;
}
}
#media (max-width: 500px) {
#sidebar {
animation: toggle1 200ms ease-out 1 normal forwards;
}
}
#keyframes toggle {
0% {
left: 0px;
}
100% {
left: -200px;
}
}
#keyframes toggle1 {
from {
left: 0px;
}
to {
left: -200px;
}
}
<div id="sidebar"></div>
Just use a simple transition instead of animation, and 1 media query
#sidebar {
position: absolute;
width: 200px;
background-color: #123456;
height: 100vh;
transition:left 500ms ease;
left:0;
}
#media (max-width: 500px) {
#sidebar {
left: -200px;
}
}
https://jsfiddle.net/ufoste1y/3/
You can also use transform:translateX, which should provide better performance.
#sidebar {
position: absolute;
width: 200px;
background-color: #123456;
height: 100vh;
transition:transform 500ms ease;
}
#media (max-width: 500px) {
#sidebar {
transform: translateX(-200px);
}
}
https://jsfiddle.net/ufoste1y/8/
In order to force the sidebar to be opened or closed by default, that cannot be done with raw CSS. You'd need JavaScript to wait until the page has finished loading, and then dynamically update the element to have a class or similar that the CSS animation applies to.
As for the duplicate code, you can certainly just use toggle. It not working for you was probably a result of you forgetting to also change the #media animation reference from toggle1 to toggle.
Here's an example showing the sidebar staying open by default with the aid of JavaScript. The animation is now triggering only on the .loaded class, and the JavaScript applies the loaded class to the element 1000 milliseconds after the page has loaded, meaning that it won't trigger the animation initially.
Having said that, you'll probably only want to trigger the slide on some sort of condition anyway, and JavaScript would be much better suited to that :)
window.addEventListener("load", function() {
setTimeout(function() {
var sidebar = document.getElementById("sidebar");
sidebar.classList.add("loaded");
}, 1000);
});
body {
margin: 0;
padding: 0;
overflow: hidden;
}
#sidebar {
position: absolute;
width: 200px;
background-color: #123456;
height: 100vh;
}
#media (min-width: 500px) {
#sidebar.loaded {
animation: toggle 200ms ease-in 1 reverse forwards;
}
}
#media (max-width: 500px) {
#sidebar.loaded {
animation: toggle 200ms ease-out 1 normal forwards;
}
}
#keyframes toggle {
0% {
left: 0px;
}
100% {
left: -200px;
}
}
<div id="sidebar"></div>
Related
why animation can be reusable after im changing elemets display property with js
can some one explain i couldnt find any answer for this
can someone explain me this
my codes downbelow
`
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
aside {
display: none;
position: relative;
left: -100%;
height: 100vh;
background-color: red;
width: 20%;
animation: openit 800ms ease-in forwards ;
}
#keyframes openit {
to{
left: 0;
}
}
aside a {
display: block;
}
.open {
position: absolute;
z-index: -1;
}
</style>
`
I found this:
When we want to use transition for display:none to display:block, transition properties do not work. The reason for this is, display:none property is used for removing block and display:block property is used for displaying block. A block cannot be partly displayed. Either it is available or unavailable. That is why the transition property does not work.
form this link. I hope this help.
I have a drawer menu that appears on screen after clicking a button. The transition is a little laggy using absolute positioning so I went with using translate3d. The menu has two widths. One that's 100% of the view for mobile and 395px for viewports 600px and up. One quirk I'm noticing is that if I were to resize my screen, the menu will subtly appear. Is there a way to get the menu to completely stay off-screen when this happens?
Note: To see this, expand the snipped to full-screen and horizontally resize to 600px or lower. You should see see the div appear and go back off-screen.
$('button').on('click', function() {
$('#drawer').toggleClass('active');
});
html,
body {
height: 100%;
margin: 0;
}
#drawer {
width: 100%;
height: 100%;
background-color: grey;
transition: transform .5s ease-in;
transform: translate3d(-100%, 0, 0);
}
#drawer.active {
transform: translate3d(0, 0, 0);
}
#media (min-width: 600px) {
#drawer {
transform: translate3d(-395px, 0, 0);
width: 395px;
}
}
button {
position: absolute;
top: 10px;
left: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drawer"></div>
<button>Toggle Drawer</button>
The problem: A transition is set on the drawer's transform property. When it hits the designated media query, the drawer transitions to it's new x coordinate.
The solution: Instead of putting the responsibility of placement solely on transform, use absolute positioning and initially offset the drawer to its' negative width. In this case it would be 395px. On the active state, the transform3d property would be the width of the drawer to bring it back into the visible part of the window.
$('button').on('click', function() {
$('#drawer').toggleClass('active');
});
html,
body {
height: 100%;
margin: 0;
}
#drawer {
width: 100%;
height: 100%;
position: absolute;
left: -100%;
background-color: grey;
transition: transform .5s ease-in;
transform: translate3d(0,0,0);
}
#drawer.active {
transform: translate3d(100%, 0, 0);
}
#media (min-width: 600px) {
#drawer {
left: -395px;
width: 395px;
}
#drawer.active {
transform: translate3d(395px, 0, 0);
}
}
button {
position: absolute;
top: 10px;
left: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drawer"></div>
<button>Toggle Drawer</button>
I have a question a bout why my CSS code doesn't work when put after an animation.
Here is the example :
img {
max-width: 50px;
}
#keyframes slidedown {
from {
margin-top: 100%;
height: 300%;
to {
margin-top: 0%;
height: 300%;
}
}
img {
max-width: 50px;
}
img will be 50px if I put it before the animation, and will fill the entire page when put after the animation.
This is just an example (the animation is about a text). But I can't understand why my CSS code doesn't work written after the animation.
You're missing a closing } after the from declaration and before the to declaration. Try:
#keyframes slidedown {
from {
margin-top: 100%;
height: 300%;
}
to {
margin-top: 0%;
height: 300%;
}
}
I'm trying to learn CSS animations and one thing I can't figure out and couldnt find on the web is how to set the proper duration.
I'm trying to have my website responsive therefore the font size would change depending on the size of the view. I have the following code so far:
#media screen {
.EntranceDiv{
top: 40%;
position: relative;
}
h1 {
font-size: 4rem;
margin: 0px;
}
.helloworld{
overflow: hidden; /* Ensures the content is not revealed until the animation */
border-right: .15em solid #D9FAFF; /* The typwriter cursor */
white-space: nowrap; /* Keeps the content on a single line */
margin: 0 auto; /* Gives that scrolling effect as the typing happens */
letter-spacing: .8em;
display: inline-block;
animation:
typing initial steps(30, end),
blink-caret .5s step-end infinite;
}
#keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: #D9FAFF }
}
#keyframes typing {
from { width: 0 }
to { width: 65% }
}
}
My problem is that with the changes in the font size, the animation either goes for too long or for too short and then the whole thing just pops on the screen. What is a good way of setting duration for responsive animations
Your main issue here is that the width you set is relative to parent container so it has no relation with the content of your inline-block element. You need to find a way to correctly set the width of the element.
Since you cannot make a transition to width:auto, here is an idea where I duplicate the content and I use a pseudo-element with absolute position. The first content will define the width and will be hidden and the second one will be visible and I can stretch to fit the defined width using left/right properties:
h1 {
font-size: 4rem;
margin: 0px;
}
.helloworld {
letter-spacing: .8em;
display: inline-block;
position:relative;
visibility:hidden;
white-space: nowrap;
}
.helloworld:after {
content:attr(data-content);
display:block;
visibility:visible;
overflow: hidden;
white-space: nowrap;
position:absolute;
top:0;
left:0;
bottom:0;
right:100%;
border-right: .15em solid #D9FAFF;
animation: typing 2s steps(30, end) forwards, blink-caret .5s step-end infinite;
}
#keyframes blink-caret {
from,
to {
border-color: transparent
}
50% {
border-color: #D9FAFF
}
}
#keyframes typing {
from {
right:100%
}
to {
right: 0%
}
}
}
<h1 data-content="lorem" class="helloworld">
Lorem
</h1>
<h1 data-content="lor" class="helloworld">
Lor
</h1>
<h1 data-content="lorem ipsume" class="helloworld">
Lorem ipsume
</h1>
I've noticed that transition is not working when the element is also changing from display none to block. Why is that? It works if I remove the display attribute.
CSS:
#box {
width: 150px;
height: 150px;
background: red;
transform: scale(0);
display: none;
transition: transform .5s;
}
#box.active {
transform: scale(1);
display: block;
}
http://jsfiddle.net/640kL55u/
Because it has display: none to begin with, the other styles are not being taken into the dom to be transitioned once display: block is added.
Instead, you can hide the div with height, so its still on the page but not showing. Then add the height on the show div.
JS Fiddle
Any change from or to display: none won't trigger transitions.
You can, however, change the display property and then add the class name at the end of the javascript stack. For instance:
function showElem(elem) {
elem.style.display = "block";
setTimeout(function() {
elem.classList.add("active");
}, 0);
}
And then pass element nodes to this function.
You can't transition with display: none; properties...
$("button").on("click", function() {
$("#box").addClass("active");
});
#box {
width: 0;
height: 0;
overflow: hidden;
background: red;
transform: scale(0);
transition: transform .5s;
}
#box.active {
width: 150px;
height: 150px;
transform: scale(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="box"></div>
<button>CLICK</button>