Creating a transition on a :before or :after element - css

I'm using CSS3 transitions to make some fade in/out transitions on a link.
I've used the transition to make the background colour fade to nothing, but I'd like to make two "borders" fade in and also move down. The borders are not actually borders because I cannot use that to position it correctly, so I've used a psuedo element of a :before: with a 3px height to create a border effect.
My question is, is it possible to use CSS3 transitions (e.g fade in the colour or move the border down 3px)
li:hover:before{content: "";height: 3px;background-color: black;width: 100%;position: absolute;left: 0;top: -3px;}
li:hover:after{content: "";height: 3px;background-color: black;width: 100%;position: absolute;left: 0;bottom: -3px;}
http://jsfiddle.net/akxrv4zf/1/

You simply need to style the :after and :before psuedo-elements WITHOUT the :hover psuedo event.
You need styles like: li:before AND styles like: li:hover:before. Try something like below.
/* Menu link animations */
li {
transition: background-color 0.3s ease-in;
position: relative;
}
li:hover {
background-color: transparent;
}
li:before {
content: "";
height: 3px;
background-color: transparent;
width: 100%;
position: absolute;
left: 0;
top: -10px;
transition: background 0.5s, top 0.5s;
}
li:after {
content: "";
height: 3px;
background-color: transparent;
width: 100%;
position: absolute;
left: 0;
bottom: -10px;
transition: background 0.5s, bottom 0.5s;
}
li:hover:before {
content: "";
height: 3px;
background-color: black;
width: 100%;
position: absolute;
left: 0;
top: -3px;
}
li:hover:after {
content: "";
height: 3px;
background-color: black;
width: 100%;
position: absolute;
left: 0;
bottom: -3px;
}
/* General Link settings */
li {
cursor: pointer;
margin: 25px 2% 0 2%;
display: inline-block;
width: 15%;
text-align: center;
padding: 5px;
background-color: #E7DAC6;
<li>Example</li>

Yes, you can style :after and :before elements just like any other element, including transitions.
Checkout this jsFiddle.

You will have to make give content to the :after,:before elements, so you can animate from one state to another.
If they do not have content from the start they are treated as display:none and you cannot apply transitions to elements whose state starts from display:none
li:before, li:after {
content:"";
height: 3px;
background-color: transparent;
width: 100%;
position: absolute;
left: 0;
transition:all 0.3s ease-in;
}
li:before {top: 0px;}
li:after {bottom: 0px;}
li:hover:before {top: -3px;}
li:hover:after {bottom: -3px;}
li:hover:after, li:hover:before {
background-color:black;
}
Demo at http://jsfiddle.net/gaby/vmL8qt6k/1

Related

animating :after pseudo element does not work

I am new to coding, I have tried various solutions from similar questions asked, but nothing seems to work.
I have the following problem:
I made a breadcrumb, including various divs with :before and :after elements - shaping them like connected arrows.
The problem is, I made an animation for the breadcrumb element to fade-in-down. However, no matter in what combination I tried -> The :after element does not animate properly, or at all.
It kinda just pops up after :before and the parent div .breadcrumb have finished sliding in. Can anybody help me here, or has anyone maybe have aa clue?
... I have tried animating the :after element separatly, with transition, with animation-delay etc...nothing seems to work...everything slides in fine from top, excep the :after element, which just pops up ugly after the animation from my ".breadcrumb" is finished.
<div class="breadcrumb_wrapper">
Lasermaschinen
Serien
Unterserien
Produkt
.breadcrumb_wrapper {
position: fixed;
display: flex;
align-items: center;
width: 100%;
height: auto;
margin-top: 120px;
text-align: center;
}
.breadcrumb_element {
padding: 0 2rem 0 2rem;
width: auto;
line-height: 32px;
min-height: 32px;
max-height: 32px;
background: var(--Breadcrumb-gradient);
position: relative;
text-align: center;
margin-left: 0.5rem;
color: var(--nav-text-color-and-general-background);
cursor: pointer;
text-decoration: none;
animation: fade-in-down 0.5s ease-in-out;
}
.breadcrumb_element:before {
content: "";
position: absolute;
top: 4.69px;
left: -11.32px;
width: 22.427px;
height: 22.427px;
background: var(--nav-text-color-and-general-background);
transform: rotate(45deg);
z-index: 1;
border-top: 1px solid #F0F0F0;
border-right: 1px solid #F0F0F0;
border-top-right-radius: 5px;
}
.breadcrumb_element:after {
content: "";
position: absolute;
top: 4.69px;
right: -11.6px;
width: 22.427px;
height: 22.427px;
background: var(--Breadcrumb-arrow-gradient);
transform: rotate(45deg);
z-index: 2;
border-top-right-radius: 5px;
animation: fade-in-down 0.5s ease-in-out;
}
#keyframes fade-in-down {
0% {
opacity: 0;
transform: translateY(-20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
Without seeing your HTML code I just had to take a guess at how you need this but here is an example with the after pseudo element coming in from the top and sitting on top of the before pseudo. Hope this helps you get what you are looking for. You can have it come in from any direction that you want.
ul {
list-style: none;
display: flex;
overflow: hidden;
}
li {
margin-left: 20px;
margin-right: 20px;
position: relative;
}
li::before {
content: '';
width: 20px;
height: 20px;
background-color: green;
position: absolute;
right: -25px;
}
li::after {
content: '';
width: 20px;
height: 20px;
background-color: red;
position: absolute;
right: -25px;
top: -100px;
transition: all 1s;
}
li:hover:after {
top: 0;
}
<ul>
<li>Menu Item 1</li>
<li>Menu Item 2</li>
</ul>

CSS transition background color without a hover

I have a div called time-box. Sometimes I will also include an additional class called countdown. If countdown is added then I would like to use a CSS transition effect so the background changes to be red over the course of 60 seconds. In other words, each second that passes the red background gets a little wider until eventually all of the green background has gone.
I have found similar posts here but they all seem to relate to hover
Here is a fiddle
https://jsfiddle.net/e2vbheew/
I don't know a "simple" way to get what you want going from left to right, but there's a way you can create it using before and after pseudoelements. The key here is I'm going to create a :before pseudoelement that has the new background that transitions across, and an :after pseudoelement that replicates the content and puts it on top of the before, so it's still visible. This required putting the content in an attribute on the div so I could reference it in the 'content' of the pseudoelement. If you had more complex content inside, you could probably do away with the :after and simply give the internal content position and z-index to make sure it's visible. Here's the resulting CSS
.time-box {
height: 27px;
text-align: center;
background-color: #25E57B;
font-size:2rem;
padding:0px;
font-size:1.2rem;
text-transform:uppercase;
padding:3px 5px 3px 5px;;
font-weight:600;
height:auto;
position: relative;
}
.time-box:before {
background-color: red;
position: absolute;
left:0;
top: 0;
height: 100%;
width: 0;
content: " ";
transition: width 60s ease;
}
.countdown:after {
content: attr(data-content);
width: 100%;
text-align: center;
height: 100%;
position: absolute;
left: 0;
top: center;
z-index: 1;
}
.countdown:before {
width:100%;
}
And updated fiddle: https://jsfiddle.net/tunzwqd7/2/
Using CSS animation property...
.time-box {
height: 27px;
text-align: center;
background-color: #25E57B;
font-size: 2rem;
padding: 0px;
font-size: 1.2rem;
text-transform: uppercase;
padding: 3px 5px 3px 5px;
font-weight: 600;
height: auto;
position: relative;
z-index: 1;
}
.time-box.countdown:before {
content: '';
width: 0;
height: 100%;
display: block;
position: absolute;
top: 0;
left: 0;
background: red;
animation: countdown 60s forwards;
z-index: -1;
}
#keyframes countdown {
0% {
width: 0;
}
100% {
width: 100%;
}
}
<div class="time-box">
12:00
</div>
<div class="time-box countdown">
<span>12:00</span>
</div>
You would need to add a maximum and a little more math to make the 100% divisible by 60, but this should get you on the right track. Currently this code updates every second and adds 1% to the progress bar width with each iteration.
var time = 0;
var bar = document.querySelector('.countdown .progress-bar');
window.setInterval(function(){
time++;
bar.style.width = time+"%";
}, 1000);
.time-box {
height: 27px;
text-align: center;
background-color: #25E57B;
font-size:2rem;
padding:0px;
font-size:1.2rem;
text-transform:uppercase;
padding:3px 5px 3px 5px;;
font-weight:600;
height:auto;
position: relative;
}
.progress-bar {
display: none;
}
.countdown .progress-bar {
display: block;
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: red;
width: 0%;
z-index: 1;
transition: all 0.3s ease-out;
}
.countdown p {
z-index: 2;
position: relative;
}
<div class="time-box">
<p>12:00</p>
<div class="progress-bar"></div>
</div>
<div class="time-box countdown">
<p>12:00</p>
<div class="progress-bar"></div>
</div>

bottom-border hover transition

Can any one tell me how to do a border-bottom hover effect from bottom to top?
Src: http://www.sony.com/electronics/playstation
Here is a simple sample using the pseudo element ::after
The advantage using this in favor of the border-bottom, it will not move the element up and down
a {
position: relative;
padding: 10px 20px;
}
a::after {
content: ' ';
position: absolute;
left: 0;
bottom: -5px;
width: 100%;
height: 0;
background: blue;
transition: height 0.3s;
}
a:hover::after {
height: 5px;
transition: height 0.3s;
}
a + a::after {
content: ' ';
position: absolute;
left: 0;
bottom: -5px;
width: 0;
height: 5px;
background: blue;
transition: width 0.3s;
}
a + a:hover::after {
width: 100%;
transition: width 0.3s;
}
<a> Hover me </a> <a> Hover me 2 </a>

Underline from left to right on hover in and out [duplicate]

This question already has answers here:
Hover effect : expand bottom border
(9 answers)
Closed 6 years ago.
With the following code I get an hover underline effect from left to right.
.underline {
display: inline;
position: relative;
overflow: hidden;
}
.underline:after {
content: "";
position: absolute;
z-index: -1;
left: 0;
right: 100%;
bottom: -5px;
background: #000;
height: 4px;
transition-property: left right;
transition-duration: 0.3s;
transition-timing-function: ease-out;
}
.underline:hover:after,
.underline:focus:after,
.underline:active:after {
right: 0;
}
<p>hello, link is underline
</p>
When you're not in hover, the :after element returns to the left, the initial state. Is there any way that the :after goes to the right and not to the left when you leave the hover?
You can try animating the width instead of the right/left properties.
.underline {
display: inline;
position: relative;
overflow: hidden;
}
.underline:after {
content: "";
position: absolute;
z-index: -1;
right: 0;
width: 0;
bottom: -5px;
background: #000;
height: 4px;
transition-property: width;
transition-duration: 0.3s;
transition-timing-function: ease-out;
}
.underline:hover:after,
.underline:focus:after,
.underline:active:after {
left: 0;
right: auto;
width: 100%;
}
<p>hello, link is underline</p>
See this fiddle for a working example: https://jsfiddle.net/1gyksyoa/
Based on this answer : Expand bottom border on hover you can change the transform-origin property on hover to achieve the "hover out"
effect you are looking for. Here is an example :
.expand{
position:relative;
text-decoration:none;
display:inline-block;
}
.expand:after {
display:block;
content: '';
border-bottom: solid 3px #000;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
transform-origin:100% 50%
}
.expand:hover:after {
transform: scaleX(1);
transform-origin:0 50%;
}
Here is some dummy text expand

After/Before pseudo elements in < IE11

I created a pseudo element which transitions width to reveal a second pseudo element below of a different colour. It's working in all browsers except IE where the pseudo element becomes 100% of the page width when hovering off the element. What gives?
<span>Hello world</span>
<style>
span{
position: relative;
font-size: 64px;
}
span:before, span:after{
position: absolute;
content: "";
left: 0;
bottom: -3px;
width: 100%;
height: 5px;
transition: all 1s ease;
}
span:before{
background: green;
}
span:after{
background: red;
}
span:hover:after{
width: 0;
}
</style>
https://jsfiddle.net/mmbgLf51/
Can't say (yet) why that happens but here is a workaround, where I use the right property instead.
Update
Giving the span inline-block (or block) does as well solve it, which would mean that the inline element for some reason gets pushed by the pseudo content, and most likely qualifies as a bug ..
.. or normal IE behavior :)
Sample 1 (using right)
span{
position: relative;
font-size: 64px;
}
span:before, span:after{
position: absolute;
content: " ";
left: 0;
bottom: -3px;
right: 0;
height: 5px;
transition: all 1s ease;
}
span:before{
background: green;
}
span:after{
background: red;
}
span:hover:after{
right: 100%;
}
<span>Hello world</span>
Sample 2 (using display: inline-block)
span{
display: inline-block;
position: relative;
font-size: 64px;
}
span:before, span:after{
position: absolute;
content: "";
left: 0;
bottom: -3px;
width: 100%;
height: 5px;
transition: all 1s ease;
}
span:before{
background: green;
}
span:after{
background: red;
}
span:hover:after{
width: 0;
}
<span>Hello world</span>

Resources