I suddenly have this idea: Can I use pure CSS to create a loading indicator (image)? Then I have this:

Loading…

Here is a YouTube clip if you can see the above stuff normally.

1   Complete code

1.1   HTML

<div class="loading-image-wrapper">
  <div class="loading-image-container" id="lic-1">
    <div class="loading-image">
      <div class="loading-image">
        <div class="loading-image">
          <div class="loading-image">
            <div class="loading-image">
              <div class="loading-image">
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="message">Loading...</div>
</div>

1.2   CSS

@-webkit-keyframes 'rotation' {
 from {-webkit-transform: rotate(0deg);}
 to {-webkit-transform: rotate(359deg);}
}
div.loading-image-container {
  -webkit-animation-duration: 5s;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
  -webkit-animation-direction: normal;
}
div.loading-image-wrapper {
  border: 1px solid black;
  border-radius: 5px;
  -moz-border-radius: 5px
  -webkit-border-radius: 5px
  box-shadow: #000 0 0 5px;
  -moz-box-shadow: #000 0 0 5px;
  -webkit-box-shadow: #000 0 0 5px;
  padding-top: 51px;
  width: 128px;
  margin: 0 auto;
}
div.loading-image-container,
div.loading-image {
  width: 0px;
  height: 0px;
  margin: 0 auto;
}
div.loading-image-container {
  border: 1px solid transparent;
}
div.loading-image {
  margin-left: 0;
  margin-top: -72px;
  position: relative;
  top: 0;
  left: 0;
  width: 72px;
  height: 72px;
  -webkit-transform: rotate(-60deg);
  -moz-transform: rotate(-60deg);
  opacity: 0.5;
}
div.loading-image-container > div.loading-image{
  margin-left: -36px;
  margin-top: -36px;
  -webkit-transform: rotate(0deg);
  -moz-transform: rotate(0deg);
  opacity: 1;
}
div.loading-image:before {
  color: #000;
  content: "\2501";
  display: block;
  font-family: Arial;
  font-size: 36px;
  width: 72px;
  height: 72px;
}
div.loading-image-wrapper div.message {
  font-family: Arial;
  font-size: 24px;
  margin-top: 51px;
  text-align: center;
}

2   Explanation

Basically, it has structure like

<div class="loading-image-wrapper">
  <div class="loading-image-container">
    <div class="loading-image">
      <div class="loading-image">

div.loading-image represents each component of the loading indicator. Because of CSS and the cascading power, we use the following CSS to rotate and fade out one level by one level:

div.loading-image {
  -webkit-transform: rotate(-60deg);
  -moz-transform: rotate(-60deg);
  opacity: 0.5;
}

In this case, we have two div.loading-image, you can use any amount your like. The content of each div.loading-image is using pseudo element :before, so we don’t have to manually input them into each div.loading-image.

div.loading-image:before {
  color: #000;
  content: "━";
  display: block;
  font-family: Arial;
  font-size: 36px;
  width: 72px;
  height: 72px;
}

div.loading-image-container is the one being rotated, we use @-webkit-keyframes to make this animation never stop.

@-webkit-keyframes 'rotation' {
 from {-webkit-transform: rotate(0deg);}
 to {-webkit-transform: rotate(359deg);}
}
div.loading-image-container {
  -webkit-animation-duration: 5s;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
  -webkit-animation-direction: normal;
}

div.loading-image-container rotates clockwise since it’s from 0 degree to 359 degree, this direction is what we usually see. So you may notice that rotate(-60deg) indicates that div.loading-image are placed counterclockwise, it generates first item in 100% opacity, then second in 50% opacity, and so on.

If you want the loading indicator to rotate counterclockwise, switch the contents of from() and to(), then make div.loading-image rotate 60 degree.

The other thing is rotation reference point. You must make first div.loading-image to stay at center of div.loading-image-container, which is that little green dot in the following figure:

3   Conclusion

This is just for fun because it’s not so practical. The reasons are: 1) Not all current stable browsers support all CSS features used in this example, and this would cause strange screen; 2) the performance isn’t good, on my Core 2 Duo 1.833 GHz, Chromium 5.0.375.9 on Linux, it utilizes around 18% processing power. There is another way to do with external image, the <canvas> but I haven’t tried that.