Hover dependant behavior of two elements : when A or B are hovered show A - javascript

here is my CodePen demo or you can run the snippet below.
In the original script, the front face of the cube is a slider, and when I hover my 'info-box' it shows the right side of it with some description (<p> an <a>).
The expected behavior is that as long as the user stays on the description, the element keeps having the .hover class given in the $('#info-box').hover() function
All was working fine until i tested it on chrome :(...
From what I understand, it seems to fires multiples mouseOver/mouseOut events when hovering and it messes and flicker everything up.
Should I use a setTimeout ?
$('.slide-info').click(function() {
$(this).parent().toggleClass('hover');
})
.hover(function() {
$(this).parent().addClass('hover');
},
function() {
$(this).parent().removeClass('hover');
});
$('.right').hover(function() {
$(this).parent().parent().addClass('hover');
},
function() {
$(this).parent().parent().removeClass('hover');
});
h1 {
text-align: center;
}
body {
background-color: #333;
}
.Cube-container {
width: 500px;
top: 20px;
height: 150px;
perspective: 1000px;
position: relative;
margin-right: auto;
margin-left: auto;
transform-origin: 50% 50% -250px;
}
.Cube {
transition: all .5s ease-out;
transform-style: preserve-3d;
backface-visibility:hidden;
}
.front,
.right {
height: 150%;
text-align: center;
padding-top: 10px;
backface-visibility: hidden;
}
.Cube-container.hover .Cube {
transform: rotateY(90deg);
transform-origin: 50% 50% -250px;
}
.front {
transform-style: preserve-3d;
transition: all .5s ease-out;
background-color: #fc8;
position: relative;
}
.right {
background-color: #8cf;
position: absolute;
top: 0px;
left: 0px;
height: calc(100% - 10px);
/* because it takes in account the padding, i guess we can do some box-sizing: border box to avoid that...*/
width: 100%;
transform: rotateY(-90deg) translateX(-100%);
transform-origin: 0 0;
}
.ol
/* OverLay */
{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.slide-info {
width: auto;
height: auto;
background-color: rgba(0, 0, 0, 0.5);
padding: 0 15px;
cursor: pointer;
color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Cube-container">
<div class="ol Cube">
<div class="ol right">
<h2>Right side</h2>
<p>While we hover that side, parent element keeps having the .hover class, making it visible</p>
</div>
<div class="ol front">
<h2>Front</h2>
<p>Hover the info box please :)</p>
</div>
</div>
<div class="ol slide-info">
<h3>INFO</h3>
</div>
</div>http://stackoverflow.com/questions/ask#

The problem was that I used backface-visibility: hidden on parent element. (see commented line in snippet)
Crazy but that solved my problem on Chrome browser, now everything works fine.
$('.slide-info').click(function() {
$(this).parent().toggleClass('hover');
})
.hover(function() {
$(this).parent().addClass('hover');
},
function() {
$(this).parent().removeClass('hover');
});
$('.right').hover(function() {
$(this).parent().parent().addClass('hover');
},
function() {
$(this).parent().parent().removeClass('hover');
});
h1 {
text-align: center;
}
body {
background-color: #333;
}
.Cube-container {
width: 500px;
top: 20px;
height: 150px;
perspective: 1000px;
position: relative;
margin-right: auto;
margin-left: auto;
transform-origin: 50% 50% -250px;
}
.Cube {
transition: all .5s ease-out;
transform-style: preserve-3d;
/*backface-visibility:hidden; <-- Causing the problem */
}
.front,
.right {
height: 150%;
text-align: center;
padding-top: 10px;
backface-visibility: hidden;
}
.Cube-container.hover .Cube {
transform: rotateY(90deg);
transform-origin: 50% 50% -250px;
}
.front {
transform-style: preserve-3d;
transition: all .5s ease-out;
background-color: #fc8;
position: relative;
}
.right {
background-color: #8cf;
position: absolute;
top: 0px;
left: 0px;
height: calc(100% - 10px);
/* because it takes in account the padding, i guess we can do some box-sizing: border box to avoid that...*/
width: 100%;
transform: rotateY(-90deg) translateX(-100%);
transform-origin: 0 0;
}
.ol
/* OverLay */
{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.slide-info {
width: auto;
height: auto;
background-color: rgba(0, 0, 0, 0.5);
padding: 0 15px;
cursor: pointer;
color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Cube-container">
<div class="ol Cube">
<div class="ol right">
<h2>Right side</h2>
<p>While we hover that side, parent element keeps having the .hover class, making it visible</p>
</div>
<div class="ol front">
<h2>Front</h2>
<p>Hover the info box please :)</p>
</div>
</div>
<div class="ol slide-info">
<h3>INFO</h3>
</div>
</div>http://stackoverflow.com/questions/ask#

Related

Smooth Scroll CSS Property

I have the following code. Even though I have added scroll-behavior: smooth; to .containerScroll, why does it not scroll smoothly to the next section? How can I make it so it scrolls smoothly to the next section? Right now, its not scrolling smoothly to the next section even though I made use of the property. How can I fix this?
.containerScroll {
--bs-gutter-x: 1.5rem;
width: 100%;
padding-right: calc(var(--bs-gutter-x) / 2);
padding-left: calc(var(--bs-gutter-x) / 2);
margin-right: auto;
margin-left: auto;
scroll-behavior: smooth;
}
.first-scroll {
left: calc(50% - -2em) !important;
width: 1.5em;
height: 1.5em;
background-color: transparent;
z-index: 80;
bottom: 25px;
border-width: 0 0.18em 0.18em 0;
border-style: solid;
border-color: black;
position: absolute;
animation: scrolldown1 1.2s ease-in-out infinite 0.15s;
}
.second-scroll {
left: calc(50% - -2em) !important;
width: 1.5em;
height: 1.5em;
background-color: transparent;
z-index: 80;
bottom: 40px;
position: absolute;
border-width: 0 0.18em 0.18em 0;
border-style: solid;
border-color: black;
animation: scrolldown1 1.2s ease-in-out infinite;
}
#keyframes scrolldown1 {
0% {
transform: translateY(20%) rotate(45deg);
opacity: 0.4;
}
50% {
transform: translateY(0%) rotate(45deg);
opacity: 0.2;
}
100% {
transform: translateY(20%) rotate(45deg);
opacity: 0.4;
}
}
#media (min-width:320px) and (max-width:480px) {
.containerScroll {
display: none;
}
}
.long-container {
height: 600px;
background: yellow;
}
#about {
height: 600px;
background: green;
}
<a href="#about">
<div class="containerScroll">
<div class="first-scroll"></div>
<div class="second-scroll"></div>
</div>
</a>
<div id="" class="long-container">
long old container
</div>
<div id="about">
scroll to me
</div>
Add to root html tag:
html {
scroll-behavior: smooth;
}
The smooth scroll behavior should be added to the element that is being scrolled, not to the element that triggers the scroll.
CSS property scroll-behavior: smooth with html tag should wrap the #about div tag. And need CSS property overflow-y: scroll and height prop also.
Idk for some reason this site's code snippet shows error, So if you want to see my explanation in code, visit below codepen.
https://codepen.io/junzero741/pen/zYEWWEK
function scrollf() {//js function
let e = document.getElementById("about");//Your id to scroll
e.scrollIntoView({
block: 'start',
behavior: 'smooth',
inline: 'start'
});
}
.containerScroll {
/*--bs-gutter-x: 1.5rem;
width: 100%;
padding-right: calc(var(--bs-gutter-x) / 2);
padding-left: calc(var(--bs-gutter-x) / 2);
margin-right: auto;
margin-left: auto;
scroll-behavior: smooth; //removed these unwanted lines,u may un comment*/
}
.first-scroll {
left: calc(50% - -2em) !important;
width: 1.5em;
height: 1.5em;
background-color: transparent;
z-index: 80;
bottom: 25px;
border-width: 0 0.18em 0.18em 0;
border-style: solid;
border-color: black;
position: absolute;
animation: scrolldown1 1.2s ease-in-out infinite 0.15s;
cursor: pointer; /*added this for cursor click-like effect*/
}
.second-scroll {
left: calc(50% - -2em) !important;
width: 1.5em;
height: 1.5em;
background-color: transparent;
z-index: 80;
bottom: 40px;
position: absolute;
border-width: 0 0.18em 0.18em 0;
border-style: solid;
border-color: black;
animation: scrolldown1 1.2s ease-in-out infinite;
cursor: pointer; /*added this for cursor click-like effect*/
}
#keyframes scrolldown1 {
0% {
transform: translateY(20%) rotate(45deg);
opacity: 0.4;
}
50% {
transform: translateY(0%) rotate(45deg);
opacity: 0.2;
}
100% {
transform: translateY(20%) rotate(45deg);
opacity: 0.4;
}
}
#media (min-width:320px) and (max-width:480px) {
.containerScroll {
display: none;
}
}
.long-container {
height: 600px;
background: yellow;
}
#about {
height: 600px;
background: green;
}
<div class="containerScroll" onclick="scrollf()"><!--use div with js-->
<div class="first-scroll"></div>
<div class="second-scroll"></div>
</div>
<div id="" class="long-container">
long old container
</div>
<div id="about">
scroll to me
</div>
ReadMe: Nowadays we are not understand what the anchor a tag does,even though it opens a div in the same page
what it actually does is reload the page and show the div.//yes this is false it may not reload the page ,its only my opinion
so in the above code we us pure js to scroll ,
we call this function when containerScroll is clicked,
since its js we dont get a pointable-mouse when we hover over those arrows, so we use cursor: pointer; in css for first-scroll&second-scroll.
This one below is another approach that I got from https://stackoverflow.com/a/70553396/14862885
It preserves your animation, fixed glitches & bugs but still not recommended, unless You need to avoid js
.containerScroll {
--bs-gutter-x: 1.5rem;
width: 100%;
padding-right: calc(var(--bs-gutter-x) / 2);
padding-left: calc(var(--bs-gutter-x) / 2);
margin-right: auto;
margin-left: auto;
scroll-behavior: smooth;
}
.first-scroll {
left: calc(50% - -2em) !important;
width: 1.5em;
height: 1.5em;
background-color: transparent;
z-index: 80;
bottom: 25px;
border-width: 0 0.18em 0.18em 0;
border-style: solid;
border-color: black;
position: sticky; /*makes scroll arrow to stick to container*/
animation: scrolldown1 1.2s ease-in-out infinite 0.15s;
}
.second-scroll {
left: calc(50% - -2em) !important;
width: 1.5em;
height: 1.5em;
background-color: transparent;
z-index: 80;
bottom: 40px;
position: sticky;/*makes scroll arrow to stick to container*/
border-width: 0 0.18em 0.18em 0;
border-style: solid;
border-color: black;
animation: scrolldown1 1.2s ease-in-out infinite;
}
#keyframes scrolldown1 {
0% {
transform: translateY(20%) rotate(45deg);
opacity: 0.4;
}
50% {
transform: translateY(0%) rotate(45deg);
opacity: 0.2;
}
100% {
transform: translateY(20%) rotate(45deg);
opacity: 0.4;
}
}
#media (min-width:320px) and (max-width:480px) {
.containerScroll {
display: none;
}
}
.long-container {
height: 600px;
background: yellow;
}
#about {
height: 600px;
background: green;
}
.smooth-container {
width: 100%;
height: 600px;
overflow: scroll;
scroll-behavior: smooth;
padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
box-sizing: content-box;
}
.parent {
width: 100%;
height: 600px;
overflow: hidden;
}
<!-- div tag with class `smooth-container` is wrapping the `long-container` and `about`. and with CSS, `overflow-y: scroll` and `height` value. -->
<div class="parent">
<div class="smooth-container">
<div id="" class="long-container">
long old container
<a href="#about"><!-- added anchor tag inside long-container-->
<div class="containerScroll">
<div class="first-scroll"></div>
<div class="second-scroll"></div>
</div>
</a>
</div>
<div id="about">
scroll to me
</div>
</div>
</div>

how do I fix the overlay "overflow: hidden;" instead of the entire body

So I have this hamburger menu on the right side of the navbar which when clicked should pop open overlay and be full screen black and un-scrollable(just the overlay) but right now when it's clicked is scrollable and not full screen black, I don't know what went wrong, any help would be really appreciated, thanx!
$(function() {
$(".menu-link").click(function(e) {
e.preventDefault();
$(".menu-overlay").toggleClass("open");
$(".menu").toggleClass("open");
});
});
.nav {
display: flex;
justify-content: space-between;
padding: 0 5%;
}
#brandname {
color: black;
font-weight: bold;
font-family: Circular Std Black;
line-height: 60px;
font-size:20px;
margin-top: 45px;
}
.menu {
position: absolute;
margin-top: 50px;
right: 5%;
height: 46px;
width: 46px;
}
.menu-link {
width: 100%;
height: 100%;
position: absolute;
z-index: 1002;
}
.menu-icon {
position: absolute;
width: 20px;
height: 15px;
margin: auto;
left: 0;
top: 0;
right: 0;
bottom: 1px;
}
/* ------------- */
.menu-line {
background-color: white;
height: 3px;
width: 100%;
border-radius: 2px;
position: absolute;
left: 0;
transition: all 0.25s ease-in-out;
}
.menu-line-2 {
top: 0;
bottom: 0;
margin: auto;
}
.menu-line-3 {
bottom: 0;
}
.menu.open .menu-line-1 {
transform: translateY(7px) translateY(-50%) rotate(-45deg);
}
.menu.open .menu-line-2 {
opacity: 0;
}
.menu.open .menu-line-3 {
transform: translateY(-7px) translateY(50%) rotate(45deg);
}
/* ------------- */
.menu-circle {
background-color: #E095F0;
width: 100%;
height: 100%;
position: absolute;
border-radius: 50%;
transform: scale(1);
z-index: 1000;
transition: transform 0.3s ease-in-out;
}
.menu:hover .menu-circle {
transform: scale(1.5);
}
.menu.open .menu-circle {
transform: scale(60);
}
/* ------------- */
.menu-overlay {
background-color: black;
color: white;
height: 100%;
width: 100%;
position: fixed;
transition: opacity 0.2s ease-in-out;
z-index: 1001;
opacity: 0;
visibility: hidden;
display: flex;
flex-direction: column;
}
.menu-overlay.open {
opacity: 1;
visibility: visible;
}
<nav class="nav">
<div id="brandname">Test</div>
<div class="menu">
<span class="menu-circle"></span>
<a href="#" class="menu-link">
<span class="menu-icon">
<span class="menu-line menu-line-1"></span>
<span class="menu-line menu-line-2"></span>
<span class="menu-line menu-line-3"></span>
</span>
</a>
</div>
<div class="menu-overlay">
Home
About
</div>
</nav>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
See adjustments to the CSS inline below, but here are the major points:
The overlay should not be using Flexbox. If you want the layout within the overlay to use Flexbox, then set that up on the elements it contains.
The element itself should not be in the HTML as a child of the main content if you are going to size it using percents, because then it will only be as big as the parent. Instead, use vh and vw (Viewport Height and Viewport Width) units.
Set the top and left CSS properties to position the overlay at the top-left of the screen.
Don't use visibility to hide the overlay, use display:none and then display:block to bring it back.
$(function() {
$(".menu-link").click(function(e) {
e.preventDefault();
$(".menu-overlay").toggleClass("open");
$(".menu").toggleClass("open");
});
});
/* ------------- */
.menu-overlay {
transition: opacity 0.2s ease-in-out;
opacity:0;
display:hidden;
}
.menu-overlay.open {
position: fixed;
top:0;
left:0;
height: 100vh;
width: 100vw;
opacity:1;
display:block;
z-index: 1001;
background-color: black;
color: white;
}
.nav {
display: flex;
justify-content: space-between;
padding: 0 5%;
}
#brandname {
color: black;
font-weight: bold;
font-family: Circular Std Black;
line-height: 60px;
font-size:20px;
margin-top: 45px;
}
.menu {
position: absolute;
margin-top: 50px;
right: 5%;
height: 46px;
width: 46px;
}
.menu-link {
width: 100%;
height: 100%;
position: absolute;
z-index: 1002;
}
.menu-icon {
position: absolute;
width: 20px;
height: 15px;
margin: auto;
left: 0;
top: 0;
right: 0;
bottom: 1px;
}
/* ------------- */
.menu-line {
background-color: white;
height: 3px;
width: 100%;
border-radius: 2px;
position: absolute;
left: 0;
transition: all 0.25s ease-in-out;
}
.menu-line-2 {
top: 0;
bottom: 0;
margin: auto;
}
.menu-line-3 {
bottom: 0;
}
.menu.open .menu-line-1 {
transform: translateY(7px) translateY(-50%) rotate(-45deg);
}
.menu.open .menu-line-2 {
opacity: 0;
}
.menu.open .menu-line-3 {
transform: translateY(-7px) translateY(50%) rotate(45deg);
}
/* ------------- */
.menu-circle {
background-color: #E095F0;
width: 100%;
height: 100%;
position: absolute;
border-radius: 50%;
transform: scale(1);
z-index: 1000;
transition: transform 0.3s ease-in-out;
}
.menu:hover .menu-circle {
transform: scale(1.5);
}
.menu.open .menu-circle {
transform: scale(60);
}
<div class="menu-overlay">
Home
About
</div>
<nav class="nav">
<div id="brandname">Test</div>
<div class="menu">
<span class="menu-circle"></span>
<a href="#" class="menu-link">
<span class="menu-icon">
<span class="menu-line menu-line-1"></span>
<span class="menu-line menu-line-2"></span>
<span class="menu-line menu-line-3"></span>
</span>
</a>
</div>
</nav>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Thanks to #Scott Marcus for fixing the layout but the overflow was still not working so I added a toggle-class in js, It works just fine but lemme know otherwise if it contains any DOM errors. Cheers!
$('.menu-link').click(function() {
$('body').toggleClass('no-scroll');
});
.no-scroll{
overflow: hidden;
}

How would I mask an element with an animated overlay?

I'm trying to do some page transitions for a project I'm working on, I have an animated overlay that comes onto the screen when the user is navigating the site using Barba but I'm having an issue.
I want a logo centered on the page that rolls in with the overlay but I need it to be positioned separately from the overlay since any transform on the overlay would affect the logo as well. (I want the logo to mask with the overlay element)
What I've tried :
Switching around the Element hierarchy/Z-index (I'm sure the problem lies somewhere in here)
Trying different transforms
Messing with Max Width (Had some success but I need the transform origin property)
Example -
let transitionOpen = false;
$('.transition-cta').on("click", function() {
if (transitionOpen === false) {
$('.transition-background').css("transform", "scaleX(1)");
$(this).css("color", "white");
transitionOpen = true;
} else {
$('.transition-background').css("transform", "scaleX(0)");
$(this).css("color", "black");
transitionOpen = false;
}
});
body {
background-color: lightblue;
}
.someContent {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.transition-wrapper {
overflow: hidden;
}
.transition-background {
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
transform-origin: left;
transition: 0.7s ease-in-out;
background-color: #1f1f1f;
transform: scaleX(0);
z-index: 2;
}
.transition-center {
background-image: url('https://i.imgur.com/6um9G9h.png');
z-index: 2;
width: 150px;
height: 150px;
position: absolute;
background-repeat: no-repeat;
background-size: cover;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.transition-cta {
text-decoration: underline;
cursor: pointer;
z-index: 3;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="transition-wrapper">
<div class="transition-background"></div>
<!-- I want to clip this with the transition background -->
<div title="I only want this to show with the transition overlay" class="transition-center"></div>
</div>
<div class="transition-cta">Trigger Transition</div>
<div class="someContent">
<h1>Some Content</h1>
</div>
(The globe should roll in with the overlay)
This feels like an extremely simple problem but I'm really struggling to solve it. I can't tell if I'm burned out or this is actually as complicated as my brain is making it.
Thanks!
Use a clip-path animation instead and you can simplify your code by having the logo as background of the transition-wrapper
let transitionOpen = false;
$('.transition-cta').on("click", function() {
$('.transition-wrapper').toggleClass('show');
if (transitionOpen === false) {
$(this).css("color", "white");
transitionOpen = true;
} else {
$(this).css("color", "black");
transitionOpen = false;
}
});
body {
background-color: lightblue;
}
.someContent {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.transition-wrapper {
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
transition: 0.7s ease-in-out;
background: url('https://i.imgur.com/6um9G9h.png') center/150px 150px no-repeat;
background-color: #1f1f1f;
clip-path: polygon(0 0, 0% 0, 0% 100%, 0 100%);
z-index: 3;
}
.transition-wrapper.show {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
.transition-cta {
text-decoration: underline;
cursor: pointer;
z-index: 3;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="transition-wrapper">
</div>
<div class="transition-cta">Trigger Transition</div>
<div class="someContent">
<h1>Some Content</h1>
</div>
I would do something like:
$('.transition-cta').on("click", function() {
$('.transition-wrapper').toggleClass('opened');
$('.transition-content').animate({ width: 'toggle' }, 800);
});
body {
background: lightblue;
}
.content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.transition-content {
background-color: #1f1f1f;
display: none;
overflow: hidden;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
width: 100%;
}
.transition-cta {
position: relative;
text-decoration: underline;
z-index: 999;
}
.transition-wrapper.opened .transition-cta {
color: #fff;
}
.transition-content__inner {
width: 100vw;
}
.transition-content__inner img {
width: 150px;
height: 150px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="transition-wrapper">
<div class="transition-cta">Trigger Transition</div>
<div class="content">
<h1>Some Content</h1>
</div>
<div class="transition-content">
<div class="transition-content__inner">
<img src="https://i.imgur.com/6um9G9h.png"/>
</div>
</div>
</div>

hide nav based on scroll removing adding classes

I found a nav layout I would like to use but I seem to have run into 2 problems.
problem #1 the transitions in the css do not seem to be transitioning smooth when scrolling up or down.
problem #2 if the scroll position is not zero I do not want mainnav to shrink and i want the top nav to show or hide when i scroll up or down.. thats hard to word so what I am trying to accomplish exactly is the following
https://www.battlefield.com/games/battlefield-4/classes
now when you scroll down it hides the top nav but if you scroll just a little each way it will show or hide thats what I am trying to do.. but I dont want the 2nd nav to scale down unless the top is 0
$(window).scroll(function() {
if ($(this).scrollTop() > 0) {
$('.netnav').addClass('hide-nav');
$('.netnav').removeClass('show-nav');
$('.mainnav').addClass('scrolled');
}
else {
$('.netnav').addClass('show-nav');
$('.netnav').removeClass('hide-nav');
$('.mainnav').removeClass('scrolled');
}
});
body {
margin: 0px;
}
.hwrap {
display: block;
position: fixed;
width: 100%;
}
.netnav {
position: fixed;
height: 40px;
width: 100%;
margin: 0;
padding: 0;
background-color: blue;
z-index: 1;
}
.netnav.show-nav {
top: 0;
transition-duration: .4s;
}
.netnav.hide-nav {
transform: translate3d(0, -40px, 0);
transition-duration: .4s;
}
.mainnav {
position: fixed;
height: 68px;
z-index: 3;
background: blue;
}
.mainnav {
border-radius: 4px;
left: auto;
margin: 0 auto;
top: 50px;
position: relative;
transform: translateY(15px);
transition: transform .3s, width .3s;
width: calc(100% - 60px);
}
.mainnav.scrolled {
top: 0;
height: 60px;
border-radius: 0;
transform: translateY(0);
width: 100%;
transition: transform .3s, width .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="hwrap">
<div class="netnav">net nav</div>
<div class="mainnav">main nav</div>
</header>
<div style="height: 100vh; display: block; background-color: gold">about</div>
<div style="height: 100vh; display: block; background-color: green">about</div>
Demo
http://jsfiddle.net/gos4hwp9/52/
Explanation
Added transition: all ease-in-out .4s for smooth transitions of all properties
If scrollTop > 0 added margin: 0px and border-radius: 0px to bottom (primary) nav, Else made margin and border-radius same as initial state
If scrollDir == "down" added translateY(-50px) to header, Else removed translateY
Moving the whole header will move both navs which is nice as compared to moving them individually
I've slightly changed your transitions and added transitions to the classes which you toggle.
body {
margin: 0px;
}
.hwrap {
display: block;
position: fixed;
width: 100%;
}
.netnav {
position: fixed;
height: 40px;
width: 100%;
margin: 0;
padding: 0;
background-color: blue;
z-index: 1;
transition: .3s all;
}
.netnav.show-nav {
top: 0;
transition: .3s all;
}
.netnav.hide-nav {
transform: translate3d(0, -40px, 0);
transition: .3s all;
}
.mainnav {
position: fixed;
height: 68px;
z-index: 3;
background: blue;
}
.mainnav {
border-radius: 4px;
left: auto;
margin: 0 auto;
top: 50px;
position: relative;
transform: translateY(15px);
transition: .3s all;
width: calc(100% - 60px);
}
.mainnav.scrolled {
top: 0;
height: 60px;
border-radius: 0;
transform: translateY(0);
width: 100%;
transition: .3s all;
}
I followed the link you provided and edit the JavaScript and CSS.
Fixed the transitions in the CSS that does not seem smooth in transitioning when scrolling up or down using JavaScript.
You may visit this pen that I edited based on your snippet, and play around with it.
$(window).scroll(function(){
if ($(this).scrollTop() > 15) {
$('.netnav').addClass('hide-nav');
$('.netnav').removeClass('show-nav');
$('.mainnav').addClass('RemoveTop');
}
else {
$('.netnav').addClass('show-nav');
$('.netnav').removeClass('hide-nav');
$('.mainnav').removeClass('RemoveTop');
$('.mainnav').removeClass('scrolled');
}
});
$(window).scroll(function(){
if ($(this).scrollTop() > 50) {
$('.mainnav').addClass('scrolled');
}
else {
$('.netnav').removeClass('scrolled');
}
});
body {
margin: 0px;
}
.hwrap{
display:block;
position: fixed;
width: 100%;
}
.netnav{
position: fixed;
height: 40px;
width: 100%;
margin: 0;
padding: 0;
background-color: blue;
transition: all .3s;
z-index: 1;
}
.netnav.show-nav {
top: 0;
transition-duration: .4s;
}
.netnav.hide-nav {
transform: translate3d(0,-40px,0);
transition-duration: .4s;
}
.mainnav{
position: fixed;
height: 68px;
z-index: 3;
background: blue;
}
.mainnav {
border-radius: 4px;
left: auto;
margin: 0 auto;
top: 50px;
position: relative;
transform: translateY(15px);
transition: all .3s,width .3s;
width: calc(100% - 60px);
}
.mainnav.RemoveTop {
top: 0px;
}
.mainnav.scrolled {
height: 60px;
border-radius: 0;
transform: translateY(0);
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="hwrap">
<div class="netnav">net nav</div>
<div class="mainnav">main nav</div>
</header>
<div style="height: 100vh; display: block; background-color: gold">about</div>
<div style="height: 100vh; display: block; background-color: green">about</div>

How can I reverse this animation smoothly on mouseout?

I have this flipcard I put together, and when you hover over it, it flips 180 degrees on it's x-axis, and then expands. When I mouse-off of the element, I would like for this element to flip back the opposite way smoothly, the way it came in. Instead of the sudden change back when you mouseout like it is right now.
Also, it should be noted that I would like the animation to use animation: forwards for as long as the mouse is hovering over the element. (ie. so long as the user is hovering over the element, it should remain flipped, and enlarged.)
Is there any way to do this using just CSS? Or will I need Javascript? If so, I'd like to do this with pure Vanilla JS.
I have been poking around for solutions on Stack Overflow, and can't seem to find a definitive answer, or am not typing in the correct question.
html, body {
background: #f2edea;
height: 100%;
width: 100%;
}
.container {
width: 250px;
height: 320px;
margin: auto;
position: relative;
top: 35%;
}
img {
width: 100%;
max-height: 100%;
}
.flipcard {
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
}
#keyframes grow {
from {
transform: rotateY(0) scale(1);
}
to {
transform: rotateY(180deg) scale(2);
}
}
.flipcard:hover {
animation: grow 1s forwards;
}
.front-side {
height: 100%;
width: 100%;
position: relative;
backface-visibility: hidden;
}
.back-side {
width: 100%;
height: 100%;
transform: rotateY(180deg);
position: absolute;
top: 0;
border-radius: 3px;
}
<div class='container'>
<div class='flipcard'>
<div class='front-side'>
<img src='https://pre00.deviantart.net/4121/th/pre/i/2018/059/6/7/brigitte_by_raikoart-dc4kzas.png'>
</div>
<div class='back-side'>
<img src="https://img00.deviantart.net/e0ec/i/2017/297/8/c/mercy_by_raikoart-dbrm54b.png">
</div>
</div>
</div>
You'd better use transition between normal and hover states.
Note that you have to track hover on .container to avoid jumping and flickering.
html, body {
background: #f2edea;
height: 100%;
width: 100%;
}
.container {
width: 250px;
height: 320px;
margin: auto;
position: relative;
}
img {
width: 100%;
max-height: 100%;
}
.flipcard {
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
transition: all .5s ease-in-out;
}
.container:hover .flipcard {
transform: rotateY(180deg) scale(2);
}
.front-side {
height: 100%;
width: 100%;
position: relative;
backface-visibility: hidden;
}
.back-side {
width: 100%;
height: 100%;
transform: rotateY(180deg);
position: absolute;
top: 0;
border-radius: 3px;
}
<div class='container'>
<div class='flipcard'>
<div class='front-side'>
<img src='https://pre00.deviantart.net/4121/th/pre/i/2018/059/6/7/brigitte_by_raikoart-dc4kzas.png'>
</div>
<div class='back-side'>
<img src="https://img00.deviantart.net/e0ec/i/2017/297/8/c/mercy_by_raikoart-dbrm54b.png">
</div>
</div>
</div>
The reason this happens is because on the default non-hover state there's no animation state to return to. You have two options for this.
Don't use animations and just transition the effect on hover.
This way on out the properties will return to their non-hover state with transition.
.flipcard {
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
transform: rotateY(0) scale(1);
transition: all 0.3s ease;
}
.flipcard:hover {
transform: rotateY(180deg) scale(2);
}
https://jsfiddle.net/255mnwxr/5/
To have a out animation property.
This is least desired because on load the animation will play once for it to animate then it acts naturally afterwards.
.flipcard {
animation: return 1s forwards;
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
transition: all 0.3s ease;
}
#keyframes grow {
from {
transform: rotateY(0) scale(1);
}
to {
transform: rotateY(180deg) scale(2);
}
}
#keyframes return {
from {
transform: rotateY(180deg) scale(2);
}
to {
transform: rotateY(0) scale(1);
}
}
https://jsfiddle.net/255mnwxr/2/
You need to add #keyframes on the mouse in and out hover.
html, body {
background: #f2edea;
height: 100%;
width: 100%;
}
.container {
width: 250px;
height: 320px;
margin: auto;
position: relative;
top: 35%;
}
img {
width: 100%;
max-height: 100%;
}
.flipcard {
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
}
#-webkit-keyframes in {
from { -webkit-transform: rotate(0deg); }
to {-webkit-transform: rotateY(180deg) scale(2);}
}
#-webkit-keyframes out {
0% { -webkit-transform: rotateY(180deg) scale(2); }
100% { -webkit-transform: rotate(0deg); }
}
.flipcard:hover {
animation: out 1s forwards;
}
.flipcard {
animation: in 1s forwards;
}
.front-side {
height: 100%;
width: 100%;
position: relative;
backface-visibility: hidden;
}
.back-side {
width: 100%;
height: 100%;
transform: rotateY(180deg);
position: absolute;
top: 0;
border-radius: 3px;
}
<div class='container'>
<div class='flipcard'>
<div class='front-side'>
<img src='https://pre00.deviantart.net/4121/th/pre/i/2018/059/6/7/brigitte_by_raikoart-dc4kzas.png'>
</div>
<div class='back-side'>
<img src="https://img00.deviantart.net/e0ec/i/2017/297/8/c/mercy_by_raikoart-dbrm54b.png">
</div>
</div>
</div>
You don't need a keyframe animation for this, you could just use basic CSS transitions for this, they'll rewind on mouseout with the transition property:
.flipcard {
transform: rotateY(0) scale(1);
transition: 1s all ease-out;
}
.flipcard:hover {
transform: rotateY(180deg) scale(2);
}
However, if you do want to use animations (for more complex interactions) I have a snippet for that at the bottom, just know this can be a little harder to maintain, and just reversing it on the default element won't work.
Also note that you may want a mouse-container that doesn't rotate but controls the hover state otherwise the mouse may fall off part way through the transition, like:
.flipcard-container:hover .flipcard {
transform: rotateY(180deg) scale(2);
}
html, body {
background: #f2edea;
height: 100%;
width: 100%;
}
.container {
width: 250px;
height: 320px;
margin: auto;
position: relative;
top: 35%;
}
img {
width: 100%;
max-height: 100%;
}
.flipcard {
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
transform: rotateY(0) scale(1);
transition: 1s all ease-out;
}
.flipcard:hover {
transform: rotateY(180deg) scale(2);
}
.front-side {
height: 100%;
width: 100%;
position: relative;
backface-visibility: hidden;
}
.back-side {
width: 100%;
height: 100%;
transform: rotateY(180deg);
position: absolute;
top: 0;
border-radius: 3px;
}
<div class='container'>
<div class='flipcard'>
<div class='front-side'>
<img src='https://pre00.deviantart.net/4121/th/pre/i/2018/059/6/7/brigitte_by_raikoart-dc4kzas.png'>
</div>
<div class='back-side'>
<img src="https://img00.deviantart.net/e0ec/i/2017/297/8/c/mercy_by_raikoart-dbrm54b.png">
</div>
</div>
</div>
html, body {
background: #f2edea;
height: 100%;
width: 100%;
}
.container {
width: 250px;
height: 320px;
margin: auto;
position: relative;
top: 35%;
}
img {
width: 100%;
max-height: 100%;
}
#keyframes grow {
from {
transform: rotateY(0) scale(1);
}
to {
transform: rotateY(180deg) scale(2);
}
}
#keyframes shrink {
from {
transform: rotateY(180deg) scale(2);
}
to {
transform: rotateY(0) scale(1);
}
}
.flipcard {
height: 100%;
width: 100%;
margin: auto;
top: 20%;
position: relative;
box-shadow: 5px 5px 20px #94989e;
border: 3px solid #b8b8ba;
border-radius: 5px;
background: pink;
transform-style: preserve-3d;
transform: rotateY(0) scale(1);
animation: shrink 1s forwards;
}
.flipcard:hover {
animation: grow 1s forwards;
}
.front-side {
height: 100%;
width: 100%;
position: relative;
backface-visibility: hidden;
}
.back-side {
width: 100%;
height: 100%;
transform: rotateY(180deg);
position: absolute;
top: 0;
border-radius: 3px;
}
<div class='container'>
<div class='flipcard'>
<div class='front-side'>
<img src='https://pre00.deviantart.net/4121/th/pre/i/2018/059/6/7/brigitte_by_raikoart-dc4kzas.png'>
</div>
<div class='back-side'>
<img src="https://img00.deviantart.net/e0ec/i/2017/297/8/c/mercy_by_raikoart-dbrm54b.png">
</div>
</div>
</div>

Categories