I\'m trying to create an overlay that overlays a page with a spinner in the middle. What\'s the simplest way to accomplish this? I only need to worry about IE 8 and above.
use a css3 class "spinner". It's more beautiful and you don't need .gif
.spinner {
position: absolute;
left: 50%;
top: 50%;
height:60px;
width:60px;
margin:0px auto;
-webkit-animation: rotation .6s infinite linear;
-moz-animation: rotation .6s infinite linear;
-o-animation: rotation .6s infinite linear;
animation: rotation .6s infinite linear;
border-left:6px solid rgba(0,174,239,.15);
border-right:6px solid rgba(0,174,239,.15);
border-bottom:6px solid rgba(0,174,239,.15);
border-top:6px solid rgba(0,174,239,.8);
border-radius:100%;
}
@-webkit-keyframes rotation {
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(359deg);}
}
@-moz-keyframes rotation {
from {-moz-transform: rotate(0deg);}
to {-moz-transform: rotate(359deg);}
}
@-o-keyframes rotation {
from {-o-transform: rotate(0deg);}
to {-o-transform: rotate(359deg);}
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(359deg);}
}
Exemple of what is looks like : http://jsbin.com/roqakuxebo/1/edit
You can find a lot of css spinners like this here : http://cssload.net/en/spinners/
#overlay {
position: fixed;
width: 100%;
height: 100%;
background: black url(spinner.gif) center center no-repeat;
opacity: .5;
}
it's better to use rgba color instead of opacity to prevent applying alpha to spinner image.
background: rgba(0,0,0,.5) url(spinner.gif) center center no-repeat;
As an update, for Angular 7, a very good example, loading plus http interceptor, here: https://nezhar.com/blog/create-a-loading-screen-for-angular-apps/.
For version 6, you need a small adjustment when you use Subject. You need to add the generic type.
loadingStatus: Subject<boolean> = new Subject();
I'm using angular material, so instead of a loading text, you can use mat-spinner.
<mat-spinner></mat-spinner>
Update: the code from the previous page will not complete work (regarding the interceptor part), but here you have the complete solution: https://github.com/nezhar/snypy-frontend
And as Miranda recommended into comments, here is also the solution:
The loading screen component:
loading-screen.component.ts
import { Component, ElementRef, ChangeDetectorRef, OnDestroy, AfterViewInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { LoadingScreenService } from '../services/loading-screen.service';
@Component({
selector: 'app-loading-screen',
templateUrl: './loading-screen.component.html',
styleUrls: ['./loading-screen.component.css']
})
export class LoadingScreenComponent implements AfterViewInit, OnDestroy {
loading: boolean = false;
loadingSubscription: Subscription;
constructor(
private loadingScreenService: LoadingScreenService,
private _elmRef: ElementRef,
private _changeDetectorRef: ChangeDetectorRef
) { }
ngAfterViewInit(): void {
this._elmRef.nativeElement.style.display = 'none';
this.loadingSubscription = this.loadingScreenService.loadingStatus.pipe().subscribe(
(status: boolean) => {
this._elmRef.nativeElement.style.display = status ? 'block' : 'none';
this._changeDetectorRef.detectChanges();
}
);
}
ngOnDestroy() {
console.log("inside destroy loading component");
this.loadingSubscription.unsubscribe();
}
}
loading-screen.component.html
<div id="overlay">
<mat-spinner class="content"></mat-spinner>
</div>
loading-screen.component.css
#overlay {
position: fixed; /* Sit on top of the page content */
display: block; /* Hidden by default */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(60, 138, 255, 0.1); /* Black background with opacity */
opacity: 0.5;
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
cursor: progress; /* Add a pointer on hover */
}
.content {
position: absolute;
top: 50%;
left: 50%;
font-size: 50px;
color: white;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
}
Don't forget to add the component to your root component. In my case, AppComponent
app.component.html
<app-loading-screen></app-loading-screen>
The service that will manage the component: loading-screen.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LoadingScreenService {
constructor() { }
private _loading: boolean = false;
loadingStatus: Subject<boolean> = new Subject();
get loading(): boolean {
console.log("get loading: " + this._loading);
return this._loading;
}
set loading(value) {
console.log("get loading: " + value);
this._loading = value;
this.loadingStatus.next(value);
}
startLoading() {
console.log("startLoading");
this.loading = true;
}
stopLoading() {
console.log("stopLoading");
this.loading = false;
}
}
Here is the http interceptor, which will show/hide the component, using the previous service.
loading-screen-interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { LoadingScreenService } from '../services/loading-screen.service';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
@Injectable()
export class LoadingScreenInterceptor implements HttpInterceptor {
activeRequests: number = 0;
constructor(
private loadingScreenService: LoadingScreenService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log("inside interceptor");
if (this.activeRequests === 0) {
this.loadingScreenService.startLoading();
}
this.activeRequests++;
return next.handle(request).pipe(
finalize(() => {
this.activeRequests--;
if (this.activeRequests === 0) {
this.loadingScreenService.stopLoading();
}
})
)
};
}
And in your app.module.ts, don't forget to config the interceptor
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: LoadingScreenInterceptor,
multi: true
}
]
Here is an Pure CSS endless spinner. Position absolute, to place the buttons on top of each other.
button {
position: absolute;
width: 150px;
font-size: 120%;
padding: 5px;
background: #B52519;
color: #EAEAEA;
border: none;
margin: 50px;
border-radius: 5px;
display: flex;
align-content: center;
justify-content: center;
transition: all 0.5s;
cursor: pointer;
}
#orderButton:hover {
color: #c8c8c8;
}
#orderLoading {
animation: rotation 1s infinite linear;
height: 20px;
width: 20px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 100%;
border: 2px solid;
border-style: outset;
color: #fff;
}
@keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
<button><div id="orderLoading"></div></button>
<button id="orderButton" onclick="this.style.visibility= 'hidden';">Order!</button>
And for a spinner like iOs I use this:
html:
<div class='spinner'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Css:
.spinner {
font-size: 30px;
position: relative;
display: inline-block;
width: 1em;
height: 1em;
}
.spinner div {
position: absolute;
left: 0.4629em;
bottom: 0;
width: 0.074em;
height: 0.2777em;
border-radius: 0.5em;
background-color: transparent;
-webkit-transform-origin: center -0.2222em;
-ms-transform-origin: center -0.2222em;
transform-origin: center -0.2222em;
-webkit-animation: spinner-fade 1s infinite linear;
animation: spinner-fade 1s infinite linear;
}
.spinner div:nth-child(1) {
-webkit-animation-delay: 0s;
animation-delay: 0s;
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
.spinner div:nth-child(2) {
-webkit-animation-delay: 0.083s;
animation-delay: 0.083s;
-webkit-transform: rotate(30deg);
-ms-transform: rotate(30deg);
transform: rotate(30deg);
}
.spinner div:nth-child(3) {
-webkit-animation-delay: 0.166s;
animation-delay: 0.166s;
-webkit-transform: rotate(60deg);
-ms-transform: rotate(60deg);
transform: rotate(60deg);
}
.spinner div:nth-child(4) {
-webkit-animation-delay: 0.249s;
animation-delay: 0.249s;
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.spinner div:nth-child(5) {
-webkit-animation-delay: 0.332s;
animation-delay: 0.332s;
-webkit-transform: rotate(120deg);
-ms-transform: rotate(120deg);
transform: rotate(120deg);
}
.spinner div:nth-child(6) {
-webkit-animation-delay: 0.415s;
animation-delay: 0.415s;
-webkit-transform: rotate(150deg);
-ms-transform: rotate(150deg);
transform: rotate(150deg);
}
.spinner div:nth-child(7) {
-webkit-animation-delay: 0.498s;
animation-delay: 0.498s;
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.spinner div:nth-child(8) {
-webkit-animation-delay: 0.581s;
animation-delay: 0.581s;
-webkit-transform: rotate(210deg);
-ms-transform: rotate(210deg);
transform: rotate(210deg);
}
.spinner div:nth-child(9) {
-webkit-animation-delay: 0.664s;
animation-delay: 0.664s;
-webkit-transform: rotate(240deg);
-ms-transform: rotate(240deg);
transform: rotate(240deg);
}
.spinner div:nth-child(10) {
-webkit-animation-delay: 0.747s;
animation-delay: 0.747s;
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.spinner div:nth-child(11) {
-webkit-animation-delay: 0.83s;
animation-delay: 0.83s;
-webkit-transform: rotate(300deg);
-ms-transform: rotate(300deg);
transform: rotate(300deg);
}
.spinner div:nth-child(12) {
-webkit-animation-delay: 0.913s;
animation-delay: 0.913s;
-webkit-transform: rotate(330deg);
-ms-transform: rotate(330deg);
transform: rotate(330deg);
}
@-webkit-keyframes spinner-fade {
0% {
background-color: #69717d;
}
100% {
background-color: transparent;
}
}
@keyframes spinner-fade {
0% {
background-color: #69717d;
}
100% {
background-color: transparent;
}
}
get from this website : https://365webresources.com/10-best-pure-css-loading-spinners-front-end-developers/
Here is simple overlay div without using any gif, This can be applied over another div.
<style>
.loader {
position: relative;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 70px;
height: 70px;
left:50%;
top:50%;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
}
#overlay{
position: absolute;
top:0px;
left:0px;
width: 100%;
height: 100%;
background: black;
opacity: .5;
}
.container{
position:relative;
height: 300px;
width: 200px;
border:1px solid
}
/* Safari */
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
<h2>How To Create A Loader</h2>
<div class="container">
<h3>Overlay over this div</h3>
<div id="overlay">
<div class="loader"></div>
</div>
<div>