NNseum
NNseum

Reputation: 31

Simple CSS spinner element wobbles while rotating

I've been trying to create a simple css spinner which is shown while my page is loading by using a pseudo element overlaying a div where content will be shown. It uses border-radius and transform: rotate() to achieve this effect but as you can see it wobbles strangely while rotating. The effect is more or less obvious depending on the screen size, zoom level and browser. I find it's most visible in MS Edge.

Example fiddle

.loading {
  width: 75vh;
  height: 100vh;
  margin: auto;
  background: white;
  position: relative;
}

.loading::after {
    border: 6vmin solid lightblue;
    border-top: 6vmin solid darkblue;
    position: absolute;
    margin-top: 5vmin;
    margin-left: 5vmin;
    width: 15vmin;
    height: 15vmin;
    content: "";
    border-radius: 50%;
    animation: spin .5s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
<div class="loading"></div>

Upvotes: 3

Views: 1817

Answers (3)

Corbin Mosher
Corbin Mosher

Reputation: 11

This issue was driving me crazy all day. I was able to solve it personally by making the ring thicker than desired and then masking over its inner and outer portions to hide the wobble from the viewer.

Solution. https://codepen.io/corbinmosher/pen/GRWmYjy

Solution with background coloring to help with understanding it. https://codepen.io/corbinmosher/pen/bGqWmEj

<div class="spinner__container">
  <div class="spinner__ring"></div>
  <div class="spinner__outline"></div>
</div>

.spinner__container {
  position: relative;
  width: 58px;
  height: 58px;
  
  background-color: white;
}

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

  width: calc(100% - 8px);
  height: calc(100% - 8px);
  border-radius: 50%;
}

.spinner__ring:before {
  position: absolute;
  top: -1px;
  left: -1px;

  width: calc(100% + 2px);
  height: calc(100% + 2px);

  border: 10px solid lightblue;
  border-top: 10px solid blue;
  box-sizing: border-box;
  content: '';
  border-radius: 50%;
  animation: rotate-spinner 1s linear infinite;
}

.spinner__ring:after {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  width: calc(100% - 8px);
  height: calc(100% - 8px);

  box-sizing: border-box;
  content: '';
  border-radius: 50%;

  background-color: white;
}

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

  width: calc(100% - 8px);
  height: calc(100% - 8px);
  border-radius: 50%;
  border: solid 2px white;
}

@keyframes rotate-spinner {
  0% {
    transform: rotate(405deg);
  }
  100% {
    transform: rotate(765deg);
  }
}

@-webkit-keyframes rotate-spinner {
  0% {
    transform: rotate(405deg);
  }
  100% {
    transform: rotate(765deg);
  }
}

Upvotes: 1

Kossi
Kossi

Reputation: 97

Changing the width and height to a pixel value seems to fix the issue. It may not be the best solution, but hey, it works.

To make this appropriate for all screen sizes, you need to use @media. In the bottom of the css I have added one that changes the size if the screen size is smaller than 700px just to show you how to do it, and if you want to change the numbers around or something, you at least know how @media can be used :)

Here is the code for changing the size depending on the screen-size of the users device.

@media (max-width: 700px){
  .loading::after {
    width: 100px;
    height: 100px;
  }
}

If you want to make it different on large screens too, just swap out "max-width: 700px" with "min-width: 1500px" or a value of your choice :)

http://jsfiddle.net/hfsqebsn/5/

Again, there are probably better ways, but this works :)

Edit: I think I may have changed around some other stuff in the fiddle I linked for testing purposes, so just beware of that :P

Upvotes: 0

Mauricio Machado
Mauricio Machado

Reputation: 643

There's some weird cut going on with the border-radius Change it to border-radius: 1000px and see what happens

Upvotes: 1

Related Questions