75

Having a play around with some css3 today, transitions mainly.

What i would like to achieve is that upon hover of an li element the background will fill from left to right with a different colour, ideally i would like to be able to fill half way or all the way.. I have started a jsfiddle

Do i need to use the property

-vendor-prefix transition 

Could anyone give me some pointers on achieving this please.

Thanks

Richlewis
  • 15,070
  • 37
  • 122
  • 283
  • Do you mean something like this??? http://www.htmldrive.net/items/demo/71/Dynamic-glide-navigation-with-jQuery-plugin – Nitesh Jun 20 '13 at 11:12
  • http://caniuse.com/#feat=css-transitions This will tell you whether you need to use a vendor prefix or not. For webkit browsers you will need to use the webkit prefix. – jezzipin Jun 20 '13 at 11:14
  • no, i would like the li element being hovered to fill from left to right with a different colour – Richlewis Jun 20 '13 at 11:14
  • 1
    I guess you want something like a gradient. If so, then this will help http://sapphion.com/2011/10/css3-gradient-transition-with-background-position/ – Correia JPV Jun 20 '13 at 11:18

3 Answers3

193

The thing you will need to do here is use a linear gradient as background and animate the background position. In code:

Use a linear gradient (50% red, 50% blue) and tell the browser that background is 2 times larger than the element's width (width:200%, height:100%), then tell it to position the background right.

background: linear-gradient(to left, red 50%, blue 50%) right;
background-size: 200% 100%;

On hover, change the background position to left and with transition:all 2s ease;, the position will change gradually (it's nicer with linear tough)

background-position: left;

http://jsfiddle.net/75Umu/3/

As for the -vendor-prefix'es, see the comments to your question

extra:

If you wish to have a "transition" in the colour, you can make it 300% width and make the transition start at 34% (a bit more than 1/3) and end at 65% (a bit less than 2/3).

background: linear-gradient(to left, red 34%, blue 65%) right;
background-size: 300% 100%;

Demo:

div {
    font: 22px Arial;
    display: inline-block;
    padding: 1em 2em;
    text-align: center;
    color: white;
    background: red; /* default color */

    /* "to left" / "to right" - affects initial color */
    background: linear-gradient(to left, salmon 50%, lightblue 50%) right;
    background-size: 200%;
    transition: .5s ease-out;
}
div:hover {
    background-position: left;
}
<div>Hover me</div>
YoniChechik
  • 1,397
  • 16
  • 25
beardhatcode
  • 4,533
  • 1
  • 16
  • 29
  • +1 but I had to edit your fiddle to remove the -webkit-prefix in order to see it work in Firefox. :-( – Spudley Jun 20 '13 at 11:40
  • @Spudley You will need to use both as Webkit browsers do not currently use the stock transition. – jezzipin Jun 20 '13 at 11:46
  • @jezzipin - actually according to [CanIUse](http://caniuse.com/#feat=css-transitions), Chrome doesn't require a prefix any more (although I guess Chrome isn't technically a webkit browser any more...). But my point was that the question specifically asked about prefixes, so the fact that the fiddle didn't work in all browsers due to the prefix was a bit of a faux-pas. :) Anyway, all sorted now. – Spudley Jun 20 '13 at 12:19
  • @gar_onn how would i get the transition to stop at say 3/4 of the way? rather than filling up the element – Richlewis Jun 20 '13 at 12:25
  • You can use `background-position:75% bottom;` see [the backgound-position documentaion on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position) – beardhatcode Jun 20 '13 at 12:36
  • seriously @beardhatcode you should edit https://developer.mozilla.org/en-US/docs/Web/CSS/background-size great answer! – dotnetCarpenter May 13 '16 at 22:51
  • Nice one, just two minor remarks/additions. 1) I noticed that in my case, I had to set the splits lightly beyond 50% in the normal case, and slightly below 50% in the hovered case to prevent left-over background. 2) If you apply 1, and then redefine the gradient for the hover-case, specify `background-image` rather than `background`, so `background-size` and `background-position`-properties aren't reset as well. – Bram May 17 '20 at 10:58
38

A single css code on hover can do the trick: box-shadow: inset 100px 0 0 0 #e0e0e0;

A complete demo can be found in my fiddle:

https://jsfiddle.net/shuvamallick/3o0h5oka/

shuva mallick
  • 509
  • 4
  • 6
  • Clever. I like it. I don't know about browser compatibility, but I like it. – armadadrive Mar 14 '17 at 17:05
  • 4
    The only thing I can see immediately is that the `100px` value needs to be hard-coded, so it's harder to use this as a class across multiple elements of varying widths. – armadadrive Mar 14 '17 at 17:14
  • 1
    It works, however box-shadow is a very expensive property to animate (in terms of system resources) https://csstriggers.com/box-shadow and also setting `transition: all;` is not the best. A similar effect could be achieved with pseudo elements: https://jsfiddle.net/f198x4bq/19/ . The same effect is achieved by transitioning the transform and opacity properties on `::before` and transition the color property on the button. And it addresses the problem that @armadadrive pointed out – Phlame Aug 10 '20 at 01:13
  • This is easiest one and thats what exactly I was looking for – Md. Amanur Rahman May 10 '23 at 18:54
3

If you are like me and need to change color of text itself also while in the same time filling the background color check my solution.

Steps to create:

  1. Have two text, one is static colored in color on hover, and the other one in default state color which you will be moving on hover
  2. On hover move wrapper of the not static one text while in the same time move inner text of that wrapper to the opposite direction.
  3. Make sure to add overflow hidden where needed

Good thing about this solution:

  • Support IE9, uses only transform
  • Button (or element you are applying animation) is fluid in width, so no fixed values are being used here

Not so good thing about this solution:

  • A really messy markup, could be solved by using pseudo elements and att(data)?
  • There is some small glitch in animation when having more then one button next to each other, maybe it could be easily solved but I didn't take much time to investigate yet.

Check the pen ---> https://codepen.io/nikolamitic/pen/vpNoNq

<button class="btn btn--animation-from-right">
  <span class="btn__text-static">Cover left</span>
  <div class="btn__text-dynamic">
    <span class="btn__text-dynamic-inner">Cover left</span>
  </div>
</button>

.btn {
  padding: 10px 20px;
  position: relative;

  border: 2px solid #222;
  color: #fff;
  background-color: #222;
  position: relative;

  overflow: hidden;
  cursor: pointer;

  text-transform: uppercase;
  font-family: monospace;
  letter-spacing: -1px;

  [class^="btn__text"] {
    font-size: 24px;
  }

  .btn__text-dynamic,
  .btn__text-dynamic-inner {    
    display: flex;
    justify-content: center;
    align-items: center;

    position: absolute;
    top:0;
    left:0;
    right:0;
    bottom:0;
    z-index: 2;

    transition: all ease 0.5s;
  }

  .btn__text-dynamic {
    background-color: #fff;
    color: #222;

    overflow: hidden;
  }

  &:hover {
    .btn__text-dynamic {
      transform: translateX(-100%);
    }
    .btn__text-dynamic-inner {
      transform: translateX(100%);
    }
  }
}

.btn--animation-from-right {
    &:hover {
    .btn__text-dynamic {
      transform: translateX(100%);
    }
    .btn__text-dynamic-inner {
      transform: translateX(-100%);
    }
  }
}

You can remove .btn--animation-from-right modifier if you want to animate to the left.

Nikola Mitic
  • 1,298
  • 3
  • 11
  • 23