pagol
pagol

Reputation: 507

How to create animated rollover arrow animation

I want to make a rollover button like https://www.plantflags.com/en/

This websites buttons rollover effect. Example: if you rollover on button then the text should fade-out and an Arrow should come from the left and create. After the roll-out, the arrow goes to right side and fades-out and the text fades-in again.

Example: if you go to that website and roll-over that button, you'll understand.

if you go to that website and roll-over this button then you can understand

I've studied their code, the CSS I can understand but there are is a JS issue which I can't understand.

Can you figure out how I can make it like this type of rollover effect.

There html code like

<a href="#" class="promo__button" data-module="modules/AnimatedArrowButton" data-contact-button>Tell me more</a>

there data attribute modules/AnimatedArrowButton actually call js and create more span

Demo without effect https://jsfiddle.net/cyber007/78pshojd/

Upvotes: 13

Views: 3015

Answers (5)

Yonas Hailu
Yonas Hailu

Reputation: 853

I know it's too late but it might be interesting. I have used css only animation with after & before pseudo classes much used.

body {
  font-family: "Helvetica Neue", sans-serif;
  background: #f8f8f8;
}

.promo {
  color: #fff;
  text-align: center;
}

.promo__button {
  border: 1px solid #fff;
  display: inline-block;
  position: relative;
  margin-top: 1.5em;
  font-size: 24px;
  padding: 20px 50px;
  text-decoration: none;
  text-transform: uppercase;
  font-weight: 700;
  line-height: 1;
  letter-spacing: .025em;
  text-align: center;
  color: #fff;
  background: #E21710;
  overflow: hidden;
  transition: transform 0.5s cubic-bezier(0.77, 0, 0.175, 1);
  
}

.promo__button:after {
  content: '';
  position: absolute;
  display: block;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  background: #fff;
  transform: scaleY(0);
  transform-origin: bottom;
  transition: all 0.5s cubic-bezier(0.77, 0, 0.175, 1);
}

.text {
  transform: matrix(1, 0, 0, 1, 0, 0);
  display: block;
  transition: transform 0.5s cubic-bezier(0.77, 0, 0.175, 1);
}

.arrow {
  position: absolute;
  top: 50%;
  transform: translate(-300%, -50%);
  width: 80px;
  height: 1px;
  background: #E21710;
  display: inline-block;
  z-index: 1;
  visibility: hidden;
  opacity: 0;
  transition: all 0.5s cubic-bezier(0.77, 0, 0.175, 1);
}

.arrow:after,
.arrow:before {
  content: '';
  position: absolute;
  right: -3px;
  display: block;
  width: 20px;
  height: 1px;
  background: #E21710;
  z-index: 2;
}

.arrow:after {
  top: 7px;
  transform: rotate(-45deg);
}

.arrow:before {
  transform: rotate(45deg);
  top: -7px;
}

.promo__button:hover .text {
  transform: translateX(200%);
}

.promo__button:hover .arrow {
  visibility: visible;
  opacity: 1;
  transform: translate(-50%, -50%);
}
.promo__button:hover {
	box-shadow: 0 0 37px 10px rgba(0, 0, 0, 0.02); 
}
.promo__button:hover:after {
  transform: scaleY(1);
}
<div class="promo">
  <a href="#" class="promo__button" data-module="modules/AnimatedArrowButton" data-contact-button>
			<span class="text">Tell me more</span>
			<span class="arrow"></span>
  </a>

</div>

.

Upvotes: 0

James Zhang
James Zhang

Reputation: 101

I'm positive the button doesn't require javascript.

Here's the high level framework in just html and css: https://jsfiddle.net/gsvcaLrt/1/

button {
  background-color: red;
  border: none;
  padding: 1rem;
  overflow: hidden;
  position: relative;
}
.arrow {
  visibility: hidden;
  opacity: 0;
  position: absolute;
  transform: translateX(-30px);
  transition: 0.4s;
}
button:hover .arrow {
  visibility: visible;
  opacity: 1;
  transform: translateX(0px);
}

.text {
  visibility: visible;
  opacity: 1;
  transition: 0.4s;
  display: inline-block;
}
/* hide button on hover */
button:hover .text {
  visibility: hidden;
  opacity: 0;
  transform: translateX(30px);
}
<button>
  <span class="arrow">--></span>
  <span class="text">Hello</span>
</button>

You can add more detail to the different parts of animation sequence with css.

Upvotes: 3

Kalimah
Kalimah

Reputation: 11437

You can mix css and jQuery to achieve this effect (since you tagged your question with jQuery).

var timeout = null;
var transitionEnd = true;

jQuery('.line').on("mouseenter", function() {
  if (!transitionEnd)
    return;

  _this = jQuery(this);

  _this.addClass("hide-text");

  timeout = setTimeout(function() {
    _this.addClass("in");
  }, 300);

  transitionEnd = false;
}).on("mouseleave", function() {
  clearTimeout(timeout);

  jQuery(this).addClass("out").one("transitionend", function() {
    transitionEnd = true;
    jQuery(this).removeClass("hide-text out in");
  });


});
.line {
  background-color: red;
  border: 1px solid;
  border-radius: 5px;
  color: white;
  cursor: pointer;
  display: block;
  float: left;
  font-size: 25px;
  height: 70px;
  line-height: 70px;
  margin: 30px;
  overflow: hidden;
  position: relative;
  text-align: center;
  width: 200px;
}
.line::after {
  content: " ";
  border-top: 1px solid white;
  position: absolute;
  top: 50%;
  right: 100%;
  left: -150%;
  transition: left 0.5s, right 0.3s;
  opacity: 0;
}
.line::before {
  border-right: 1px solid white;
  border-top: 1px solid white;
  content: " ";
  height: 10px;
  position: absolute;
  right: 20%;
  top: calc(50% - 5px);
  transform: rotate(45deg) scale(0.2);
  transition: all 0.5s ease 0s;
  width: 10px;
  opacity: 0;
}
.line span,
.line.out span {
  opacity: 1;
  transition: 0.5s;
  transition-delay: 0.1s;
}
.line.hide-text span {
  opacity: 0;
}
.line.in::after {
  left: 20%;
  right: 20%;
  opacity: 1;
}
.line.in::before {
  transform: rotate(45deg) scale(1);
  opacity: 1;
}
.line.out::before {
  right: -100%;
  transition-delay: 0s;
}
.line.out::after {
  left: 100%;
  right: -150%;
  transition: left 0.3s, right 0.3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='line'>
  <span class='text'>Button Text</span>
</div>

Upvotes: 5

Serg Chernata
Serg Chernata

Reputation: 12400

Here's my first pass. I tried to keep extra markup to a minimum; the only addition is a span wrapping the text. Arrow is created via pseudo elements. It's purely decorative and wouldn't be semantic if constructed out of other elements, in my opinion.

<a href="#" class="promo__button">
  <span>Tell me more</span>
</a>

https://jsfiddle.net/6ewvbq75/

I tried my best to keep the code clean and commented. A few important bits:

  1. You'll notice that part of the animation plays on page load. It's a known issue, what you could do is apply the animation class on hover. This looks just as good but avoids the awkward animation of these buttons on page load: https://jsfiddle.net/b5sc9xrp/

  2. All of the animations are stored in keyframes at the end. on hover or on mouse over animation is applied with assignment to, for example .button:hover span directive. on mouse out is assigned within the standard declaration .button span which is a little counter-intuitive and thus worth mentioning. There is no :un-hover after all.

  3. forwards keyword in animation assignment means that the animation will only play forward and stop there. This is key. For example, when we slide the text to the right and fade it out we want it to stay on the last keyframe. Without forwards the animation would jump back to keyframe 1.

  4. I made the arrow elements 2 pixels in width. I think it looks better and less jumpy than the 1px version but it's an easy enough adjustment.

Let me know if you have any other questions. This was a fun little demo to build.

Upvotes: 0

Samuel Kirschner
Samuel Kirschner

Reputation: 1185

If you want a simple solution, I suggest using just css transition, with the exception of changing one class with javascript to have a different animation for fading in and out.

Take the following structure:

<a class="promo__button exit">
  <span class="arrowleft">
     <span>*the arrow that comes from the left*</span>
  </span>
  <span class="message">
     <span>*the text*</span>
  </span>
  <span class="arrowleft">
     <span>*the arrow that disappears to the right*</span>
  </span>
</a>

then in css you can have these 6 selectors:

.promo__button .message span {
  //the css for the text when it is visible
}

.promo__button:hover .message span {
  //the aditional css for the text when it is faded out
}

.promo__button .arrowleft span {
  //the css for the arrow before it came in from the left (invisible)
}

.promo__button:hover .arrowleft span {
  //the aditional css to make the arrow visible 
}

.promo__button .arrowright span {
  //the css for the arrow after it went away to the right side
}

.promo__button:hover .arrowright span {
  //the aditional css to make the arrow visible 
}

now add .promo__button * * { transition: left 0.2s, opacity, 0.2s} for all the values that changed from normal to hover

use two classes to hide the unwanted arrow animation:

.promo__button.enter .arrowright {display:none}
.promo__button.exit .arrowleft {display:none}

and use javascript to switch enter/exit onmouseenter

Upvotes: 0

Related Questions