I am trying to replicate this transition from uber.design site:
The thing is that i am stuck at reversing the transition:
.un {
display: inline-block;
}
.un:after {
content: '';
width: 0px;
height: 2px;
display: block;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
<span class="un">Underlined Text</span>
You can use gradient and adjust background-position with a delay to obtain such effect:
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(#000 0 0);
background-position: 0 100%; /*OR bottom left*/
background-size: 0% 2px;
background-repeat: no-repeat;
transition:
background-size 0.3s,
background-position 0s 0.3s; /*change after the size immediately*/
}
.un:hover {
background-position: 100% 100%; /*OR bottom right*/
background-size: 100% 2px;
}
<span class="un">Underlined Text</span>
In case you want a continuous animation on hover you can try this:
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(#000 0 0);
background-position: right -100% bottom 0;
background-size: 200% 2px;
background-repeat: no-repeat;
}
.un:hover {
background-position: left -100% bottom 0;
transition: background-position 0.5s;
}
<span class="un">Underlined Text</span>
You can check this answer for more details about how the calculation of the different value is done: Using percentage values with background-position on a linear-gradient
Another kind of animation
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(to right, #000 33%,#0000 33% 66%,#000 66%);
background-position: right bottom;
background-size: 300% 2px;
background-repeat: no-repeat;
}
.un:hover {
background-position: left bottom;
transition: background-position 0.5s;
}
<span class="un">Underlined Text</span>
let's don't forget the basic one:
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(#000 0 0);
background-position: right bottom; /* OR left bottom*/
background-size: 100% 2px;
background-repeat: no-repeat;
transition: background-size 0.5s;
}
.un:hover {
background-size: 0% 2px;
}
<span class="un">Underlined Text</span>
You can find more techniques here: https://dev.to/afif/100-underline-overlay-animation-the-ultimate-css-collection-4p40
Another related article: Cool Hover Effects That Use Background Properties
You'll need your pseudo element to be absolute positioned and use the :not selector to reproduce this effect.
.un {
display: inline-block;
position: relative;
}
.un:after {
content: '';
width: 0px;
height: 2px;
position: absolute;
top: 100%;
left: 0;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
}
.un:not(:hover):after {
right: 0;
left: auto;
}
<span class="un">Underlined Text</span>
The easiest solution of all, without :not selector or gradients, is to switch between right and left positions such as in the code.
span.un {
position: relative;
}
span.un::after {
position: absolute;
content: "";
background: black;
bottom: 0;
right: 0;
height: 2px;
width: 0%;
transition: 300ms ease-in-out;
}
span.un:hover::after {
width: 100%;
left: 0;
}
<span class="un">Underline me</span>
Related
I'm trying to get a transition hover effect on border that the border expands on hover.
h1 {
color: #666;
}
h1:after {
position: absolute;
left: 10px;
content: '';
height: 40px;
width: 275px;
border-bottom: solid 3px #019fb6;
transition: left 250ms ease-in-out, right 250ms ease-in-out;
opacity: 0;
}
h1:hover:after {
opacity: 1;
}
<h1>CSS IS AWESOME</h1>
I've tried this on Jsfiddle
To expand the bottom border on hover, you can use transform:scaleX'(); (mdn reference) and transition it from 0 to 1 on the hover state.
Here is an example of what the border hover effect can look like :
The border and transition are set on a pseudo element to prevent transitioning the text and avoid adding markup.
To expand the bottom border from left or right, you can change the transform-origin property to the left or right of the pseudo element:
h1 { color: #666;display:inline-block; margin:0;text-transform:uppercase; }
h1:after {
display:block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1:hover:after { transform: scaleX(1); }
h1.fromRight:after{ transform-origin:100% 50%; }
h1.fromLeft:after{ transform-origin: 0% 50%; }
<h1 class="fromCenter">Expand from center</h1><br/>
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
Note : You need to add vendor prefixes to maximize browser support (see canIuse).
Expand bottom border on hover with 2 lines
You can achieve this effect when the text spans on 2 lines. The before pseudo element is absolutely positioned to make underline of the first line with bottom:1.2em;:
h1 { position:relative;color: #666;display:inline-block; margin:0;text-transform:uppercase;text-align:center;line-height:1.2em; }
h1:after, h1:before {
display:block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1:before{
position:absolute;
bottom:1.2em; left:0;
width:100%;
}
.ef2:hover:after {
transition-delay:150ms;
}
h1:hover:after, h1:hover:before { transform: scaleX(1); }
<h1>Expand border<br/>on two lines</h1>
<br/>
<br/>
<h1 class="ef2">Expand border<br/>effect two</h1>
Different transition direction on hover in and out :
The point is to change the transform-origin position from one side to the other on the hover state. This way the bottom boder enters from one side on hover and exits on the other when the element isn't hovered anymore.
Here is a demo :
h1 { color: #666;display:inline-block; margin:0;text-transform:uppercase; }
h1:after {
display:block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1.fromLeft:after{ transform-origin: 100% 50%; }
h1.fromRight:after{ transform-origin: 0% 50%; }
h1.fromLeft:hover:after{ transform: scaleX(1); transform-origin: 0% 50%; }
h1.fromRight:hover:after{ transform: scaleX(1); transform-origin: 100% 50%; }
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
We can do this with only background. No pseudo-element needed. This is more flexible.
h1 {
/* you can change these variables to control the border */
--border-color: purple;
--border-width: 5px;
--bottom-distance: 0px; /* you can increase this */
color: #666;
display: inline-block;
background-image: linear-gradient(var(--border-color), var(--border-color));
background-size: 0% var(--border-width);
background-repeat: no-repeat;
transition: background-size 0.3s;
margin: 5px 0;
}
.fromCenter {
background-position: 50% calc(100% - var(--bottom-distance));
}
.fromRight {
background-position: 100% calc(100% - var(--bottom-distance));
}
.fromLeft {
background-position: 0 calc(100% - var(--bottom-distance))
}
h1:hover {
background-size: 100% var(--border-width);
}
<h1 class="fromCenter">Expand from center</h1><br/>
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
Multiple line animation:
h1 {
/* you can change these variables to control the border */
--border-color: purple;
--border-width: 5px;
--bottom-distance: 0px; /* you can increase this */
color: #666;
display: inline; /* should be 'inline' for multiple line animation */
background-image: linear-gradient(var(--border-color), var(--border-color));
background-size: 0% var(--border-width);
background-repeat: no-repeat;
transition: background-size 0.5s;
}
.fromCenter {
background-position: 50% calc(100% - var(--bottom-distance));
}
.fromRight {
background-position: 100% calc(100% - var(--bottom-distance));
}
.fromLeft {
background-position: 0 calc(100% - var(--bottom-distance))
}
h1:hover {
background-size: 100% var(--border-width);
}
<h1 class="fromLeft">Expand from <br>left with <br>multiple line</h1>
simple and lightweight version
li {
margin-bottom: 10px;
}
.cool-link {
display: inline-block;
color: #000;
text-decoration: none;
}
.cool-link::after {
content: '';
display: block;
width: 0;
height: 2px;
background: #000;
transition: width .3s;
}
.cool-link:hover::after {
width: 100%;
//transition: width .3s;
}
<ul>
<li><a class="cool-link" href="#">A cool link</a></li>
<li><a class="cool-link" href="#">A cool link</a></li>
<li><a class="cool-link" href="#">A cool link</a></li>
</ul>
I know this is an old post and it is already answered but you might like the following effect too.
<div class="cd-single-point">
<a class="cd-img-replace" href="#0"></a>
</div>
.cd-single-point {
position: absolute;
list-style-type: none;
left: 20px;
top: 20px;
}
.cd-single-point>a {
position: relative;
z-index: 2;
display: block;
width: 10px;
height: 10px;
border-radius: 50%;
background: #0079ff;
-webkit-transition: background-color 0.2s;
-moz-transition: background-color 0.2s;
-o-transition: background-color 0.2s;
transition: background-color 0.2s;
}
.cd-single-point::after {
content: '';
position: absolute;
border-radius: 50%;
width: 100%;
height: 100%;
top: 0;
left: 0;
animation: cd-pulse 2s infinite;
}
#keyframes cd-pulse
{
0% {box-shadow:0 0 0 0 #0079ff}
100%{box-shadow:0 0 0 20px rgba(255,150,44,0)}
}
DEMO
h1 {
color: #666;
display:inline-block;
margin:0;
text-transform:uppercase;
}
h1:after {
display:block;
content: '';
border-bottom: solid 3px #92a8d1;
transform: scaleX(0);
transition: transform 800ms ease-in-out;
}
h1:hover:after {
transform: scaleX(1);
}
<h1 class="fromCenter">Hover Over Me</h1><br/>
we can do using simple transition effect.
HTML
<h1>CSS IS AWESOME</h1>
CSS
h1 {
color: #666;
position: relative;
display: inline-block;
}
h1:after {
position: absolute;
left: 50%;
content: '';
height: 40px;
height: 5px;
background: #f00;
transition: all 0.5s linear;
width: 0;
bottom: 0;
}
h1:hover:after {
width: 270px;
margin-left: -135px;
}
Link to Fiddle
h1 {
/* you can change these variables to control the border */
--border-color: purple;
--border-width: 5px;
--bottom-distance: 0px; /* you can increase this */
color: #666;
display: inline-block;
background-image: linear-gradient(var(--border-color), var(--border-color));
background-size: 0% var(--border-width);
background-repeat: no-repeat;
transition: background-size 0.3s;
margin: 5px 0;
}
.fromCenter {
background-position: 50% calc(100% - var(--bottom-distance));
}
.fromRight {
background-position: 100% calc(100% - var(--bottom-distance));
}
.fromLeft {
background-position: 0 calc(100% - var(--bottom-distance))
}
h1:hover {
background-size: 100% var(--border-width);
}
<h1 class="fromCenter">Expand from center</h1><br/>
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
transition: all 1000ms ease-in-out;
Demo
or are you looking for this
Demo2
h1 {
color: #666;
}
h1:after {
position: absolute;
left: 10px;
content: '';
height: 40px;
width: 275px;
border-bottom: solid 3px #019fb6;
transition: all 550ms ease-in-out;
border-bottom-width: 0px;
}
h1:hover:after {
border-bottom-width: 5px;
}
<h1>CSS IS AWESOME</h1>
I am trying to replicate this transition from uber.design site:
The thing is that i am stuck at reversing the transition:
.un {
display: inline-block;
}
.un:after {
content: '';
width: 0px;
height: 2px;
display: block;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
<span class="un">Underlined Text</span>
You can use gradient and adjust background-position with a delay to obtain such effect:
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(#000 0 0);
background-position: 0 100%; /*OR bottom left*/
background-size: 0% 2px;
background-repeat: no-repeat;
transition:
background-size 0.3s,
background-position 0s 0.3s; /*change after the size immediately*/
}
.un:hover {
background-position: 100% 100%; /*OR bottom right*/
background-size: 100% 2px;
}
<span class="un">Underlined Text</span>
In case you want a continuous animation on hover you can try this:
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(#000 0 0);
background-position: right -100% bottom 0;
background-size: 200% 2px;
background-repeat: no-repeat;
}
.un:hover {
background-position: left -100% bottom 0;
transition: background-position 0.5s;
}
<span class="un">Underlined Text</span>
You can check this answer for more details about how the calculation of the different value is done: Using percentage values with background-position on a linear-gradient
Another kind of animation
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(to right, #000 33%,#0000 33% 66%,#000 66%);
background-position: right bottom;
background-size: 300% 2px;
background-repeat: no-repeat;
}
.un:hover {
background-position: left bottom;
transition: background-position 0.5s;
}
<span class="un">Underlined Text</span>
let's don't forget the basic one:
.un {
display: inline-block;
padding-bottom:2px;
background-image: linear-gradient(#000 0 0);
background-position: right bottom; /* OR left bottom*/
background-size: 100% 2px;
background-repeat: no-repeat;
transition: background-size 0.5s;
}
.un:hover {
background-size: 0% 2px;
}
<span class="un">Underlined Text</span>
You can find more techniques here: https://dev.to/afif/100-underline-overlay-animation-the-ultimate-css-collection-4p40
Another related article: Cool Hover Effects That Use Background Properties
You'll need your pseudo element to be absolute positioned and use the :not selector to reproduce this effect.
.un {
display: inline-block;
position: relative;
}
.un:after {
content: '';
width: 0px;
height: 2px;
position: absolute;
top: 100%;
left: 0;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
}
.un:not(:hover):after {
right: 0;
left: auto;
}
<span class="un">Underlined Text</span>
The easiest solution of all, without :not selector or gradients, is to switch between right and left positions such as in the code.
span.un {
position: relative;
}
span.un::after {
position: absolute;
content: "";
background: black;
bottom: 0;
right: 0;
height: 2px;
width: 0%;
transition: 300ms ease-in-out;
}
span.un:hover::after {
width: 100%;
left: 0;
}
<span class="un">Underline me</span>
I am trying to make a text color change either bottom up or up to bottom on hover.
.box {
width: 200px; height: 100px;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, red 50%, green 50%);
-webkit-transition: background-position 1s;
-moz-transition: background-position 1s;
transition: background-position 1s;
}
.box:hover {
background-position: 0 -100%;
}
<div class="box">Text</div>
the above code makes the box change color instead the text. What can I do to make the text color instead of the box.
You gotta use Background Clip:
.box {
width: 200px;
height: 100px;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, red 50%, green 50%);
-webkit-transition: background-position 3s;
-moz-transition: background-position 3s;
transition: background-position 3s;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: bold;
font-size: 50pt;
}
.box:hover {
background-position: 0 -100%;
}
<div class="box">Text</div>
Note: I have increased the font size and time to 3 seconds to see the effect well.
You can achieve the effect using an overlay (the before pseudo element) with the background, and mix-blend-mode: screen:
.box {
position: relative;
width: 200px;
height: 100px;
font-size: 5em;
background: white;
}
.box::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, red 50%, green 50%);
transition: background-position 1s;
content: '';
pointer-events: none;
mix-blend-mode: screen;
}
.box:hover::before {
background-position: 0 -100%;
}
<div class="box">Text</div>
I'm trying to make the child image slide to the left and dissapear just like the parent. If your run the snipped now the image is scaling instead of sliding to the left.
How can I prevent the image to scale? And make the image slide to the left and dissapear just like the parent?
The transition will trigger by the media query.
This is my code.
.parent {
height: 130px;
width: 180px;
background-color: #fff;
border-bottom-right-radius: 10px;
border: 1px solid #000000;
text-align: center;
float: left;
position: fixed;
z-index: 1;
transition: ease all 0.3s;
}
.child {
width: 100%;
height: 100%;
background-size: contain;
text-indent: -9999px;
display: block;
background-image: url(https://static.pexels.com/photos/34490/keyboard-computer-keys-white.jpg);
background-repeat: no-repeat;
background-position: center center;
}
#media screen and (max-width: 655px){
.parent {
visibility: hidden;
width: 1px;
}
}
<div class="parent">
<span class="child">
</span>
</div>
Easiest solution that I could suggest you is set visibility:visible; for .child element and this works, but it is not supported by some browser. And this is only element which makes child element visible on hiding parent element.
The visibility property can be used to hide an element while leaving
the space where it would have been. It can also hide rows or columns
of a table.
Solution - 1
Check this jsfiddle
.parent {
height: 130px;
width: 180px;
background-color: #fff;
border-bottom-right-radius: 10px;
border: 1px solid #000000;
text-align: center;
float: left;
position: fixed;
z-index: 1;
transition: ease all 0.3s;
}
.child {
width: 100%;
height: 100%;
background-size: contain;
text-indent: -9999px;
display: block;
background-image: url(https://static.pexels.com/photos/34490/keyboard-computer-keys-white.jpg);
background-repeat: no-repeat;
background-position: center center;
}
#media screen and (max-width: 655px){
.parent {
visibility: hidden;
width: 1px;
}
.child{
width:180px;
height:130px;
visibility:visible;
background-size:100% 100%;
}
}
<div class="parent">
<span class="child">
</span>
</div>
Solution - 2
Check this jsFiddle
Create two different element and hide below div using opacity.
#bx{
width:200px;
height:130px;
background:#111;
transition: ease all 0.3s;
}
#b{
width:200px;
height:120px;
top:13px;
left:8px;
position:absolute;
background-image: url(https://static.pexels.com/photos/34490/keyboard-computer-keys-white.jpg);
background-repeat: no-repeat;
background-position: center center;
background-size:100%;
margin-left:0;
transition: ease all 0.3s;
}
#media screen and (max-width: 655px){
#bx{
width:1px;
opacity:0;
}
#b{
margin-left:-220px;
}
}
<div id="bx"></div>
<div id="b"></div>
The reason why the .child disappears with parent is because:
...the .child's height and width are 100% of .parent. Guess what .child's height and width are when.parent's` width and height are 1px and 130px (hint: what's a 100% of 1px and 100% of 130px?)
Another reason is because all children of an element that has visibility:hidden will be hidden as well, unless a child element has visibility: visible explicitly set (must have it as a declared CSS rule)
So knowing this, we should counter those properties when that MQ (media query) kicks in. Details are commented in the Snippet below:
.child {
width: 100%;
height: 100%;
background-size: contain;
text-indent: -9999px;
display: block;
background-image: url(https://static.pexels.com/photos/34490/keyboard-computer-keys-white.jpg);
background-repeat: no-repeat;
background-position: center center;
/* These properties were added so that `.child` is in the normal
|| "flow" to which `.parent` is not due to it having `position: fixed`
*/
position: relative;
right: 0;
bottom: 0;
}
#media screen and (max-width: 640px) {
.parent {
visibility: hidden;
width: 1px;
}
/* This ruleset will counter the properties
|| that were previously discussed
*/
.child {
visibility: visible;
min-width: 180px;
min-height: 130px;
}
}
SNIPPET
.parent {
height: 130px;
width: 180px;
background-color: #fff;
border-bottom-right-radius: 10px;
border: 1px solid #000000;
text-align: center;
float: left;
position: fixed;
z-index: -1;
background: red;
}
.child {
width: 100%;
height: 100%;
background-size: contain;
text-indent: -9999px;
display: block;
background-image: url(https://static.pexels.com/photos/34490/keyboard-computer-keys-white.jpg);
background-repeat: no-repeat;
background-position: center center;
position: relative;
right: 0;
bottom: 0;
}
#media screen and (max-width: 640px) {
.parent {
width: 1px;
overflow-x: hidden;
transition: width 0.3s ease;
}
.child {
visibility: visible;
max-width: 0px;
min-height: 130px;
transition: transform 1s ease-out;
transform: translateX(-180px);
}
}
<div class="parent">
<span class="child">
</span>
</div>
Check out example that you need to understand.
.sibling {
width:300px;
height:56px;
background-color:hsla(40, 50%, 60%, .6);
position:absolute;
left:240px;
}
.parent {
visibility:visible;
width:170px;
height:170px;
border-radius:50%;
background-image: linear-gradient(90deg, hsla(10, 90%, 50%, 1) 50%, hsla(100, 90%, 50%, .0) 50%);
position:absolute;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-transition:0s;
transition:0s;
}
.sibling:hover ~ .parent {
visibility:visible;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transition: .6s ease-in .2s;
transition: .6s ease-in .2s;
}
.child {
width:150px;
height:150px;
border-radius:50%;
background-image: linear-gradient(90deg, hsla(5, 35%, 50%, 1) 50%, hsla(100, 90%, 50%, .0) 50%);
position: relative;
top: 10px;
left: 10px;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transition:0s;
transition:0s;
}
.sibling:hover ~ .parent > .child {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-transition: .1s ease-in .9s;
transition: .1s ease-in .9s;
}
<div class="sibling"></div>
<div class="parent">
<div class="child"></div>
</div>
i am trying to get the background color to change on hover. Something like this.
I have tried various approaches but cannot get it to work, presumably it is the way my CSS and HTML is set up. I cannot figure out why it is not working, as it should be easy to implement
Please see code below.
CSS
.image-container {
position: relative;
}
.image-container .after {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: 100%;
height: 100%;
display: none;
color: #FFF;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, red 50%, black 50%);
-webkit-transition: background-position 1s;
-moz-transition: background-position 1s;
transition: background-position 1s;
}
.image-container .after p {
position: relative;
text-align: center;
font-size: 26px;
text-transform: uppercase;
font-weight: 300;
line-height: 300px;
height: 300px;
}
.image-container:hover .after {
display: block;
background: rgba(0,0,0,0.3);
background-position: 0 -100%;
}
[class*='col-'] {
float: left;
}
.col-1-3 {
width: 33.33%;
}
HTML
<div class="col-1-3 image-container">
<img class="portrait-image geysir" src="images/geysir.jpg">
<div class="after">GEYSIR</div>
</div>
Remove the background declaration on the hover. It's overriding all the other backgrounds you declared previously.
.image-container:hover .after {
display: block;
background-position: 0 -100%;
}
It should then work.
Based on the given fiddle, I would use a transparent .png image as a second overlapping element like that. Not sure if that's your intention...
.container{
position:relative;
}
.box {
width: 400px; height: 200px;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, red 50%, black 50%);
-webkit-transition: background-position 1s;
-moz-transition: background-position 1s;
transition: background-position 1s;
}
.box:hover {
background-position: 0 -100%;
}
.geysir{
position:absolute;
top:0px;
}
<div class="container">
<div class="box"></div>
<img class="portrait-image geysir" src="http://cdn.mysitemyway.com/etc-mysitemyway/icons/legacy-previews/icons-256/high-resolution-dark-blue-denim-jeans-icons-arrows/008776-high-resolution-dark-blue-denim-jeans-icon-arrows-hand-pointer1-right.png">
</div>
Do you want to have the background, including the text slide in from the top on hover? In which case you would be better transitioning a bottom move like this:
.image-container {
position: relative;
overflow: hidden;
}
.image-container .after {
position: absolute;
bottom: 100%;
margin: auto;
width: 100%;
height: 100%;
color: #fff;
background-color: black;
-webkit-transition: bottom 1s;
-moz-transition: bottom 1s;
transition: bottom 1s;
}
.image-container:hover .after {
bottom: 0;
}
Fiddle
If you're looking to have your text appear on a red background that shifts to black, try using a combination of the above with what you were using. Avoid using display: none/block as this stops the transistion from functioning.
.image-container {
position: relative;
overflow: hidden;
}
.image-container .after {
position: absolute;
bottom: 100%;
margin: auto;
width: 100%;
height: 100%;
color: #fff;
background-size: 100% 200%;
background-image: linear-gradient(to bottom, red 50%, black 50%);
-webkit-transition: background-position 2s;
-moz-transition: background-position 2s;
transition: background-position: 2s;
}
.image-container:hover .after {
bottom: 0;
background-position: 0 -100%;
}
Fiddle