AI CSS Animations

Glass Clock Widget

An iOS style world clock widget: four analog dials, two for day and two for night, on a frosted card over drifting color. Second hands sweep in sync and the other hands turn at true speed.

Also known as: glassmorphism clock css, css analog clock widget, ios world clock widget.

  • CUP -8h
  • NYC -5h
  • LON Local
  • PAR +1h

HTML

<div class="gls-glass-clock-widget">
  <span class="gls-glass-clock-widget-orb gls-glass-clock-widget-orb-a" aria-hidden="true"></span>
  <span class="gls-glass-clock-widget-orb gls-glass-clock-widget-orb-b" aria-hidden="true"></span>
  <ul class="gls-glass-clock-widget-card" aria-label="World clock">
    <li class="gls-glass-clock-widget-city gls-glass-clock-widget-night">
      <span class="gls-glass-clock-widget-dial" aria-hidden="true"><i class="gls-glass-clock-widget-hour"></i><i class="gls-glass-clock-widget-min"></i><i class="gls-glass-clock-widget-sec"></i></span>
      <b>CUP</b>
      <small>-8h</small>
    </li>
    <li class="gls-glass-clock-widget-city gls-glass-clock-widget-night">
      <span class="gls-glass-clock-widget-dial" aria-hidden="true"><i class="gls-glass-clock-widget-hour"></i><i class="gls-glass-clock-widget-min"></i><i class="gls-glass-clock-widget-sec"></i></span>
      <b>NYC</b>
      <small>-5h</small>
    </li>
    <li class="gls-glass-clock-widget-city">
      <span class="gls-glass-clock-widget-dial" aria-hidden="true"><i class="gls-glass-clock-widget-hour"></i><i class="gls-glass-clock-widget-min"></i><i class="gls-glass-clock-widget-sec"></i></span>
      <b>LON</b>
      <small>Local</small>
    </li>
    <li class="gls-glass-clock-widget-city">
      <span class="gls-glass-clock-widget-dial" aria-hidden="true"><i class="gls-glass-clock-widget-hour"></i><i class="gls-glass-clock-widget-min"></i><i class="gls-glass-clock-widget-sec"></i></span>
      <b>PAR</b>
      <small>+1h</small>
    </li>
  </ul>
</div>

CSS

.gls-glass-clock-widget {
  --c: var(--gls-color, #3b82f6);
  font-size: var(--gls-size, 16px);
  position: relative;
  display: grid;
  place-items: center;
  width: 22em;
  height: 12em;
  border-radius: 1.25em;
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(150deg, color-mix(in srgb, var(--c) 50%, #0f172a), color-mix(in srgb, var(--c) 30%, #312e81));
  color: #fff;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.3;
}
.gls-glass-clock-widget-orb {
  position: absolute;
  z-index: -1;
  border-radius: 50%;
}
.gls-glass-clock-widget-orb-a {
  left: 1.6em;
  top: 0.3em;
  width: 7em;
  height: 7em;
  background: linear-gradient(135deg, color-mix(in srgb, var(--c) 40%, #fff), var(--c));
  animation: gls-glass-clock-widget-drift-a 9s ease-in-out infinite alternate;
}
.gls-glass-clock-widget-orb-b {
  right: 1.8em;
  bottom: 0.2em;
  width: 6em;
  height: 6em;
  background: linear-gradient(135deg, #fdba74, #ec4899);
  animation: gls-glass-clock-widget-drift-b 10s ease-in-out infinite alternate;
}
.gls-glass-clock-widget-card {
  --m: 9;
  display: flex;
  gap: 0.95em;
  margin: 0;
  padding: 0.85em 1.05em 0.7em;
  border-radius: 1.3em;
  list-style: none;
  background: color-mix(in srgb, #fff 16%, transparent);
  -webkit-backdrop-filter: blur(0.9em) saturate(1.5);
  backdrop-filter: blur(0.9em) saturate(1.5);
  border: 1px solid color-mix(in srgb, #fff 45%, transparent);
  box-shadow: 0 0.5em 1.5em -0.5em rgb(0 0 0 / 0.35), inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
}
.gls-glass-clock-widget-city {
  display: grid;
  justify-items: center;
  line-height: 1.25;
}
.gls-glass-clock-widget-city:nth-child(1) { --h: 2; }
.gls-glass-clock-widget-city:nth-child(2) { --h: 5; }
.gls-glass-clock-widget-city:nth-child(3) { --h: 10; }
.gls-glass-clock-widget-city:nth-child(4) { --h: 11; }
.gls-glass-clock-widget-city b { font-size: 0.6em; font-weight: 700; letter-spacing: 0.05em; }
.gls-glass-clock-widget-city small { font-size: 0.5em; font-weight: 600; opacity: 0.75; }
.gls-glass-clock-widget-dial {
  position: relative;
  width: 3.3em;
  height: 3.3em;
  margin-bottom: 0.4em;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.9);
  color: #111827;
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.6), 0 0.35em 0.8em -0.35em rgb(0 0 0 / 0.45);
  transition: scale 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.gls-glass-clock-widget-night .gls-glass-clock-widget-dial {
  background: rgb(15 23 42 / 0.6);
  color: #fff;
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.25), inset 0 1px 0 rgb(255 255 255 / 0.3), 0 0.35em 0.8em -0.35em rgb(0 0 0 / 0.5);
}
.gls-glass-clock-widget-city:hover .gls-glass-clock-widget-dial { scale: 1.08; }
/* twelve hour ticks: a conic gradient masked to a ring */
.gls-glass-clock-widget-dial::before {
  content: "";
  position: absolute;
  inset: 0.2em;
  border-radius: 50%;
  background: repeating-conic-gradient(from -2deg, currentColor 0 4deg, transparent 4deg 30deg);
  -webkit-mask: radial-gradient(closest-side, transparent 78%, #000 80%);
  mask: radial-gradient(closest-side, transparent 78%, #000 80%);
  opacity: 0.55;
}
/* center cap, painted over the hands */
.gls-glass-clock-widget-dial::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0.26em;
  height: 0.26em;
  margin: -0.13em 0 0 -0.13em;
  border-radius: 50%;
  background: #f97316;
}
.gls-glass-clock-widget-hour,
.gls-glass-clock-widget-min,
.gls-glass-clock-widget-sec {
  position: absolute;
  left: 50%;
  bottom: 50%;
  border-radius: 99em;
  background: currentColor;
  transform-origin: 50% 100%;
  animation: gls-glass-clock-widget-turn linear infinite;
}
.gls-glass-clock-widget-hour {
  width: 0.17em;
  height: 0.8em;
  margin-left: -0.085em;
  transform: rotate(calc(var(--h) * 30deg + var(--m) * 0.5deg));
  animation-duration: 43200s;
}
.gls-glass-clock-widget-min {
  width: 0.12em;
  height: 1.2em;
  margin-left: -0.06em;
  transform: rotate(calc(var(--m) * 6deg));
  animation-duration: 3600s;
}
.gls-glass-clock-widget-sec {
  width: 0.07em;
  height: 1.55em;
  margin: 0 0 -0.3em -0.035em;
  background: #f97316;
  transform-origin: 50% calc(100% - 0.3em);
  transform: rotate(240deg);
  animation-duration: 60s;
}
@keyframes gls-glass-clock-widget-turn {
  to { rotate: 1turn; }
}
@keyframes gls-glass-clock-widget-drift-a {
  to { transform: translate(4em, 1.5em) scale(1.1); }
}
@keyframes gls-glass-clock-widget-drift-b {
  to { transform: translate(-4.5em, -1em) scale(0.9); }
}

@media (prefers-reduced-motion: reduce) {
  .gls-glass-clock-widget, .gls-glass-clock-widget *, .gls-glass-clock-widget::before, .gls-glass-clock-widget::after, .gls-glass-clock-widget *::before, .gls-glass-clock-widget *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --gls-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --gls-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar glass effects