<div id="chooser">
</div>

<div class="fill">
  <div class="clock
              hour-style-pill
              hour-text-style-large
              hour-display-style-all
              minute-style-line
              minute-display-style-fine-2
              minute-text-style-outside
              hand-style-hollow
              " id="utility-clock">
    <div class="centre">
        <div class="dynamic"></div>
        <div class="expand round circle-1"></div>
        <div class="anchor hour">
            <div class="element thin-hand"></div>
            <div class="element fat-hand"></div>
        </div>
        <div class="anchor minute">
            <div class="element thin-hand"></div>
            <div class="element fat-hand minute-hand"></div>
        </div>
        <div class="anchor second">
            <div class="element second-hand second-hand-front"></div>
            <div class="element second-hand second-hand-back"></div>
        </div>
        <div class="expand round circle-2"></div>
    </div>
  </div>
</div>
body {
  background: black;
}

.fill {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.clock {
  position: absolute;
  opacity: 1;
  left: 50%;
  top: 50%;
}

.centre {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
}

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

.anchor {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
}

.element {
  position: absolute;
  top: 0;
  left: 0;
}

.round {
  border-radius: 296px;
}

.circle-1 {
  width: 6px;
  height: 6px;
  border: 3px solid white;
}

.circle-2 {
  width: 4px;
  height: 4px;
  border: 2px solid #FA9F22;
}

.second {
  transform: rotate(180deg);
}

.minute {
  transform: rotate(54deg);
}

.second-hand {
  width: 2px;
  background: #FA9F22;
}
.second-hand-front {
  width: 2px;
  height: 137px;
  background: #FA9F22;
  transform: translate(-50%,-100%) translateY(-3px);
}
.second-hand-back {
  width: 2px;
  height: 21px;
  background: #FA9F22;
  opacity: 1;
  transform: translate(-50%,-100%) translateY(24px);
}

.hour {
  transform: rotate(304.5deg);
}

.thin-hand {
  width: 4px;
  height: 50px;
  background: white;
  transform: translate(-50%,-100%) translateY(-5px);
}

.fat-hand {
  box-sizing: border-box;
  width: 10px;
  height: 57px;
  border-radius: 10px;
  background: white;
  transform: translate(-50%,-100%) translateY(-18px);
}

.minute-hand {
  height: 112px;
}


.minute-line {
  background: white;
  width: 1px;
  height: 9px;
  transform: translate(-50%,-100%) translateY(-131px);
  opacity: 0.34;
}
.major.minute-line {
  opacity: 0.5;
}
.minute-text {
  font: 12px Avenir Next, Helvetica;
  color: white;
  top: -135px;
}

.hour-pill {
  background: white;
  width: 6px;
  height: 35px;
  border-radius: 10px;
  transform: translate(-50%,-100%) translateY(-85px);
  opacity: 0.75;
}
.hour-text {
  font: 40px Hei, Helvetica;
  color: white;
  top: -105px;
}
.hour-10 .content {
  padding-left: 0.4ex;
}
.hour-11 .content {
  padding-left: 0.25ex;
}

/* Now, customizations! */


/* Customize: hour */
.hour-style-text .hour-pill {
  opacity: 0;
}
.hour-style-pill .hour-text {
  opacity: 0;
}
.hour-style-text-quarters .hour-1.hour-text,
.hour-style-text-quarters .hour-2.hour-text,
.hour-style-text-quarters .hour-3.hour-pill,
.hour-style-text-quarters .hour-4.hour-text,
.hour-style-text-quarters .hour-5.hour-text,
.hour-style-text-quarters .hour-6.hour-pill,
.hour-style-text-quarters .hour-7.hour-text,
.hour-style-text-quarters .hour-8.hour-text,
.hour-style-text-quarters .hour-9.hour-pill,
.hour-style-text-quarters .hour-10.hour-text,
.hour-style-text-quarters .hour-11.hour-text,
.hour-style-text-quarters .hour-12.hour-pill {
  opacity: 0;
}

/* Customize: hour-text */
.hour-text-style-small .hour-text {
  font-size: 24px;
  top: -113px;
}

/* Customize: hour-display */
.hour-display-style-quarters .hour-1,
.hour-display-style-quarters .hour-2,
.hour-display-style-quarters .hour-4,
.hour-display-style-quarters .hour-5,
.hour-display-style-quarters .hour-7,
.hour-display-style-quarters .hour-8,
.hour-display-style-quarters .hour-10,
.hour-display-style-quarters .hour-11 {
  opacity: 0;
}
.hour-display-style-none .hour-item {
  opacity: 0;
}

/* Customize: minute */
.minute-style-dot .minute-line {
  width: 6px;
  height: 6px;
  transform: translate(-50%,-100%) translateY(-134px);
  border-radius: 6px;
  opacity: 0.75;
}
.minute-style-dot .part.minute-line,
.minute-style-dot.hour-style-pill .major.minute-line {
  opacity: 0;
}
.minute-style-dot .hour-pill {
  transform: translate(-50%,-100%) translateY(-100px);
  height: 40px;
}

/* Customize: minute text */
.minute-text-style-inside .major.minute-line {
  opacity: 0;
}
.minute-text-style-outside .minute-text {
  top: -152px;
  font-size: 14px;
}
.minute-text-style-none .minute-text {
  opacity: 0;
}

/* Customize: Minute display */
.minute-style-line.minute-display-style-fine-2 .whole.minute-line,
.minute-style-line.minute-display-style-fine-2 .major.minute-line {
  height: 13px;
  transform: translate(-50%,-100%) translateY(-127px);
}
.minute-style-line.minute-display-style-fine-2 .part.minute-line {
  height: 8px;
  transform: translate(-50%,-100%) translateY(-132px);
}
.minute-display-style-coarse .part.minute-line {
  opacity: 0;
}
.minute-display-style-major .part.minute-line,
.minute-display-style-major .whole.minute-line {
  opacity: 0;
}
.minute-display-style-none .part.minute-line,
.minute-display-style-none .major.major.minute-line,
.minute-display-style-none .whole.minute-line {
  opacity: 0;
}

/* Customize: hand */
.hand-style-hollow .fat-hand {
  background: black;
  border: 2px solid white;
}

/* Customizer */
#chooser {
  font: 10px Verdana, sans-serif;
  position: absolute;
  top: 4px;
  left: 4px;
  color: white;
  z-index: 1;
  opacity: 0.5;
}
#chooser div {
  cursor: pointer;
}
#chooser div:hover {
  background: rgba(255,255,255,0.4);
}

var clock = document.querySelector('#utility-clock')
utilityClock(clock)
autoResize(clock, 295 + 32)

choose(clock, [
  ['hour', ['text', 'text-quarters', 'pill']],
  ['hour-text', ['large', 'small']],
  ['hour-display', ['all', 'quarters', 'none']],
  ['minute', ['line', 'dot']],
  ['minute-display', ['fine', 'fine-2', 'coarse', 'major', 'none']],
  ['minute-text', ['inside', 'outside', 'none']],
  ['hand', ['normal', 'hollow']]
])

function utilityClock(container) {
  
  var dynamic = container.querySelector('.dynamic')
  var hourElement = container.querySelector('.hour')
  var minuteElement = container.querySelector('.minute')
  var secondElement = container.querySelector('.second')
  
  var div = function(className, innerHTML) {
    var element = document.createElement('div')
    element.className = className
    element.innerHTML = innerHTML || ''
    return element
  }

  var append = function(element) {
    return {
      to: function(parent) {
        parent.appendChild(element)
        return append(parent)
      }
    }
  }

  var anchor = function(element, rotation) {
    var anchor = div('anchor')
    rotate(anchor, rotation)
    append(element).to(anchor).to(dynamic)
  }
  
  var minute = function(n) {
    var klass = n % 5 == 0 ? 'major' : n % 1 == 0 ? 'whole' : 'part'
    var line = div('element minute-line ' + klass)
    anchor(line, n)
    if (n % 5 == 0) {
      var text = div('anchor minute-text ' + klass)
      var content = div('expand content', (n < 10 ? '0' : '') + n)
      append(content).to(text)
      rotate(text, -n)
      anchor(text, n)
    }
  }

  var hour = function(n) {
    var klass = 'hour-item hour-' + n
    var line = div('element hour-pill ' + klass)
    anchor(line, n * 5)
    var text = div('anchor hour-text ' + klass)
    var content = div('expand content', n)
    append(content).to(text)
    rotate(text, -n * 5)
    anchor(text, n * 5)
    return
  }

  var position = function(element, phase, r) {
    var theta = phase * 2 * Math.PI
    element.style.top = (-r * Math.cos(theta)).toFixed(1) + 'px'
    element.style.left = (r * Math.sin(theta)).toFixed(1) + 'px'
  }

  var rotate = function(element, second) {
    element.style.transform = element.style.webkitTransform = 'rotate(' + (second * 6) + 'deg)'
  }

  var animate = function() {
    var now = new Date()
    var time = now.getHours() * 3600 +
                now.getMinutes() * 60 +
                now.getSeconds() * 1 +
                now.getMilliseconds() / 1000
    rotate(secondElement, time)
    rotate(minuteElement, time / 60)
    rotate(hourElement, time / 60 / 12)
    requestAnimationFrame(animate)
  }

  for (var i = 1 / 4; i <= 60; i += 1 / 4) minute(i)
  for (var i = 1; i <= 12; i ++) hour(i)

  animate()

}

function autoResize(element, nativeSize) {
  var update = function() {
    var parent = element.offsetParent
    var scale = Math.min(parent.offsetWidth, parent.offsetHeight) / nativeSize
    element.style.transform = element.style.webkitTransform = 'scale(' + scale.toFixed(3) + ')'
  }
  update()
  window.addEventListener('resize', update)
}

function choose(clock, items) {
  var chooser = document.querySelector('#chooser')
  items.forEach(function(item) {
    var name = item[0]
    var styles = item[1]
    var element = document.createElement('div')
    element.addEventListener('click', click, false)
    update()
    chooser.appendChild(element)
    function update() {
      element.innerHTML = name + '-style-<b>' + getValue() + '</b>'
    }
    function klass(c) {
      return name + '-style-' + c
    }
    function getValue() {
      for (var i = 0; i < styles.length; i ++) {
        if (clock.classList.contains(klass(styles[i]))) return styles[i]
      }
    }
    function click(e) {
      for (var i = 0; i < styles.length; i ++) {
        if (clock.classList.contains(klass(styles[i]))) {
          clock.classList.remove(klass(styles[i]))
          clock.classList.add(klass(styles[(i + 1) % styles.length]))
          break
        }
      }
      update()
      e.preventDefault()
    }
  })
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.