Reputation: 31
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.
.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
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
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
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