skip to Main Content

Based on this answer, I managed to put an image as my icon appearing inside an INPUT control at its right edge. If I use a GIF that rotates, I’m all set. I only need to set the class on my control and it is "progressing".

input.busy {
  background-image: url(...);
  ...
}

However… Now, I want to control the pace of the rotation, so I need to actually animate the image. I can do that as shown in this blog, which works for many, but not all, elements. And my INPUT is one of the unfortunate exceptions.

div::after {
  content: "this shows";
  background-image: url(...);
}

input::after {
  content: "this shows not";
  background-image: url(...);
}

How can I rotate (in fact, animate the rotation) of an image (let’s say PNG) that will reside at the rightmost edge of an INPUT tag?

2

Answers


  1. To animate anything in after you can simply use

    .loading::after{
      content:'';
      display:inline-block;
      width:50px;
      height:50px;
      background-image:url('https://picsum.photos/id/63/50/50');
     }
     .loading.rotate::after{
       animation: rotation 2s infinite linear;
     }
     @keyframes rotation {
       from {
         transform: rotate(0deg);
       }
       to {
         transform: rotate(359deg);
       }
    }
    

    And use, e.g.

    <div (click)="toogle=!toogle" class="loading" [class.rotate]="toogle">
      here
    </div>
    

    But the problem is when we use an input. I don’t know if there’re a better solution but always we can create a directive

    @Directive({
      selector: '[pending]',
      standalone: true,
      exportAs: 'child',
    })
    export class InputPending implements OnInit {
      div = this.render.createElement('div');
      @Input('pending') set _(value: boolean) {
        if (value) {
          this.render.insertBefore(
            this.elementRef.nativeElement.parentElement,
            this.div,
            this.render.nextSibling(this.elementRef.nativeElement)
          );
        } else
          this.render.removeChild(
            this.elementRef.nativeElement.parentElement,
            this.div
          );
      }
      constructor(private elementRef: ElementRef, private render: Renderer2) {}
      ngOnInit() {
        this.render.setAttribute(this.div, 'class', 'pendding');
        this.render.setStyle(
          this.div,
          'width',
          this.elementRef.nativeElement.offsetHeight + 'px'
        );
        this.render.setStyle(
          this.div,
          'height',
          this.elementRef.nativeElement.offsetHeight + 'px'
        );
      }
    }
    

    And we use like

    <input [pending]="toogle">
    

    the .css

    input ~ .pendding{
      background-image: url("https://picsum.photos/id/237/50/50");
      display:inline-block;
      margin-bottom:-6px;
      margin-left:2px;
      animation: rotation 2s linear infinite
     }
     @keyframes rotation {
      from {
       transform: rotate(0deg);
      }
      to {
       transform: rotate(359deg);
      }
    }
    

    the stackblitz

    Login or Signup to reply.
  2. I would use a container containing an image and an input. Put the image on top of the input and add a .loading class to the container whenever you want to show the animated image.

    There is no need to use a GIF.

    If you’re going to use this setup in several places, I suggest making a custom element out of it.

    .input-container {
      display: inline-grid;
      place-items: center end;
    }
    
    .input-container > * {
      grid-row: 1;
      grid-column: 1;
    }
    
    .input-container > img {
      display: none;
      border-radius: 50%;
      animation:spin 4s linear infinite;
    }
    
    .input-container.loading > img {
      display: inline-block;
    }
    
    
    @keyframes spin { 
      100% { 
        transform:rotate(360deg); 
      } 
    }
    <div class="loading input-container">
      <input />
      <img src="https://picsum.photos/id/200/20">
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search