65

I'm trying to add a transition to a button I have that's background is made with css linear-gradient but it's not working.

This is the css for my button.

a.button
{
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@green), color-stop(100%,#a5c956));
-webkit-transition: background 5s linear;
}

a.button:hover
{
-webkit-gradient(linear, left top, left bottom, color-stop(0%,@greenhover), color-stop(100%,#89af37))
}

If you're wondering about @green and @greenhover, I'm using .less to make my css.

Anything wrong with this? Any ideas?

1
  • i just wanna hint to my answer coz you gonna find all answers refers to opacity change and that's not satisfying.. hope you agree and y'all find it helps Commented Feb 2, 2018 at 19:25

8 Answers 8

52

Sadly, you really can't transition gradients for now.

So, the only workable workaround is using an extra element with needed gradient and transition it's opacity:

a.button {
  position: relative;
  z-index: 9;
  display: inline-block;
  padding: 0 10px;
  background: -webkit-gradient(linear, 0 0, 0 100%, from(green), to(#a5c956));
  background: -webkit-linear-gradient(top, green, #a5c956);
  background: -moz-linear-gradient(top, green, #a5c956);
  background: -o-linear-gradient(top, green, #a5c956);
  background: linear-gradient(top, green, #a5c956);
}

.button-helper {
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  background: -webkit-gradient(linear, 0 0, 0 100%, from(lime), to(#89af37));
  background: -webkit-linear-gradient(top, lime, #89af37);
  background: -moz-linear-gradient(top, lime, #89af37);
  background: -o-linear-gradient(top, lime, #89af37);
  background: linear-gradient(top, lime, #89af37);
  -webkit-transition: opacity 1s linear;
  -moz-transition: opacity 1s linear;
  -o-transition: opacity 1s linear;
  transition: opacity 1s linear;
}

a.button:hover .button-helper {
  opacity: 1;
}
<a href="#" class="button"><span class="button-helper"></span>button</a>

Sign up to request clarification or add additional context in comments.

3 Comments

This is dated, psudo elements work fine now
This doesn't always provide the same results. You can use SVG to have a real transition instead
instead of even the svg solution i found this is so much satisfying check my solution
41

it's tricky.. and of course tricky is cool ;)

okay.. i got a solution. and it's basically done via amazing :before selector

#cool-hover{
	width: 120px;
	height: 120px;
	display: block;
	cursor: pointer;
	border-radius: 10px;
	box-shadow: 0 0 15px rgba(0,0,0,0.3);
	margin: 0px auto 24px auto;
	transition: all 0.5s;
	position: relative;
	overflow: hidden;
}
#cool-hover:before{
	border-radius: inherit;
	display: block;
	width: 200%;
	height: 200%;
	content: '';
        position: absolute;
        top: 0; 
        left: 0;
	background: linear-gradient(135deg, #21d4fd 25%, #b721ff 75%);	
	transition: all 0.5s;
	transform: translate(-25%, -25%);
	z-index: 0;
}
#cool-hover:after{
	border-radius: 9px;
	display: block;
	width: 108px;
	height: 108px;
	margin: 6px;
	background: url('https://i.imgur.com/w0BjFgr.png');
	background-size: cover;
	content: '';
	position: absolute;
	top: 0; left: 0;
	z-index: 1;
}
#cool-hover:hover:before{
	transform: translate(-25%, -25%) rotate(-180deg);
}
#cool-hover:hover{
	box-shadow: 0 0 35px rgba(0,0,0,0.3);
}
<div id="cool-hover"></div>


NOTE : i just added the :after sudo class just for the small on top image placeholder purpose..

have a nice awesome styling ;)

Comments

8

I know this pretty old but I could not find any good solution yet. So here is my solution

First Make gradient on ":before and hide it with opacity then transition opacity 1 on hover.

https://jsfiddle.net/sumon380/osqLpboc/3/

.button {
    text-decoration: none;
    padding: 10px 25px;
    font-size: 20px;
    color: #333;
    display: inline-block;
    background: #d6e9eb;
    position: relative;
    z-index: 1;
    transition: color 0.3s ease-out;

}
.button:before {
    background: #91a5f4;
    background: linear-gradient(135deg, #91a5f4 0%, #b08cf9 86%);
    content: "";
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    position: absolute;
    z-index: -1;
    opacity: 0;
    transition: opacity 0.3s ease-out;
}
.button:hover:before {
    opacity: 1;
}
.button:hover {
    color: #fff;
}
<a class="button" href="#">Button</a>

3 Comments

Best answer here!
It doesn't work for me unless I use ::before instead of :before.
okay it could have some browser specific issue. why not use .button:before, .button::before
6

You can fake gradient transitions using drop shadows! For instance, from one of my pages:

c { 
color: #FFF;
background: #000;
border-style:solid;
border-color:#CCC;
border-width: 0 0 0 1px;
box-shadow: 2px 2px 2px #555, inset 0 25px 20px -10px rgba(255, 255, 255, 0.3),
    inset 0 -15px 20px -10px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 2px 2px 2px #555, inset 0 25px 20px -10px rgba(255, 255, 255, 0.3),
    inset 0 -15px 20px -10px rgba(0, 0, 0, 0.15);
-o-box-shadow: 2px 2px 2px #555, inset 0 25px 20px -10px rgba(255, 255, 255, 0.3),
    inset 0 -15px 20px -10px rgba(0, 0, 0, 0.15);
-webkit-box-shadow: 2px 2px 2px #555,
    inset 0 25px 20px -10px rgba(255, 255, 255, 0.3),
    inset 0 -15px 20px -10px rgba(0, 0, 0, 0.15);
-moz-transition: background-color .5s ease; 
-o-transition: background-color .5s ease; 
-webkit-transition: background-color .5s ease-in-out; 
transition: background-color .5s ease;
}

Followed by:

c:hover {
color:#FFF;
background: #505;
position:relative;
top:1px;
box-shadow: -1px -1px -1px #555,inset 0 20px 20px -10px rgba(0, 0, 0, 0.15), 
        inset 0 -15px 20px -10px rgba(255, 255, 255, 0.3);
-moz-box-shadow: -1px -1px -1px #555,inset 0 20px 20px -10px rgba(0, 0, 0, 0.15),
    inset 0 -15px 20px -10px rgba(255, 255, 255, 0.3);
-o-box-shadow: -1px -1px -1px #555, inset 0 20px 20px -10px rgba(0, 0, 0, 0.15), 
        inset 0 -15px 20px -10px rgba(255, 255, 255, 0.3);
-webkit-box-shadow: 1px -1px -1px #555, inset 0 20px 20px -10px rgba(0, 0, 0, 0.15), 
    inset 0 -15px 20px -10px rgba(255, 255, 255, 0.3);
}

Here, you are essentially using an inset shadow as a Photoshop-like mask, causing a gradient effect on the underlying element. On hover, you invert the effect.

1 Comment

This has pretty horrid performance unless it's a very minor transition
2

If you're doing the slight highlight when hovering the button there is a much simpler solution. You can just nudge the gradient down a bit and have the background-color be the same as the top color of your gradient: http://cdpn.io/oaByI

It's pretty limited I know, but if works well for that use case.

Comments

1

I know this question is pretty old, but I found a good way to animate basic gradients that will work in some cases.

This method will let you animate a change in color of the gradient but not a change in the position of the color stops.

https://jsfiddle.net/62vzydeh/

HTML:

<div class="button">
    Click Me!
</div>

CSS:

.button {

  width: 200px;
  height: 30px;

  margin: 50px;
  padding-top: 10px;

  color: #C0C0C0;
  background: linear-gradient(to left, #F8F8F8, transparent 30%);
  background-color: #808080;

  text-align: center;
  font-family: sans-serif;

  cursor: pointer;

  transition: background-color 500ms;
}

.button:hover {

  background-color: #A0A0A0;
}

Comments

0

9 years, but this time, hope my styled-components can help someone:

import React, { ReactNode } from 'react'
import { Button as ButtonUI } from "@your-library-ui"
import styled from 'styled-components'

type Props = {
  onClick?: () => void;
  children?: ReactNode;
};

const Button = ({onClick, children}: Props) => (
  <StyledButton onClick={onClick} >
    {children}
    <ButtonHelper />
  </StyledButton>
)

export default Button

const ButtonHelper = styled.span`
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border-radius: 5px;
  background: linear-gradient(to right, #5ab0f4, #1273ea)!important;
  transition: opacity 0.2s linear;
`;

const StyledButton = styled(ButtonUI)`
  position: relative;
  z-index: 1;
  background: linear-gradient(to right, #1273ea, #1c94f4)!important;
  color: #fff;
  &:hover ${ButtonHelper} {
    opacity: 1;
  }
`;

And start using your new designed component with extra effect! Thanks to @kizu for the suggestion.

Comments

-3

you must have same style in source and changed style in target.

like

a {
   background: transparent;
   background: linear-gradient(transparent,transparent);
   -moz-transition: all 0.3s ease;
   -o-transition: all 0.3s ease;
   -webkit-transition: all 0.3s ease;
   transition: all 0.3s ease;
}
a:hover
{
   background: #abc07c;
   background: linear-gradient(#c5db95,#88a743);
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.