Reputation: 15
I've essentially made 3 sections that animate on hover. It all works wonderfully when I'm hovering over at a rather leasurely pace, but if I move the mouse quickly, the section in the middle seems to have a gap on the right side as it quickly tries to match the width that's been set for it.
I'm guessing only the right side is affected because it is positioned absolute and the left value has already been set, whereas the right side can essentially do what it needs to to match it's final state.
I've tried a bunch of different things to get it to work(changing values, parent container flex, positioning, etc), but with no luck. I'm not really sure how I can remedy this situation and I wanted to see what clever solutions I've missed.
Here's all the code, although I would focus more on the section commented out as "mid". If the snippet won't run, I've included it here on codepen
const left = document.querySelector(".left");
const mid = document.querySelector(".mid");
const right = document.querySelector(".right");
const container = document.querySelector(".container");
// ===== Hover States ======
/*
* Left Section
*/
//On Hover
left.addEventListener("mouseenter", () => {
container.classList.add("hover-left");
mid.classList.add("push-right");
});
//On Leave
left.addEventListener("mouseleave", () => {
container.classList.remove("hover-left");
mid.classList.remove("push-right");
});
/*
* Mid Section
*/
//On Hover
mid.addEventListener("mouseenter", () => {
container.classList.add("hover-mid");
});
//On Leave
mid.addEventListener("mouseleave", () => {
container.classList.remove("hover-mid");
});
/*
* Right Section
*/
//On Hover
right.addEventListener("mouseenter", () => {
container.classList.add("hover-right");
mid.classList.add("push-left");
});
//On Leave
right.addEventListener("mouseleave", () => {
container.classList.remove("hover-right");
mid.classList.remove("push-left");
});
:root {
--container-bg-color: #333;
--left-bg-color: rgba(223, 39, 39, 0.7);
--left-btn-hover-color: rgba(161, 11, 11, 0.3);
--mid-bg-color: rgba(70, 223, 39, 0.7);
--mid-btn-hover-color: rgba(24, 92, 10, 0.3);
--right-bg-color: rgba(39, 186, 223, 0.7);
--right-btn-hover-color: rgba(10, 18, 92, 0.3);
--hover-width: 50%;
--other-width: 25%;
--speed: 1000ms;
}
html,
body {
padding: 0;
margin: 0;
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
width: 100%;
height: 100%;
overflow-x: hidden;
}
h2 {
font-size: 4rem;
color: #fff;
position: absolute;
left: 50%;
top: 30%;
transform: translateX(-50%);
white-space: nowrap;
}
.btn {
display: block;
position: absolute;
left: 50%;
top: 50%;
height: 2.5rem;
padding-top: 1.3rem;
width: 15rem;
text-align: center;
color: #fff;
border: #fff solid 0.2rem;
font-size: 1rem;
font-weight: bold;
text-transform: uppercase;
text-decoration: none;
transform: translateX(-50%);
}
.split.left .btn:hover {
background-color: var(--left-btn-hover-color);
border-color: var(--left-btn-hover-color);
}
.split.mid .btn:hover {
background-color: var(--mid-btn-hover-color);
border-color: var(--mid-btn-hover-color);
}
.split.right .btn:hover {
background-color: var(--right-btn-hover-color);
border-color: var(--right-btn-hover-color);
}
.container {
position: absolute;
width: 100%;
height: 100%;
background: var(--container-bg-color);
}
.split {
position: relative;
width: 33.3333333333333333333%;
height: 100%;
overflow: hidden;
}
.split.left {
position: absolute;
left: 0;
}
.split.left:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--left-bg-color);
}
.split.mid {
position: absolute;
left: 33.3333333333333333333%;
}
.split.mid:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--mid-bg-color);
}
.split.right {
position: absolute;
right: 0;
}
.split.right:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--right-bg-color);
}
.split.left,
.split.mid,
.split.right,
.split.left:before,
.split.mid:before,
.split.right:before {
transition: var(--speed) all ease-in-out;
}
/*
left
*/
.hover-left .left {
width: var(--hover-width);
}
.hover-left .mid {
width: var(--other-width);
}
.hover-left .mid:before {
z-index: 2;
}
.hover-left .right {
width: var(--other-width);
}
.hover-left .right:before {
z-index: 2;
}
/*
mid
*/
.hover-mid .mid {
left: 25%;
width: var(--hover-width);
}
.hover-mid .left {
width: var(--other-width);
}
.hover-mid .left:before {
z-index: 2;
}
.hover-mid .right {
width: var(--other-width);
}
.hover-mid .right:before {
z-index: 2;
}
/*
Right
*/
.hover-right .right {
width: var(--hover-width);
}
.hover-right .left {
width: var(--other-width);
}
.hover-right .left:before {
z-index: 2;
}
.hover-right .mid {
width: var(--other-width);
}
.hover-right .mid:before {
z-index: 2;
}
/* Push Mid */
.split.push-right {
left: 50%;
}
.split.push-left {
left: 25%;
}
@media screen and (max-height: 700px){
h2{
top: 10%;
}
.btn{
top: 60%;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Test</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="container">
<div class="split left">
<h2>Option1</h2>
<a href="#" class="btn btn-left">Learn More</a>
</div>
<div class="split mid">
<h2>Option 2</h2>
<a href="#" class="btn btn-mid">Learn More</a>
</div>
<div class="split right">
<h2>Option 3</h2>
<a href="#" class="btn btn-right">Learn More</a>
</div>
</div>
<script src="js/app.js"></script>
</body>
</html>
Upvotes: 0
Views: 63
Reputation: 1489
I would ditch the javascript and do this with css - flexbox. You may have ran into trouble trying it the first time because of absolutely positioned elements.
To set this up I removed all your absolutely positioned classes, set the parent container to display flex.
flex shorthand (flex-grow | flex-shrink | flex-basic)\ More Information: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Then you can tell your slides flex: 1 0 var(--other-width); Even though your other width is only 25% they will fill empty space automatically because the 1 tells them they can grow.
Then you can create a .slides:hover class with flex:0 0 var(--hover-width); This will expand the hovered slide to 50%. A 1 to grow in this class isn't necessary if you never want it to be over the width of your --hover-width.
Hope this helps!
:root {
--container-bg-color: #333;
--left-bg-color: rgba(223, 39, 39, 0.7);
--left-btn-hover-color: rgba(161, 11, 11, 0.3);
--mid-bg-color: rgba(70, 223, 39, 0.7);
--mid-btn-hover-color: rgba(24, 92, 10, 0.3);
--right-bg-color: rgba(39, 186, 223, 0.7);
--right-btn-hover-color: rgba(10, 18, 92, 0.3);
--hover-width: 50%;
--other-width: 25%;
--speed: 1000ms;
}
html,
body {
padding: 0;
margin: 0;
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
width: 100%;
height: 100%;
overflow-x: hidden;
}
h2 {
font-size: 4rem;
color: #fff;
position: absolute;
left: 50%;
top: 30%;
transform: translateX(-50%);
white-space: nowrap;
}
.btn {
display: block;
position: absolute;
left: 50%;
top: 50%;
height: 2.5rem;
padding-top: 1.3rem;
width: 15rem;
text-align: center;
color: #fff;
border: #fff solid 0.2rem;
font-size: 1rem;
font-weight: bold;
text-transform: uppercase;
text-decoration: none;
transform: translateX(-50%);
}
.split.left .btn:hover {
background-color: var(--left-btn-hover-color);
border-color: var(--left-btn-hover-color);
}
.split.mid .btn:hover {
background-color: var(--mid-btn-hover-color);
border-color: var(--mid-btn-hover-color);
}
.split.right .btn:hover {
background-color: var(--right-btn-hover-color);
border-color: var(--right-btn-hover-color);
}
.container {
display: flex;
width: 100%;
height: 100%;
background: var(--container-bg-color);
}
.split {
position: relative;
flex:1 0 var(--other-width);
height: 100%;
overflow: hidden;
}
.split:hover {
flex: 1 0 var(--hover-width);
}
.split.left:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--left-bg-color);
}
.split.mid:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--mid-bg-color);
}
.split.right:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--right-bg-color);
}
.split.left,
.split.mid,
.split.right,
.split.left:before,
.split.mid:before,
.split.right:before {
transition: var(--speed) all ease-in-out;
}
<div class="container">
<div class="split left">
<h2>Option1</h2>
<a href="#" class="btn btn-left">Learn More</a>
</div>
<div class="split mid">
<h2>Option 2</h2>
<a href="#" class="btn btn-mid">Learn More</a>
</div>
<div class="split right">
<h2>Option 3</h2>
<a href="#" class="btn btn-right">Learn More</a>
</div>
</div>
Upvotes: 1