ispiro
ispiro

Reputation: 27723

Set animation progress-percent by pure CSS

I want something like the snippet here where hovering over one element (A) changes another element (B). This link shows how to do it. That is not the problem.

However, what I want is to change the progress ("percent") of an animation that is on the targeted element (B). E.g. if the user hovers over A, I want the progress of B to change to 50%.

Is there a way to do that, i.e. to set the progress of an animation with CSS only?

If there's no general way but there is some way for keyframes that's fine too.

EDIT

If I wasn't clear, I want a CSS way to set the following % to 50 when a user hovers over "HERE".

@keyframes k {
  0% {
    background-color: red;
  }
  100% {
    background-color: blue;
  }
}

.a {
  height: 100px;
  width: 100px;
  animation: k 10s infinite;
}
<div class="a"></div>
<div>HERE</div>

Upvotes: 0

Views: 2216

Answers (2)

Jason
Jason

Reputation: 3485

You cannot set a specific animation keyframe, but you can rely on the :hover state to disable the animation and set the value yourself. The comments should explain the technique, but it primarily relies on and requires:

  1. CSS Custom Properties for calculation between colors, specifically hue.
  2. Flex Layout to allow the :hover event to affect the animation.
  3. hsl() because we want to calculate an 80% hue point between the two colors.
  4. calc() for doing the calculations.

The example you gave seems vague and likely doesn't capture the practical use case you need, but these techniques can be re-purposed to handle almost any transitory effect. I would highly recommend that your next SO question include an example you're actually working on.

/* animation from start hue to end */

@keyframes k {
  0% {
    background-color: hsl(var(--hue-start), 100%, 50%);
  }
  100% {
    background-color: hsl(var(--hue-end), 100%, 50%);
  }
}

.a {
  height: 100px;
  width: 100px;
  animation: k 10s infinite;
}


/* set css props to use to calculate 80% point */

.progress {
  /* shortest hue turns between red and blue */
  /* 360deg, 240deg would work too */
  --hue-start: 0deg;
  --hue-end: -120deg;
  --hue-diff: calc(var(--hue-end) - var(--hue-start));
}


/* In order to hook onto `HERE`'s `:hover`, we need it structurally before the animation */
.progress {
  display: flex;
  flex-direction: column;
}

.trigger {
  order: 2;
}

.a {
  order: 1;
}

.trigger:hover+.a {
  /* hard set background to 80% of the hue difference */
  animation: none;
  background-color: hsl(calc(var(--hue-start) + var(--hue-diff) * .8), 100%, 50%)
}
<div class="progress">
  <div class="trigger">HERE</div>
  <div class="a"></div>
</div>

Upvotes: 0

SK64_DEV
SK64_DEV

Reputation: 326

I suppose it's very simple to modify your code sample.

This is my result on CodePen

.flex-buttons{
  width:100%;
  display:flex;
  flex-wrap:wrap;
}

.flex-buttons button{
  flex:1;
  cursor:pointer;  
}

.progress {
  transition-property: all;
  transition-duration: 0.5s;
  transition-timing-function: cubic-bezier(0, 1, 0.1, 0.2, 0.7, 1);  
  min-height: 100%;
  min-width: 0%;
  width: 0%;
  background-color: #3e2a1a4f;
}

.flex-buttons button:nth-child(1):hover ~ .imgs .progress{
  min-width: 20%;
  width: 20%;
}

.flex-buttons button:nth-child(2):hover ~ .imgs .progress{
  min-width: 40%;
  width: 40%;
}

.flex-buttons button:nth-child(3):hover ~ .imgs .progress{
  min-width: 60%;
  width: 60%;
}

.flex-buttons button:nth-child(4):hover ~ .imgs .progress{
  min-width: 80%;
  width: 80%;
}

.flex-buttons button:nth-child(5):hover ~ .imgs .progress{
  min-width: 100%;
  width: 100%;
}

.imgs{
  order:-1;
  flex-basis:100%;
  height:100px;
  border:2px solid grey;
  position: repative;
}
<div class="flex-buttons">
    <button> Image 1 </button>
    <button> Image 2 </button>
    <button> Image 3 </button>
    <button> Image 4 </button>
    <button> Image 5 </button>
    <div class="imgs"><div class="progress"></div></div>
  </div>

Upvotes: 1

Related Questions