<div id="clock">
  <ul class="hours">
    <li>
      <span>
        1
      </span>
    </li>
    <li>
      <span>
        2
      </span>
    </li>
    <li>
      <span>
        3
      </span>
    </li>
    <li>
      <span>
        4
      </span>
    </li>
    <li>
      <span>
        5
      </span>
    </li>
    <li>
      <span>
        6
      </span>
    </li>
    <li>
      <span>
        7
      </span>
    </li>
    <li>
      <span>
        8
      </span>
    </li>
    <li>
      <span>
        9
      </span>
    </li>
    <li>
      <span>
        10
      </span>
    </li>
    <li>
      <span>
        11
      </span>
    </li>
    <li>
      <span>
        12
      </span>
    </li>
  </ul>

  <div class="hr-wrapper">
    <div class="hand hr"></div>
  </div>
  <div class="min-wrapper">
    <div class="hand min"></div>
  </div>
  <div class="sec-wrapper">
    <div class="hand sec"></div>
  </div>
</div>
body {
  background: rgb(13, 186, 230);
  color: #333;
  margin-top: 50px;
  font-family: Helvetica, sans-serif;
}

#clock ul {
  list-style: none;
  top: 0;
  margin: 0;
  padding: 0;
  position: absolute;
  text-align: center;
}

#clock li {
  position: absolute;
  transform-origin: 50% 100%;
  height: 160px;
}

.hours {
  left: 120px;
  font-size: 23.3333333333px;
  letter-spacing: -1.6px;
  line-height: 45px;
}
.hours li {
  width: 80px;
}
.hours span {
  display: block;
}
.hours li:nth-of-type(1) {
  transform: rotate(30deg);
}
.hours li:nth-of-type(1) span {
  transform: rotate(-30deg);
}
.hours li:nth-of-type(2) {
  transform: rotate(60deg);
}
.hours li:nth-of-type(2) span {
  transform: rotate(-60deg);
}
.hours li:nth-of-type(3) {
  transform: rotate(90deg);
}
.hours li:nth-of-type(3) span {
  transform: rotate(-90deg);
}
.hours li:nth-of-type(4) {
  transform: rotate(120deg);
}
.hours li:nth-of-type(4) span {
  transform: rotate(-120deg);
}
.hours li:nth-of-type(5) {
  transform: rotate(150deg);
}
.hours li:nth-of-type(5) span {
  transform: rotate(-150deg);
}
.hours li:nth-of-type(6) {
  transform: rotate(180deg);
}
.hours li:nth-of-type(6) span {
  transform: rotate(-180deg);
}
.hours li:nth-of-type(7) {
  transform: rotate(210deg);
}
.hours li:nth-of-type(7) span {
  transform: rotate(-210deg);
}
.hours li:nth-of-type(8) {
  transform: rotate(240deg);
}
.hours li:nth-of-type(8) span {
  transform: rotate(-240deg);
}
.hours li:nth-of-type(9) {
  transform: rotate(270deg);
}
.hours li:nth-of-type(9) span {
  transform: rotate(-270deg);
}
.hours li:nth-of-type(10) {
  transform: rotate(300deg);
}
.hours li:nth-of-type(10) span {
  transform: rotate(-300deg);
}
.hours li:nth-of-type(11) {
  transform: rotate(330deg);
}
.hours li:nth-of-type(11) span {
  transform: rotate(-330deg);
}
.hours li:nth-of-type(12) {
  transform: rotate(360deg);
}
.hours li:nth-of-type(12) span {
  transform: rotate(-360deg);
}

#clock {
  background: #fff;
  border: 15px solid #222;
  border-radius: 50%;
  position: relative;
  width: 320px;
  height: 320px;
  margin: auto;
}

/* JavaScript pre-rotates these wrappers instead of the hands when getting the time at load. If it pre-rotates the hands, then the hands will not perform 1 turn at their normal speeds. */
.hr-wrapper,
.min-wrapper,
.sec-wrapper {
  position: absolute;
  width: 320px;
  height: 320px;
}

.hand {
  position: absolute;
  bottom: 50%;
  transform-origin: 50% 100%;
}

.hr {
  background: #222;
  left: 152px;
  width: 13px;
  height: 105px;
  border-radius: 10px;
  animation: rotateHand 43200s linear infinite;
}
.hr:after {
  background: #222;
  border-radius: 50%;
  content: "";
  display: block;
  position: absolute;
  bottom: -8px;
  width: 13px;
  height: 16px;
}

.min {
  background: #222;
  left: 155px;
  width: 9px;
  height: 125px;
  border-radius: 8px;
  animation: rotateHand 3600s linear infinite;
}
.min:after {
  background: #222;
  border-radius: 50%;
  content: "";
  display: block;
  position: absolute;
  bottom: -8px;
  width: 9px;
  height: 16px;
}

.sec {
  background: #d00;
  left: 156.5px;
  width: 5px;
  height: 132px;
  border-radius: 8px;
  animation: rotateHand 60s linear infinite;
}
.sec:after {
  background: #d00;
  border-radius: 50%;
  content: "";
  display: block;
  position: absolute;
  bottom: -3.5px;
  width: 5px;
  height: 7px;
}

@keyframes rotateHand {
  to {
    transform: rotate(1turn);
  }
}
// get current time
var dateInfo = new Date();
var hr =
    dateInfo.getHours() > 12 ? dateInfo.getHours() - 12 : dateInfo.getHours(),
  min = dateInfo.getMinutes(),
  sec = dateInfo.getSeconds(),
  milsec = dateInfo.getMilliseconds();

/*
1 hr = 30°, 1 min = 6°, 1 sec = 6°, 1 millisec = 0.36°
Even though we can calculate the proper angles of the hour, minute, and second hands, we can determine more accurately where the hands are between the current and next ticks. For example, if it is 6:30, we know that the hour hand is at least 180°, yet it should be between the 6 and 7. To get that, we divide the angle of the current minute by 12 ((30 * 6°) / 12) and add the result (15) to 180. Therefore, the hour hand should be at 195°.
*/
var hrAngle = hr * 30 + (min * 6) / 12,
  minAngle = min * 6 + (sec * 6) / 60,
  secAngle = sec * 6 + (milsec * 0.36) / 1000;

// set initial angles of the hand wrappers
function setAngle(wrapper, angle) {
  document.querySelector("." + wrapper).style.transform =
    "rotate(" + angle + "deg)";
}
setAngle("hr-wrapper", hrAngle);
setAngle("min-wrapper", minAngle);
setAngle("sec-wrapper", secAngle);

External CSS

  1. https://codepen.io/wolkanca/pen/wvgOPWb

External JavaScript

  1. https://codepen.io/wolkanca/pen/wvgOPWb