Animating a CSS Gradient Background on the Hover Event

Animating a CSS gradient background on the hover event

Animation on gradients aren't supported yet. However this site provides a pleasing approach for a animated kind of feel on hover-

http://sapphion.com/2011/10/css3-gradient-transition-with-background-position/

Sample css:-

#DemoGradient{  
background: -webkit-linear-gradient(#C7D3DC,#5B798E);
background: -moz-linear-gradient(#C7D3DC,#5B798E);
background: -o-linear-gradient(#C7D3DC,#5B798E);
background: linear-gradient(#C7D3DC,#5B798E);

-webkit-transition: background 1s ease-out;
-moz-transition: background 1s ease-out;
-o-transition: background 1s ease-out;
transition: background 1s ease-out;

background-size:1px 200px;
border-radius: 10px;
border: 1px solid #839DB0;
cursor:pointer;
width: 150px;
height: 100px;
}
#DemoGradient:Hover{
background-position:100px;
}

CSS: How to animate background color to highlight on hover, with only the area of cursor changing color?

Even through my predisposition to using JavaScript (it is where my skills lie), I believe you can't just do this in CSS, but also need JavaScript to do this. There might be a way, but I don't know it, and I am curious for someone else to answer with a magical full CSS solution and blow our minds. :D

For one approach of doing this, you need to use ::after to create the hover-element inside the row. You can then use CSS variables to pass your mouse position (gathered through JavaScript) into the hover-element, making it track the mouse position. Here is an example:

<!-- HTML -->
<div class="row">

</div>
/* CSS */
.row {
width: 300px;
height: 300px;
margin: 30px 30px;
position: relative;
overflow: hidden;
background: white;
}

.row::after {
content: "";
position: absolute;
top: calc(var(--y, 0) * 1px - 50px);
left: calc(var(--x, 0) * 1px - 50px);
width: 100px;
height: 100px;
opacity: 0;
background: radial-gradient(#cef230, #ffffff00 80%);
transition: opacity 1s;
}
.row:hover::after {
opacity: 1;
}
// JavaScript
const element = document.querySelector(".row");

element.addEventListener("mousemove", (e) => {
const { x, y } = element.getBoundingClientRect();
element.style.setProperty("--x", e.clientX - x);
element.style.setProperty("--y", e.clientY - y);

});

Key elements are the ::after to create the hover-element, the use of position: absolute; to allow for "top" and "left" attributes to position the hover-element, and applying overflow: hidden; to the row: in my testing the hover-element kept the mouse-move event firing even outside the row, unless overflow was hidden.

Rotate gradient

Your problem is with the background size, if I understand ok what you are trying has the wrong dimensions

.gradient {
background: -webkit-linear-gradient(left, lightgray,white);
background: -moz-linear-gradient(left, lightgray,white);
background: -o-linear-gradient(left, lightgray,white);
background: linear-gradient(left, lightgray,white);
-webkit-transition: background 1s ease-out;
-moz-transition: background 1s ease-out;
-o-transition: background 1s ease-out;
transition: background 1s ease-out;
-moz-background-size: 200px 1px;
-o-background-size: 200px 1px;
-webkit-background-size: 200px 1px;
background-size: 200px 1px;
cursor: pointer;
}

demo

Just thinking about it, the dimensions are predefined, so your class is not reusable. You can make it resolution independent, and the way it works is more easily understood. Just change the background sixe to

    background-size: 200% 100%;

well, the y dimension is not relevant, but setting it to 100% is clearer.
and the hover to

.gradient:hover {
background-position: 100%;
}

updated demo with 2 sizes

Animate on hover using javascript and css

You don't need javascript at all for that. Instead, just define the animation in the div's hover state:

div:hover {
animation-name:ShineAnimation;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-direction: alternate;
}

Or, using the shorthand:

div:hover {
animation: 4s infinite alternate ShineAnimation;
}

I think your animation is not working quite right, but that's a separate issue. Also you were missing a closing bracket after the keyframes definition. That may have been just a bad copy-paste?

CSS animation documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations

@-webkit-keyframes ShineAnimation{

from {

background-repeat:no-repeat;

background-image:-webkit-linear-gradient(

top left,

rgba(255, 255, 255, 0.8) 0%,

rgba(255, 255, 255, 0.5) 10%,

rgba(255, 255, 255, 0.5) 37%,

rgba(255, 255, 255, 0.0) 45%,

rgba(255, 255, 255, 0.0) 48%,

rgba(255, 255, 255, 0.5) 50%,

rgba(255, 255, 255, 0.8) 52%,

rgba(255, 255, 255, 0.0) 57%,

rgba(255, 255, 255, 0.0) 100%

);

background-position:-450px -450px;

background-size: 2000px 2000px;

}

to {

background-repeat:no-repeat;

background-position:450px 450px;

}

}

div {

background-color:#990000;

padding:50px;

margin:10px;

}

div:hover {

animation: 4s infinite alternate ShineAnimation;

}
<div id="shine-me">

How to animate a qpushbutton background's gradient to go from left to right on hover?

As you suspect, Qt Style Sheet does not support animations. In this case, an alternative is to use QXAnimation as QVariantAnimation:

from PyQt5 import QtCore, QtGui, QtWidgets

class LoginButton(QtWidgets.QPushButton):
def __init__(self, parent=None):
super().__init__(parent)

self.setMinimumSize(60, 60)

self.color1 = QtGui.QColor(240, 53, 218)
self.color2 = QtGui.QColor(61, 217, 245)

self._animation = QtCore.QVariantAnimation(
self,
valueChanged=self._animate,
startValue=0.00001,
endValue=0.9999,
duration=250
)

def _animate(self, value):
qss = """
font: 75 10pt "Microsoft YaHei UI";
font-weight: bold;
color: rgb(255, 255, 255);
border-style: solid;
border-radius:21px;
"""
grad = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop:{value} {color2}, stop: 1.0 {color1});".format(
color1=self.color1.name(), color2=self.color2.name(), value=value
)
qss += grad
self.setStyleSheet(qss)

def enterEvent(self, event):
self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
self._animation.start()
super().enterEvent(event)

def leaveEvent(self, event):
self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
self._animation.start()
super().enterEvent(event)

if __name__ == "__main__":
import sys

app = QtWidgets.QApplication(sys.argv)

w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)

for i in range(5):
button = LoginButton()
button.setText("Login")
lay.addWidget(button)
lay.addStretch()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

how to animate a css grandient change with jquery

Note, Not certain if the syntax , order of

-webkit-gradient(linear, left top, right top, from(rgba()), to(rgba()))

is accurate ? See linear-gradient , Using Gradients . At piece below , changed to

-webkit-linear-gradient(left top, rgba(), rgba())

Also, the easing option easeOutBounce not appear to be standard within jquery ; require either jquery ui , or jQuery Easing Plugin . Added jquery ui to scripts loaded.

jquery's .animate() may need a "color" plugin to animate color properties . Though , can utilize the step function , within .animate()'s options , to perform tasks for each "step" of the animation , see

.animate() , at step

A function to be called for each animated property of each animated
element. This function provides an opportunity to modify the Tween
object to change the value of the property before it is set.

The properties , here , is defined with border:"0" - though , with jquery ui color animations appear possible Color Animation - step function utilized at piece below.

Try

$(document).ready(function () {

$("body").mousemove(function (event) {

var sw = $(window).width(),

sh = $(window).height(),

valueX = event.pageX,

valueY = event.pageY;

var fX = (valueX / sw),

fY = (valueY / sh);

var alpha = ((fX / 2) + (fY / 2));

var r = Math.round(((Math.floor((Math.random() * 200) + 100)))),

g = Math.round(((Math.floor((Math.random() * 200) + 100)))),

b = Math.round(((Math.floor((Math.random() * 200) + 100)))),

r2 = Math.round(((Math.floor((Math.random() * 100) + 1)))),

g2 = Math.round(((Math.floor((Math.random() * 100) + 1)))),

b2 = Math.round(((Math.floor((Math.random() * 100) + 1))));

console.log('x:' + fX + ' - y:' + fY + '');

console.log('rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')');

console.log('rgba2(' + r2 + ',' + g2 + ',' + b2 + ',' + alpha + ')');

// animate the background color on mousemove

$(event.target).stop().animate({

border:"0"

}, {

duration: 1500

, easing: 'easeOutBounce'

, step: function() {

$(this).css('background'

,'-webkit-linear-gradient(left top, rgba('

+ r +','+ g +','+ b +','

+ alpha +'), rgba('

+ r2 +','+ g2 +','+ b2 +','+ alpha +')')

}

});

});

});
body {

width : 646px;

height : 615px;

background-color : transparent;

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<script src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>

Change background color of an element when hover on other element (slowly)

So I've ALMOST got it but the fade on mouseout is giving me trouble. As stated, you can't transition background-image and linear-gradients can't be transitioned BUT they can be animated! So here's the workaround I came up with:

I put all of your content into a container for positioning and alignment purposes. Then, I separated the child buttons from everything else and put your starter background into a container behind everything. From there, I established a class for each type of gradient change that you wanted (since you only wanted to change the top color) and assigned ids to each child that I could call in javascript to add the class as well as the gradient animation. I also added a slightly different shade of blue so you could actually see that transition occur otherwise that button wouldn't appear to do much. So it works except that when you mouse out the animation isn't smooth. That's the part I'm still trying to work through. I've tried adding another class (gradientOut) but it doesn't seem to be doing what I want just yet.

let gradientOverlay = document.getElementById('gradientOverlay');
let gradient = document.getElementsByClassName('gradient');

let red = document.getElementById('red');
red.addEventListener("mouseenter", function(event) {
gradientOverlay.classList.add('redG');
gradientOverlay.classList.add('gradient');
});
red.addEventListener("mouseleave", function(event) {
gradientOverlay.classList.remove('redG');
gradientOverlay.classList.remove('gradient');
});

let blue = document.getElementById('blue');
blue.addEventListener("mouseenter", function(event) {
gradientOverlay.classList.add('blueG');
gradientOverlay.classList.add('gradient');
});
blue.addEventListener("mouseleave", function(event) {
gradientOverlay.classList.remove('blueG');
gradientOverlay.classList.remove('gradient');
});

let green = document.getElementById('green');
green.addEventListener("mouseenter", function(event) {
gradientOverlay.classList.add('greenG');
gradientOverlay.classList.add('gradient');
});
green.addEventListener("mouseleave", function(event) {
gradientOverlay.classList.remove('greenG');
gradientOverlay.classList.remove('gradient');
});

let black = document.getElementById('black');
black.addEventListener("mouseenter", function(event) {
gradientOverlay.classList.add('blackG');
gradientOverlay.classList.add('gradient');
});
black.addEventListener("mouseleave", function(event) {
gradientOverlay.classList.remove('blackG');
gradientOverlay.classList.remove('gradient');
});

let pink = document.getElementById('pink');
pink.addEventListener("mouseenter", function(event) {
gradientOverlay.classList.add('pinkG');
gradientOverlay.classList.add('gradient');
});
pink.addEventListener("mouseleave", function(event) {
gradientOverlay.classList.remove('pinkG');
gradientOverlay.classList.remove('gradient');
});

let brown = document.getElementById('brown');
brown.addEventListener("mouseenter", function(event) {
gradientOverlay.classList.add('brownG');
gradientOverlay.classList.add('gradient');
});
brown.addEventListener("mouseleave", function(event) {
gradientOverlay.classList.remove('brownG');
gradientOverlay.classList.remove('gradient');
});
:root {
--red: #ff5656f8;
--blue: #00ffea;
--green: #6cff7f;
--black: #353535;
--pink: #ff2fff;
--brown: #8b0000;
--backgroundTopBlue: #0cf0de;
}

body {
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
margin: 0;
padding: 0;
height: 100vh;
}

.mainContainer {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-content: center;
justify-content: center;
padding: 0px;
margin: 0 auto;
z-index: 2;
width: 940px;
height: 240px;
}

.main {
display: flex;
background-image: linear-gradient(to bottom, var(--backgroundTopBlue), blue);
padding: 0px;
margin: 0 auto;
border-radius: 10px;
z-index: 0;
width: 940px;
height: 240px;
}

.childContainer {
display: flex;
align-items: center;
justify-items: center;
padding: 0px;
margin: 0 auto;
z-index: 1;
}

.gradientOverlay {
display: block;
position: absolute;
margin: 0 auto;
width: 940px;
height: 240px;
background-image: linear-gradient(to bottom, var(--backgroundTopBlue), blue);
border-radius: 10px;
opacity: 0;
z-index: 0;
}

.child {
width: 100px;
height: 100px;
margin: 20px;
z-index: 2;
}

#red {
background-color: var(--red);
}

#blue {
background-color: var(--blue);
}

#green {
background-color: var(--green);
}

#black {
background-color: var(--black);
}

#pink {
background-color: var(--pink);
}

#brown {
background-color: var(--brown);
}

.redG {
display: flex;
background-image: linear-gradient(to bottom, var(--red), blue);
padding: 0px;
opacity: 0;
border-radius: 10px;
z-index: 1;
}

.blueG {
display: flex;
background-image: linear-gradient(to bottom, var(--blue), blue);
padding: 0px;
opacity: 0;
border-radius: 10px;
z-index: 1;
}

.greenG {
display: flex;
background-image: linear-gradient(to bottom, var(--green), blue);
padding: 0px;
opacity: 0;
border-radius: 10px;
z-index: 1;
}

.blackG {
display: flex;
background-image: linear-gradient(to bottom, var(--black), blue);
padding: 0px;
opacity: 0;
border-radius: 10px;
z-index: 1;
}

.pinkG {
display: flex;
background-image: linear-gradient(to bottom, var(--pink), blue);
padding: 0px;
opacity: 0;
border-radius: 10px;
z-index: 1;
}

.brownG {
display: flex;
background-image: linear-gradient(to bottom, var(--brown), blue);
padding: 0px;
opacity: 0;
border-radius: 10px;
z-index: 1;
}

.gradient {
animation: gradient 1s ease-in forwards;
}

@keyframes gradient {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

.gradientOut {
animation: gradientOut 1s ease-out forwards;
}

@keyframes gradientOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

<body>
<div class="mainContainer">
<div class="main" id="main">
<div class="gradientOverlay" id="gradientOverlay">
</div>
<div class="childContainer">
<div class="child" id="red"></div>
<div class="child" id="blue"></div>
<div class="child" id="green"></div>
<div class="child" id="black"></div>
<div class="child" id="pink"></div>
<div class="child" id="brown"></div>
</div>
</div>
</div>
</body>

</html>

How to keep link hover animation after clicking?

You are using el.querySelector() which will only return the first matching element found. You need to get the entire nodeList of the elements selector, use el.querySelectorAll() then run the nodeList through a loop and place your function in an eventListener. Since you want to remove the active class, there are multiple ways to do this. I did it by simply removing it from all elements using the el.forEach loop and then set the classList on the event.target of the event with in the function.

You could use a conditional to check which element has the active class and then toggle/remove it on click as well but that would be a bit more code in your function.

EDITS: OP wants to determine which link has been pressed on another page once the href has sent them to that page. In this case there is no need for JS, just statically set the class in the corresponding page button within that pages HTML.

If you really want to use JS, you can add an id to the body tag on each page, ie on contact page --> <body id="Contact"> that corresponds with the textContact of each of your navs page link button. Then using JS, get rid of the eventListener and simply look for the body.id and if it equals the link.textContent in the loop over the nodeList set the active class.

links.forEach(link => document.body.id === link.textContent ? link.classList.add("is-active") : null)

User clicks About on about.html

^^^^^^^^^^^^^^^^^^^^^

<li class="desktop-link is-active"><a class="link" href="html/about.html">About</a></li>

Here is the answer to the original question:

//--> you need to get all the elements in the nodeList 
//--> with the class .link --> querySelectorAll()
const links = document.querySelectorAll(".link");
//--> loop over these elements and add the eventListener
links.forEach(link => document.body.id === link.textContent ? link.classList.add("is-active") : null)
.link {
color: var(--dracula-pink);
padding: 5px 5px 5px 5px;
margin-right: 5rem;
text-decoration: none;
font-size: 1.2rem;
text-transform: uppercase;
text-shadow: 0 2px 3px rgba(0, 0, 0, 0.4), 0 8px 13px rgba(0, 0, 0, 0.1), 0 18px 23px rgba(0, 0, 0, 0.1);
}

.link:hover {
background-repeat: repeat-x;
background-position: left 0% bottom -5%;
background-image: linear-gradient(90deg, rgba(139, 233, 253, 1) 0%, rgba(189, 147, 249, 1) 50%, rgba(80, 250, 123, 1) 100%);
background-size: 100% 18%;
transition: ease-in 0.2s;
}

.link.is-active {
background-repeat: repeat-x;
background-position: left 0% bottom -5%;
background-image: linear-gradient(90deg, rgba(139, 233, 253, 1) 0%, rgba(189, 147, 249, 1) 50%, rgba(80, 250, 123, 1) 100%);
background-size: 100% 18%;
}
<body id="Home">
<div class="nav-desktop">
<ul class="desktop-list">
<li class="desktop-link"><a class="link" href="#?is-active">Home</a></li>
<li class="desktop-link"><a class="link" href="#?is-active">About</a></li>
<li class="desktop-link"><a class="link" href="#?is-active">Blog</a></li>
<li class="desktop-link"><a class="link" href="#?is-active">Projects</a></li>
<li class="desktop-link"><a class="link" href="#?is-active">Contact</a></li>
</ul>
</div>


Related Topics



Leave a reply



Submit