1

So I'm trying to implement a loader that spins in the middle of the screen I have used transform:translate earlier do this ex:

position: absolute;
left:50%;
top:50%;
transform:  translate(-50%,-50%);

I tried to implement something similar but instead of getting centered the top left appears to be in the center. Here's my code HTML

<section class="waitwrapper" v-else>
<div class="loader"></div>
</section>

CSS

.waitwrapper{
background-color: #455879;
position: relative;
width: 98vw;
height: 97vh;
}
.loader{
border: 16px solid  #f3f3f3;
border-top: 16px solid #455879; /* w3schools loader */
border-radius: 50%;
width: 20%;
aspect-ratio:1;
animation: spin 2s linear infinite;
position: absolute;
left:50%;
top:50%;
transform:  translate(-50%,-50%);

}

@keyframes spin {

0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
Zoltán Balogh
  • 188
  • 2
  • 11
  • 1
    PS: avoid using w3schools as your source of knowledge. They are not a community driven website. They employ bad coding habits. Their examples are full of outdated and bug-prone code. And sell irrelevant certificates. Still at this date. – Roko C. Buljan Dec 29 '21 at 16:37

3 Answers3

0

Don't use transform. Use display: flex; on the parent and margin: auto; on the spinner element — to center it both horizontally and vertically.

See the code comments for the needed changes:

/* Quick reset */ * {margin: 0; box-sizing: border-box; }

.loader-wrapper {
  background-color: #455879;
  position: fixed; /* why relative? use fixed! Should cover the page? */
  z-index: 9999;   /* overlay other elements */
  width: 100vw;
  height: 100vh;
  display: flex; /* use display flex */
}

.loader {
  height: 20%;   /* use height instead of width */
  aspect-ratio: 1;
  margin: auto;  /* center inside the flex parent */
  border: 10px solid #f3f3f3;
  border-top-color: transparent; /* use transparent instead */
  border-radius: 50%;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  to { transform: rotate(1turn); }
}
<section class="loader-wrapper">
  <div class="loader"></div>
</section>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • as for using relative i havent really given that much tought as i have been manually setting the viewport to be the same for the whole webpage to limit scrolling and things randomly changing sizes but i suspect that fixed does everything i want. As for the flex soloution is there really no way to it using transform? as thats what i have been using and my grader seems overly obsessed with uniform code, im also very intrested in the way you reformated the whole spin and it looks way neater to me. thank you for the reply! –  Dec 29 '21 at 16:42
  • @SebastianSjöberg that's what I use when in need to create something similar. – Roko C. Buljan Dec 29 '21 at 16:43
0

One trusted way to centralize one item is to use display: flex with justify-content: center and align-items: center in the parent element.

*, *::before, *::after{
  box-sizing:border-box;
}

.waitwrapper{
  background-color: #455879;
  width: 98vw;
  height: 97vh;
  display:flex;
  justify-content:center;
  align-items:center
}

.loader{
  border: 16px solid  #f3f3f3;
  border-top: 16px solid #455879; /* w3schools loader */
  border-radius: 50%;
  width: 20%;
  aspect-ratio:1;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
<section class="waitwrapper" v-else>
  <div class="loader"></div>
</section>

But why your code doesn't work very well? I must tell you when you change transform property in your animation actually you overwrite it. And because of it transform: translate(-50%, -50%);, doesn't work enymore. For solve that problem you can use below solution

.waitwrapper{
  background-color: #455879;
  position: relative;
  width: 98vw;
  height: 97vh;
}
.loader{
  border: 16px solid  #f3f3f3;
  border-top: 16px solid #455879; /* w3schools loader */
  border-radius: 50%;
  width: 20%;
  aspect-ratio:1;
  animation: spin 2s linear infinite;
  position: absolute;
  left:50%;
  top:50%;
/* transform:translate(-50%,-50%); */
}

@keyframes spin {
  0%{
    transform: translate(-50%, -50%) rotate(0deg);
  }
  100% {
    transform: translate(-50%, -50%)  rotate(360deg);
  }
}
<section class="waitwrapper" v-else>
  <div class="loader"></div>
</section>
Zahra Mirzaei
  • 729
  • 3
  • 7
0

Here is one of the ways how to center position-absolute element with width set:

position: absolute;
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
left: 0;
right: 0;
top:0;
bottom:0;
width:20%;

Complete snippet:

.waitwrapper{
background-color: #455879;
position: relative;
width: 98vw;
height: 97vh;
}
.loader{
border: 16px solid  #f3f3f3;
border-top: 16px solid #455879; /* w3schools loader */
border-radius: 50%;
aspect-ratio:1;
animation: spin 2s linear infinite;

position: absolute;
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
left: 0;
right: 0;
top:0;
bottom:0;
width:20%;

}

@keyframes spin {

0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    
    <section class="waitwrapper" v-else>
        <div class="loader"></div>
    </section>

</body>
</html>
trz
  • 23
  • 8