454

Currently, I have this code:

@-webkit-keyframes blinker {
  from { opacity: 1.0; }
  to { opacity: 0.0; }
}

.waitingForConnection {
  -webkit-animation-name: blinker;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: cubic-bezier(.5, 0, 1, 1);
  -webkit-animation-duration: 1.7s;
}

It blinks, but it only blinks in "one direction". I mean, it only fades out, and then it appears back with opacity: 1.0, then again fades out, appears again, and so on...

I would like it to fade out, and then "raise" from this fade back again to opacity: 1.0. Is that possible?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ojek
  • 9,680
  • 21
  • 71
  • 110
  • 163
    No offense, if he wants to blink his text, he wants to blink his text. It doesn't matter what year it is. The most innovative people in the world are those who don't live by rules. Quite the opposite, they usually break them and next, everyone copies them. I guess Apple is a great example. So is Mackie etc etc. I'd feel better if people just keep their opinions for themselves and just answer the question to the point :-) As said, no offense. Sounds a little harsh but I don't want to provoke not offend anyone. No hard feelings. ;-) – Lawrence May 01 '15 at 19:17
  • 2
    Possible duplicate of [Imitating a blink tag with CSS3 animations](http://stackoverflow.com/questions/13955163/imitating-a-blink-tag-with-css3-animations) – Michael Freidgeim Feb 09 '16 at 20:27
  • Possible duplicate of [Using CSS for fade-in effect on page load](https://stackoverflow.com/questions/11679567/using-css-for-fade-in-effect-on-page-load) – zloctb Sep 30 '17 at 03:59

14 Answers14

981

You are first setting opacity: 1; and then you are ending it on 0, so it starts from 0% and ends on 100%, so instead just set opacity to 0 at 50% and the rest will take care of itself.

Demo

.blink_me {
  animation: blinker 1s linear infinite;
}

@keyframes blinker {
  50% {
    opacity: 0;
  }
}
<div class="blink_me">BLINK ME</div>

Here, I am setting the animation duration to be 1 second, and then I am setting the timing to linear. That means it will be constant throughout. Last, I am using infinite. That means it will go on and on.

Note: If this doesn't work for you, use browser prefixes like -webkit, -moz and so on as required for animation and @keyframes. You can refer to my detailed code here


As commented, this won't work on older versions of Internet Explorer, and for that you need to use jQuery or JavaScript...

(function blink() {
  $('.blink_me').fadeOut(500).fadeIn(500, blink);
})();

Thanks to Alnitak for suggesting a better approach.

Demo (Blinker using jQuery)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
  • 11
    Just noticed that this, applied to one text element, consumes ridiculous amount of CPU on my computer using firefox. Beware. – Alex Sep 10 '14 at 09:00
  • please define *"older versions of Internet Explorer"*, it doesn't appear to work in `9` –  Dec 02 '14 at 23:05
  • @JarrodRoberson You should use sites like http://caniuse.com to check the browser support for the properties am using in this code, I think that is least a user can do by himself. – Mr. Alien Feb 08 '15 at 06:57
  • 2
    best answer for being the most easy to understand solution avialable – elad silver May 17 '15 at 14:27
  • @Alnitak I would appreciate if you explain *bad idea* – Mr. Alien Oct 27 '15 at 12:07
  • 5
    @Mr.Alien there's no synchronisation between the two - the fades will take a bit longer than the timer (and timers aren't reliable anyway) and eventually you'll likely end up with unbounded queue of animations queued up on the element. The correct approach would be to do without the timer and "recursively" call `blinker` as the completion callback to the `.fadeIn` call. – Alnitak Oct 27 '15 at 13:04
  • @Alnitak makes sense, will update my answer soon. Thanks for explaining. Appreciated. – Mr. Alien Oct 28 '15 at 02:35
  • 3
    @Mr.Alien also the whole thing could just be an IIFE - this one line will do the whole thing including initial invocation: `(function blink() { $('.blink_me').fadeOut(500).fadeIn(500, blink); })();` – Alnitak Oct 28 '15 at 09:43
  • 3
    `step-end` instead of `linear` was what I wanted. – Alex S Nov 13 '18 at 02:24
  • any ideas on this one https://stackoverflow.com/questions/67542758/how-to-blink-two-emogies-at-the-same-time-replacing-one-for-another ? – Sergino May 15 '21 at 02:23
111

The best way to get a pure "100% on, 100% off" blink, like the old <blink> is like this:

.blink {
  animation: blinker 1s step-start infinite;
}

@keyframes blinker {
  50% {
    opacity: 0;
  }
}
<div class="blink">BLINK</div>
Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • 9
    The only true "blink" solution. And also works with `color` property etc. Other stuff are workarounds or "fade" animations. – Martin Schneider Feb 04 '18 at 12:48
  • any ideas on this one https://stackoverflow.com/questions/67542758/how-to-blink-two-emogies-at-the-same-time-replacing-one-for-another ? – Sergino May 15 '21 at 02:23
82

Use the alternate value for animation-direction (and you don't need to add any keframes this way).

alternate

The animation should reverse direction each cycle. When playing in reverse, the animation steps are performed backward. In addition, timing functions are also reversed; for example, an ease-in animation is replaced with an ease-out animation when played in reverse. The count to determinate if it is an even or an odd iteration starts at one.

CSS:

.waitingForConnection {
  animation: blinker 1.7s cubic-bezier(.5, 0, 1, 1) infinite alternate;  
}
@keyframes blinker { to { opacity: 0; } }

I've removed the from keyframe. If it's missing, it gets generated from the value you've set for the animated property (opacity in this case) on the element, or if you haven't set it (and you haven't in this case), from the default value (which is 1 for opacity).

And please don't use just the WebKit version. Add the unprefixed one after it as well. If you just want to write less code, use the shorthand.

.waitingForConnection {
  animation: blinker 1.7s cubic-bezier(.5, 0, 1, 1) infinite alternate;  
}
@keyframes blinker { to { opacity: 0; } }

.waitingForConnection2 {
  animation: blinker2 0.6s cubic-bezier(1, 0, 0, 1) infinite alternate;  
}
@keyframes blinker2 { to { opacity: 0; } }

.waitingForConnection3 {
  animation: blinker3 1s ease-in-out infinite alternate;  
}
@keyframes blinker3 { to { opacity: 0; } }
<div class="waitingForConnection">X</div>
<div class="waitingForConnection2">Y</div>
<div class="waitingForConnection3">Z</div>
squarecandy
  • 4,894
  • 3
  • 34
  • 45
Ana
  • 35,599
  • 6
  • 80
  • 131
24

If you want smooth animations, try this.

    .blink {
        animation: blinker 1s infinite;
    }
      
    @keyframes blinker {
        from { opacity: 1.0; }
        50% { opacity: 0.5; }
        to { opacity: 1.0; }
    }
    <span class="blink">I am blinking</span>
Gass
  • 7,536
  • 3
  • 37
  • 41
Jaseem Abbas
  • 5,028
  • 6
  • 48
  • 73
18

Alternatively if you do not want a gradual transition between show and hide (e.g. a blinking text cursor) you could use something like:

/* Also use prefixes with @keyframes and animation to support current browsers */
@keyframes blinker {  
  from { visibility: visible }
  to { visibility: hidden }

  /* Alternatively you can do this:  
  0% { visibility: visible; }
  50% { visibility: hidden; }
  100% { visibility: visible; }
  if you don't want to use `alternate` */
}
.cursor {
  animation: blinker steps(1) 500ms infinite alternate;
}

Every 1s .cursor will go from visible to hidden.

If CSS animation is not supported (e.g. in some versions of Safari) you can fallback to this simple JS interval:

(function(){
  var show = 'visible'; // state var toggled by interval
  var time = 500; // milliseconds between each interval

  setInterval(function() {
    // Toggle our visible state on each interval
    show = (show === 'hidden') ? 'visible' : 'hidden';

    // Get the cursor elements
    var cursors = document.getElementsByClassName('cursor');
    // We could do this outside the interval callback,
    // but then it wouldn't be kept in sync with the DOM

    // Loop through the cursor elements and update them to the current state
    for (var i = 0; i < cursors.length; i++) {
      cursors[i].style.visibility = show;
    }
  }, time);
})()

This simple JavaScript is actually very fast and in many cases may even be a better default than the CSS. It's worth noting that it is lots of DOM calls that make JS animations slow (e.g. JQuery's $.animate()).

It also has the second advantage that if you add .cursor elements later, they will still animate at exactly the same time as other .cursors since the state is shared, this is impossible with CSS as far as I am aware.

MattSturgeon
  • 452
  • 4
  • 11
  • This works well EXCEPT for iOS Safari. Any ideas how to get it working on Safari? – Joe Orost Jul 20 '15 at 07:44
  • @JoeOrost I've included a JS alternative for browsers that don't support CSS animations. In my opinion it may actually be a better solution generally! – MattSturgeon Nov 13 '15 at 00:33
17
@-webkit-keyframes blinker {  
  0% { opacity: 1.0; }
  50% { opacity: 0.0; }
  100% { opacity: 1.0; }
}

@-webkit-keyframes blinker {  
  0% { opacity: 1.0; }
  50% { opacity: 0.0; }
  100% { opacity: 1.0; }
}

.blink {
  width: 10px;
  height: 10px;
  border-radius: 10px;
  animation: blinker 2s linear infinite;
  background-color: red;
  margin-right: 5px;
}

.content {
  display: flex;
  flex-direction: row;
  align-items: center;
}
<div class="content">
  <i class="blink"></i>
  LIVE
</div>
Abraham
  • 8,525
  • 5
  • 47
  • 53
onon15
  • 3,620
  • 1
  • 18
  • 22
14

I don't know why but animating only the visibility property is not working on any browser.

What you can do is animate the opacity property in such a way that the browser doesn't have enough frames to fade in or out the text.

Example:

span {
  opacity: 0;
  animation: blinking 1s linear infinite;
}

@keyframes blinking {
  from,
  49.9% {
    opacity: 0;
  }
  50%,
  to {
    opacity: 1;
  }
}
<span>I'm blinking text</span>
josketres
  • 3,329
  • 1
  • 26
  • 23
12

My solution:

.blink {
 animation: blinkMe 2s linear infinite;
}
@keyframes blinkMe {
 0% {
  opacity: 0;
 }
 50% {
  opacity: 1;
 }
 100% {
  opacity: 0;
 }
}
<p class="blink">Blink</p>

I use blinkMe for the name of the animation, 2s for the duration, linear for the timing, and infinite so that it repeats forever.

We need to use JavaScript and jQuery for older browsers as they don’t support animation and/or @keyframes:

$(document).ready(function() {
 window.setInterval(function() {
  $(".blink").fadeIn(1000).fadeOut(1000);
 }, 2000)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<p class="blink">Blink</p>

If you want to make a blink effect that works just like the blink tag, this will work:

.blink {
 animation: blink 0.5s step-start infinite;
}
@keyframes blink {
 0% {
  opacity: 1;
 }
 50% {
  opacity: 0;
 }
 100% {
  opacity: 1;
 }
}
<p class="blink">Blink</p>

Change the durations if you want to adjust the speed.

UserName Name
  • 267
  • 2
  • 3
9

Change duration and opacity to suit.

.blink_text { 
    -webkit-animation-name: blinker;
    -webkit-animation-duration: 3s;
    -webkit-animation-timing-function: linear;
    -webkit-animation-iteration-count: infinite;
    -moz-animation-name: blinker;
    -moz-animation-duration: 3s;
    -moz-animation-timing-function: linear;
    -moz-animation-iteration-count: infinite;
    animation-name: blinker;
    animation-duration: 3s;
    animation-timing-function: linear; 
    animation-iteration-count: infinite; color: red; 
} 

@-moz-keyframes blinker {
    0% { opacity: 1.0; }
    50% { opacity: 0.3; }
    100% { opacity: 1.0; } 
}

@-webkit-keyframes blinker { 
    0% { opacity: 1.0; }
    50% { opacity: 0.3; }
    100% { opacity: 1.0; } 
} 

@keyframes blinker { 
    0% { opacity: 1.0; } 
    50% { opacity: 0.3; } 
    100% { opacity: 1.0; } 
}
Tunaki
  • 132,869
  • 46
  • 340
  • 423
3

Late but wanted to add a new one with more keyframes ... here is an example on CodePen since there was an issue with the built-in code snippets:

.block{
  display:inline-block;
  padding:30px 50px;
  background:#000;
}
.flash-me {
  color:#fff;
  font-size:40px;
  -webkit-animation: flash linear 1.7s infinite;
  animation: flash linear 1.7s infinite;
}

@-webkit-keyframes flash {
  0% { opacity: 0; } 
  80% { opacity: 1; color:#fff; } 
  83% { opacity: 0; color:#fff; } 
  86% { opacity: 1; color:#fff;}  
  89% { opacity: 0} 
  92% { opacity: 1; color:#fff;} 
  95% { opacity: 0; color:#fff;}
  100% { opacity: 1; color:#fff;}
}
@keyframes flash {
  0% { opacity: 0; } 
  80% { opacity: 1; color:#fff; } 
  83% { opacity: 0; color:#fff; } 
  86% { opacity: 1; color:#fff;}  
  89% { opacity: 0} 
  92% { opacity: 1; color:#fff;} 
  95% { opacity: 0; color:#fff;}
  100% { opacity: 1; color:#fff;}
}
<span class="block">
  <span class="flash-me">Flash Me Hard</span>
</span>
br3t
  • 1,646
  • 2
  • 20
  • 27
hsobhy
  • 1,493
  • 2
  • 21
  • 35
3

enter image description here

.neon {
  font-size: 20px;
  color: #fff;
  text-shadow: 0 0 8px yellow;
  animation: blinker 6s;
  animation-iteration-count: 1;
}
@keyframes blinker {
  0% {
    opacity: 0.2;
  }
  19% {
    opacity: 0.2;
  }
  20% {
    opacity: 1;
  }
  21% {
    opacity: 1;
  }
  22% {
    opacity: 0.2;
  }
  23% {
    opacity: 0.2;
  }
  36% {
    opacity: 0.2;
  }
  40% {
    opacity: 1;
  }
  41% {
    opacity: 0;
  }
  42% {
    opacity: 1;
  }
  43% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 1;
  }
}

I used font-family: "Quicksand", sans-serif;

This is the import of the font (goes on the top of the style.css)

@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@300&display=swap");
Gass
  • 7,536
  • 3
  • 37
  • 41
2

This is good example for everyone. Try it once

.blinking_live {
    height: 15px;
    width: 15px;
    border-radius: 15px;
    background: #58C03D;
    animation: blink-live 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}

@keyframes blink-live{

    0% { opacity: 1.0; }
    50% { opacity: 0.0; }
    100% { opacity: 1.0; }
}


<div class="blinking_live"></div>
Ahsan Khan
  • 678
  • 9
  • 12
1
<style>
    .class1{
        height:100px;
        line-height:100px;
        color:white;
        font-family:Bauhaus 93;
        padding:25px;
        background-color:#2a9fd4;
        border:outset blue;
        border-radius:25px;
        box-shadow:10px 10px green;
        font-size:45px;
    }
     .class2{
        height:100px;
        line-height:100px;
        color:white;
        font-family:Bauhaus 93;
        padding:25px;
        background-color:green;
        border:outset blue;
        border-radius:25px;
        box-shadow:10px 10px green;
        font-size:65px;
    }
</style>
<script src="jquery-3.js"></script>
<script>
    $(document).ready(function () {
        $('#div1').addClass('class1');
        var flag = true;

        function blink() {
            if(flag)
            {
                $("#div1").addClass('class2');
                flag = false;
            }
            else
            { 
                if ($('#div1').hasClass('class2'))
                    $('#div1').removeClass('class2').addClass('class1');
                flag = true;
            }
        }
        window.setInterval(blink, 1000);
    });
</script>
Shahaji
  • 61
  • 5
1

It works for me by using class=blink for the respective element(s)

Simple JS Code

// Blink
      setInterval(function()
        {

        setTimeout(function()
        {

        //$(".blink").css("color","rgba(0,0,0,0.1)"); // If you want simply black/white blink of text
        $(".blink").css("visibility","hidden"); // This is for Visibility of the element  


        },900);


        //$(".blink").css("color","rgba(0,0,0,1)");  // If you want simply black/white blink of text
        $(".blink").css("visibility","visible");  // This is for Visibility of the element

        },1000);
Alpha
  • 321
  • 6
  • 16