Make navigation menu slide in - javascript

How would I go about making this menu slide in on hamburger menu click? The background of it is an SVG and not an actual shape.
https://codepen.io/KirbStarRulz/pen/GdzOyM
$(document).ready(function() {
$('.hamburger-container').on('click', function(e) {
e.preventDefault();
$('.hideMenu').toggleClass('slideInMenu');
});
});
function myFunction(x) {
x.classList.toggle("change");
}
Here's an image of what I need slid in (orange trapezoid on the right)
https://ibb.co/nRrr1T
Thanks!

If I understand correctly you want to slide in navigation. Your code works fine the only problem is negative z-index because of it your navigation is below all other elements.
.hideMenu {
background-image: url(images/kreativez_menu_bg.svg);
width: 48%;
height: 100%;
background-size: cover;
position: fixed;
transform: translateX(200%);
z-index: 100;
top: 0;
left: 0;
transition: transform 0.5s linear;
}

Related

Transitions effect between pages with svg image, css, html, js

Ok, maybe stackoverflow can help? :)
I'm trying, without any luck, to create a page transition effect with an svg image.
When the user clicks on a link in Page 1, a diamond shaped svg fades in like a portal into Page 2.
The basic idea is to recreate the space travel in the intro of the Alphaville - Forever Young video: https://www.youtube.com/watch?v=t1TcDHrkQYg
:)
Maybe the diamond also fades in from blue to transparent (but that is the next step).
Diamond svg: https://www.onlinewebfonts.com/icon/413
I suggest you use clip-path instead of a svg since animating an svg that big will be really slow and really laggy. You can change the clip path to show what you want. Bennet Feely created a nice generator that helps with this.
For the animation itself you can increase the width and height to fit your screen. Then fill the remainder by animating the Z axes.
Animation looks better in fullscreen then in the smaller preview
const links = document.querySelectorAll(".page-transition");
const overlay = document.querySelector(".overlay__diamond");
for(const link of links) {
link.addEventListener("click", (event) => {
event.preventDefault();
overlay.classList.add("overlay__diamond--animate");
setTimeout(() => window.location.reload(), 1000);
// This one is correct, one above is for the demo
// setTimeout(() => (window.location.href = link.href), 1000); // Same time as animation duration
});
}
.page {
background: green;
/* For demontrational purposes only, just to increase page size */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.overlay {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
pointer-events: none;
perspective: 500px; /* Needed for translateZ to work */
}
.overlay__diamond {
width: 100%;
height: 100%;
background: blue;
animation: fadeout 1s linear forwards;
}
.overlay__diamond--animate {
animation: zoom 1s linear forwards;
clip-path: polygon(50% 0%, 75% 50%, 50% 100%, 25% 50%);
}
#keyframes fadeout {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes zoom {
0% {
width: 0;
height: 0;
transform: translateZ(0);
}
100% {
width: 100%;
height: 100%;
transform: translateZ(400px); /* Can't go higher then the perspective */
}
}
<div class="page">
<!-- Replace #link with your actual urls -->
<a class="page-transition" href="#link">Link</a>
<a class="page-transition" href="#link">Link</a>
<a class="page-transition" href="#link">Link</a>
<div class="overlay">
<div class="overlay__diamond"></div>
</div>
</div>

Fade background from right to left

I managed with the help of the ScrollMagic library to change my background img for my section three-section-container depending on scroll position. Additionally, I managed to add an overlay that will appear only when I am on a certain section of my page.
My issue now is that I would like to animate how background image changes (I want to come from right to left and stay positioned in the middle/ as you can see in code the background is changing 2 times). I tried with `transform: translateY(40px);
property in CSS but the result was inconsistent because the image would not be 100% of my screen. Also, I want my overlay to come from left to right, and I am quite confused how.
HTML
<div id="bigSection" class="three-section-container ">
<div id="target-overlay" class=" "></div>
<div class="sec1 " id="project01"></div>
<div class="sec2 " id="project02"></div>
<div class="sec3" id="project03"></div>
</div>
CSS
.three-section-container{
position: relative;
background-color: black;
transition: all 3s ease;
background-image: url('../../Assets/Images/graphic/last/poza-augmented-reality.png');
background-repeat: no-repeat;
background-color: black;
background-size: 100% 100vh;
background-attachment: fixed;
}
.fade-img1{
transition: all 1s ease;
background-image: url('../../Assets/Images/graphic/last/poza-augmented-reality.png');
background-repeat: no-repeat;
background-color: black;
background-size: 100% 100vh;
background-attachment: fixed;
// transform: translatey(20px);
opacity: 1;
margin: 0;
z-index: 999;
}
.fade-img2{
background-image: url('../../Assets/Images/graphic/last/2.png');
background-repeat: no-repeat;
background-color: black;
background-size: 100% 100vh;
background-attachment: fixed;
opacity: 1;
transition: all 1s ease;
margin: 0;
z-index: 999;
}
.fade-img3{
background-image: url('../../Assets/Images/graphic/last/poza-interior.png');
background-repeat: no-repeat;
background-color: black;
background-size: 100% 100vh;
background-attachment: fixed;
// transform: translateY(40px);
opacity: 1;
transition: all 0.3s ease;
margin: 0;
z-index: 999;
}
.sec1, .sec2, .sec3{
height: 100vh;
}
.overlay {
transition: 0.3s linear all;
position: absolute; /* Sit on top of the page content */
width: 40%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5); /* Black background with opacity */
z-index: 999; /* Specify a stack order in case you're using a different order for other elements */
}
JS
$(document).ready(function(){
var controller=new ScrollMagic.Controller()
// build a scene
var ourScene= new ScrollMagic.Scene({
triggerElement:'#project01',
duration:"100%"
})
.setClassToggle('#bigSection', 'fade-img1')
.addIndicators({
name:'fade scene',
colorTRigger:'black',
indent:200,
colorStart:'#75c695'
})
.addTo(controller)
var ourScene= new ScrollMagic.Scene({
triggerElement:'#project02',
duration:"100%"
})
.setClassToggle('#bigSection', 'fade-img2')
.addIndicators({
name:'fade scene',
colorTRigger:'black',
indent:200,
colorStart:'#75c695'
})
.addTo(controller)
var ourScene= new ScrollMagic.Scene({
triggerElement:'#project03',
duration:"200%"
})
.setClassToggle('#bigSection', 'fade-img3')
.addIndicators({
name:'fade scene',
colorTRigger:'black',
indent:200,
colorStart:'#75c695'
})
.addTo(controller)
var ourScene= new ScrollMagic.Scene({
triggerElement:'#project01',
// duration:"200%"
})
.setClassToggle('#target-overlay', 'overlay')
.addIndicators({
name:'overlay',
colorTRigger:'black',
indent:200,
colorStart:'#75c695'
})
.addTo(controller)
})
Any help is welcomed. Thank You
I'm not familiar with the ScrollMagic API but I think this code snippet can make things a little cleared from the JS and CSS prospective involved in the animation.
In fact most of them can be done without the need of externals API but just triggering back an forth a CSS class !
Hope this helps you a little bit:
let animationDone = false;
window.addEventListener("scroll", () => {
/*
* IF you scrolled more than a certain amount:
* in this case i choose half a page height's (50vh),
* you trigger the slide animation by adding the onscreen class to the background2 div.
* Otherwise if you previously triggered the animation and
* you scrolled in the opposite direction: the animation is triggered backwards.
*/
if(window.scrollY > window.innerHeight / 2) {
document.getElementsByClassName("background2")[0].classList.add("onscreen");
document.getElementById("secondPage").classList.add("onscreen");
animationDone = true; //We makes sure that we always know the state of our animation
} else if(animationDone) {
document.getElementsByClassName("background2")[0].classList.remove("onscreen");
document.getElementById("secondPage").classList.remove("onscreen");
animationDone = false; //We makes sure that we always know the state of our animation
}
}, {passive:true});
body {
color:white;
margin: 0;
width:100vw;
height:200vh; /* 200vh is only for demo purposes: it allows to scroll the html body even thought there's nothing inside */
}
#mainContent {
text-align: center;
z-index: 99;
position: absolute;
}
#mainContent > * {
display: flex;
justify-content: center;
align-items: center;
}
#firstPage {
width: 100vw;
height: 100vh;
}
#secondPage {
width: 100vw;
height: 100vh;
opacity: 0; /* This makes our background2 div transparent as soon as its hidden */
transform: translateX(-100vw); /* This shifts our background to the left by 100vw (its width) */
transition: 1s; /* The page content animation's duration */
}
#secondPage.onscreen {
/*
* This cancels the second page's previous shift (to left) when the onscreen class is applied to secondPage div
* in 0.3s so that it won't snap-> the left to right transition is realized !
*/
transform: translateY(0);
opacity: 1; /* This makes our background2 fades from transparent (its original state) to opaque */
}
.background1 {
z-index: 1; /* Lower stacking index than the other background to hide it */
position: fixed;
width: 100vw;
height: 100vh;
background: red;
}
.background2 {
z-index: 2; /* Higher stacking index than the other background to show it*/
position: fixed;
width: 100vw;
height: 100vh;
background: blue;
opacity: 0; /* This makes our background2 div transparent as soon as its hidden */
transform: translateX(100vw); /* This shifts our background to the right by 100vw (its width) */
transition: 0.3s; /* The background2 animation's duration */
}
.background2.onscreen {
/*
* This cancels the background's previous shift when the onscreen class is applied to background2
* in 0.3s so that it won't snap-> the right to left transition is realized !
*/
transform: translateY(0);
opacity: 1; /* This makes our background2 fades from transparent (its original state) to opaque */
}
<body>
<div id = "mainContent">
<h1 id = "firstPage">The main content goes here</h1>
<h1 id = "secondPage">Animation Triggered !</h1>
</div>
<div class = "background1"></div>
<div class = "background2"></div>
</div>
</body>

How to build a CSS animation that "slides in", revealing a text/div after it finishes sliding?

I am trying to mimic the CSS animations from a website here: https://stanographer.com/
I want to copy the way the site:
starts by showing a full screen black div sliding away to the right
"loads" the black background (div tags) behind text (as in "Hi, I'm Stanley Sakai"), expanding left to right and
"loads" the text over the black background div, expanding left to right.
Now you might ask, "Why not just inspect the page, look at the classes on the divs and text, then inspect the CSS sheet in the network tab?" And I've tried that. The CSS looks weird. My friend said it is pre-processed by SASS, whatever that means. Anyway, I cannot decipher the code.
I've been to a few different StackOverflow pages (here's one) & over a dozen different pages on Google. I learned about using keyframes but I haven't figured out how to recreate the effect on Stanographer.com. My friend, who owns the website, also provided this example, but I don't get how to apply it to individual divs. He said something about using the z-index but I just don't see it.
I know that to make the page start with a full black screen & then slide out, I have to trigger a class change using JavaScript. I have:
let blackStuff = document.getElementById("blackness");
window.addEventListener("load", () => {
console.log("loaded");
blackStuff.setAttribute("class", "black-box-out");
},
false
);
.black-box {
position: fixed;
float: left;
top: 0;
width: 100%;
height: 100%;
bottom: 0;
background-color: #000;
z-index: 999999;
-webkit-animation: powerslide 0.5s forwards;
-webkit-animation-delay: 2s;
animation: powerslide 0.5s forwards;
animation-delay: 2s;
}
#-webkit-keyframes powerslide {
100% {
left: 0;
}
}
#keyframes powerslide {
100% {
left: 0;
}
}
.black-box-out {
margin-left: 100%;
animation: slide 0.5s forwards;
-webkit-transition: slide 0.5s forwards;
transition: slide 0.5s forwards;
}
<div id="blackness" class="black-box"></div>
But this just makes the "blackness" div disappear instantly on page load. I want it to slide out. Clearly, I don't get how to use CSS animations.
If you are interested in seeing more of what doesn't work, read on. Otherwise, you can skip this section: it only shows my failed trials.
I've learned how to make a CSS animation expand horizontally from 0:
.wrapper {
position: relative;
overflow: hidden;
width: 500px;
height: 50px;
border: 1px solid black;
}
.slide-custom {
width: 500px;
height: 50px;
background: cyan;
position: relative;
-webkit-animation: slideIn 2s forwards;
animation: slideIn 2s forwards;
}
/* moz and webkit keyframes excluded for space */
#keyframes slideIn {
0% {
transform: scaleX(0);
}
100% {
transform: scaleX(1);
}
}
<div class="wrapper slide-custom">
<h1 class="slide-custom">
<span>MEET ROLY POLY.</span>
<!-- expands horizontally from 0 width to 100% width -->
</h1>
</div>
And I've learned to make text "slide in" from the left, though it starts at 100% width when I want it to start at 0% width:
/* CSS */
.test-slide {
animation-duration: 3s;
animation-name: testSlide;
}
#keyframes testSlide {
from {
margin-left: 0%;
width: 50%;
}
to {
margin-left: 100%;
width: 100%;
}
}
<div class="test-slide">
<h1><span>ABOUT.</span></h1>
<!-- will slide in from the left -->
</div>
There's more -- unfortunately none of it mimics the website I'm trying to copy.
Explanation
There are multiple ways to achieve what you want actually. I did not opt to animate width. The first few frames of the animation will be not as expected.
So instead, we can use clip-path. What clip-path basically does is masking. You can "crop" a div such that only a part of it is visible. We will utilise clip-path and ::before or ::after pseudo-element (either is fine) to create this animation. What we need to do:
Create the pseudo-element and position it such that it covers (is on top) the whole animatable element (position: absolute)
Set the pseudo-element's background to black
Using clip-path, mask the animatable element to display no parts of the element (this will also cause the pseudo-element to not be displayed as it is part of the element). The direction of the clipping is important. The direction here is from the right side to the left side.
Using animation and #keyframes, unmask the previously masked div. This will reveal it slowly from the left side to the right side (because initially, we masked it from the right to left; upon unmasking, the reverse direction happens)
Upon unmasking the element, the pseudo-element will be on top of the text we want to display
After a short while later, mask the pseudo-element (not the whole element) from the right direction to the left direction, again using clip-path so that the text seems revealed slowly
It works! However, I recommend reading about clip-path. Also, one really handy clip-path CSS generator I really like to use is this (if you want to clip from the right to left, you should drag the points from the right to left). I also highly recommend reading about CSS positioning (a staple in good CSS animations). You needn't be using z-index: 9999; you generally want to keep track of the z-index you use.
Solution
Here's a working solution using the described method. Try running it.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Helvetica;
}
body,
html {
width: 100%;
height: 100%;
}
#wrapper {
background: #555555;
width: 100%;
height: 100%;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#wrapper * {
margin: 5px;
}
.heading {
font-size: 3em;
padding: 10px 5px;
}
.caption {
font-size: 1em;
padding: 5px;
font-family: Courier;
}
.animatable {
position: relative;
clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
animation: .75s cubic-bezier(1,-0.01,.12,.8) 1s 1 reveal forwards;
}
.animatable::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #20262b;
padding: inherit;
animation: .75s cubic-bezier(1,-0.01,.12,.8) 1.75s 1 hideBlack forwards;
}
#keyframes reveal {
from { clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%); }
to { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
}
#keyframes hideBlack {
from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
to { clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%); }
}
<div id="wrapper">
<div class="heading animatable">Hi, I am Richard!</div>
<div class="caption animatable">I am a person.</div>
</div>
Although the simple animation you wanted can be created using merely CSS, I still suggest you read about how to make animations using JavaScript and the various libraries it has in making animations. This is because once there are many animations and transitions going on, it becomes hard to keep track of animations (especially when you want animations to start after another animation ends). A good library is anime.js (do explore more options before settling on one). Furthermore, notice how the animations only appear upon scrolling down in the website you provided? That's doable only with JS (one such method is using IntersectionObserver API provided by most browsers).
Here you have some CSS3 animations, you trigger that animation when the .entrance-animation gets the .active class.
You'll need an observer to watch when the item gets into view and, when the item is visible, you add the .active class to it.
Hope it helps!
setTimeout(() =>
{
let animate = document.querySelectorAll('.entrance-animation');
animate.forEach(item => item.classList.add('active'));
}
,1000);
.entrance-animation
{
position: relative;
color: blueviolet;
white-space: nowrap;
font-size: 24px;
width: 0;
overflow: hidden;
transition: width 0.5s ease;
}
.entrance-animation::before
{
content: '';
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 100%;
background-color: black;
z-index: 10;
transition: width 0.5s ease;
transition-delay: 0.5s;
}
.entrance-animation.active
{
width: 100%;
}
.entrance-animation.active::before
{
width: 0%;
}
<p class="entrance-animation">
Hello
</p>
<p class = "entrance-animation">
Here we are
</p>
You can use CSS3 transitions or maybe CSS3 animations to slide in an element.
For browser support: http://caniuse.com/
I made two quick examples just to show you how I mean.
CSS transition (on hover)
Demo One
Relevant Code
.wrapper:hover #slide {
transition: 1s;
left: 0;
}
In this case, Im just transitioning the position from left: -100px; to 0; with a 1s. duration. It's also possible to move the element using transform: translate();
CSS animation
Demo Two
#slide {
position: absolute;
left: -100px;
width: 100px;
height: 100px;
background: blue;
-webkit-animation: slide 0.5s forwards;
-webkit-animation-delay: 2s;
animation: slide 0.5s forwards;
animation-delay: 2s;
}
#-webkit-keyframes slide {
100% { left: 0; }
}
#keyframes slide {
100% { left: 0; }
}
Same principle as above (Demo One), but the animation starts automatically after 2s, and in this case I've set animation-fill-mode to forwards, which will persist the end state, keeping the div visible when the animation ends.
Like I said, two quick example to show you how it could be done.
EDIT: For details regarding CSS Animations and Transitions see:
Animations
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations
Transitions
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
Hope this helped.

CSS - On hover moving image littlebit left, if not hovered then back to original position

I've been trying doing it, but it doesn't work. It should move that image left 10px, but it doesn't. That div has left css inside it, I think it's because of that. I tried !important, but it didn't work.
Here's JSFiddle: https://jsfiddle.net/jwbvxhv0/1/
$(".seen").bind("webkitAnimationEnd mozAnimationEnd animationEnd", function(){
$(this).removeClass("animated")
})
$(".seen").hover(function(){
$(this).addClass("animated");
})
#-webkit-keyframes example {
0% {
left: 0px;
}
25% {
left: 10px ! important;
}
100% {
left: 0px;
}
}
.seen.animated {
position: relative;
-webkit-animation-name: example;
-webkit-animation-duration: 2s;
}
You can use translate transform for left/right movement as it does not affect any neighbour elements' position. To make the transition smooth, you need to add transition on transform property for your image.
Update:
If you have a button next to the img, which has higher z-index as you mentioned. You need to apply the same effect to a parent element that contains both - that image and that button.
.moving-left
{
height: 100px;
position: relative;
transition: transform 0.3s ease;
transform: translateX(0px);
width: 100px;
}
.moving-left:hover
{
transform: translateX(10px);
}
.moving-left button
{
left: 8px;
position: absolute;
top: 30px;
z-index: 99;
}
<div class="moving-left">
<img src="http://placehold.it/100X100" alt="" />
<button>Button here</button>
</div><!--.moving-left-->

Fire Javascript during CSS/JS animation (vanilla JS)

Edit: this is an example of what I'm trying to do: http://codepen.io/anon/pen/OVzOjW
(Note that the menu and nav don't perfectly align, as the nav transition is being controlled by the CSS, and the menu delay is being controlled by the JS.)
I'm trying to create a slideout menu that fires some JS during the slide animation.
On page load, nav is fixed hidden to the right of the viewport and menu is fixed to the top right of the viewport. nav is wider than menu. On menu click fires the slideout animation of nav. I want to add a namespace class to nav that changes the CSS properties of menu. I want to do this the moment the visible portion of the nav becomes equal in width to the width of the menu, at which point the menu will just become part of the nav for the rest of the slideout.
I need to do this with some combination of CSS3 and vanilla JS (jQuery is unavailable). I can do the nav animation with CSS or JS easy enough, but timing the CSS property changes on menu is what I can't figure out.
I've tried to write a loop that constantly evaluates the right property value of nav to see if it's >= the width of menu (using CSS to do the transition), but that seems to fire the entire loop right away.
I'm not picky over a CSS vs JS solution for the animation itself, but I'd prefer CSS as I feel it's easier to control the transition settings and it runs smoother.
Relevant code below. Any help would be greatly appreciated!
HTML:
<nav id="nav">
<a id="menu" href="#">Menu</a>
Foo
Foo
Foo
</nav>
CSS:
#nav {
position: fixed;
right: -100px;
top: 0;
width: 100px;
}
#nav.expanded-nav {
right: 0;
}
#nav.expanded-menu #menu {
position: absolute;
right: auto;
top: auto;
width: 100%;
}
#menu {
position: fixed;
right: 0;
top: 0;
width: 50px;
}
You can do that with CSS animation chaining or animation-delay or simple setTimeout of Vanilla JavaScript
Check out the below code for CSS way..
$("#go").click(function() {
$(".container").addClass("demo");
});
.container {position: relative;}
#nav, #menu {
height: 100px;
width: 100px;
position: absolute;
}
#nav {
top: 10px;
left:-100px;
background: #000;
}
#menu {
top: 150px;
left:200px;
background: #f00;
}
.demo #nav {
-webkit-animation: demo 1s, demo1 2s;
-webkit-animation-delay: 0s, 1s;
-webkit-animation-timing-function: ease-in-out;
}
.demo #menu {
-webkit-animation: demo1 2s;
-webkit-animation-delay: 1s;
-webkit-animation-timing-function: ease-in-out;
}
#-webkit-keyframes demo {
0% {
left: -100px;
}
100% {
left: 200px;
}
}
#-webkit-keyframes demo1 {
0% {
left: 200px;
}
100% {
left: 300px;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="go">Go</button>
<div class="container">
<div id="nav"></div>
<div id="menu"></div>
</div>
This was actually way easier than I initially thought. It can actually rather easily be solved by setting a min-width on menu and allowing it to "grow" to the full length of the parent `nav' when it slides out. Demo here: http://codepen.io/anon/pen/EjobEJ

Categories