Wrist is a bi-weekly illustrative exercise to explore typography, colors, clock mechanics, and everything else that goes into watch design. Starting with one of my watches, I will be illustrating existing watches as well as exploring new watch designs. I sadly only own two watches, so I’ll quickly be moving to the latter.
This is the clock we’ll create using HTML, CSS and a little JavaScript. We’ll use CSS animations or transitions for any movement, and rely on JavaScript to set the initial time and adding basic CSS transforms.
My initial approach was to use three elements for each of the hands. I then went back and wrapped each in a container element. While the simpler HTML worked as far as the basic CSS animations, we’ll need containing elements when we want to position the hands and animate them also.
HTML:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <div id='watch'> <!-- The bands of the watch --> <div id='tlg' class='grip'></div> <div id='trg' class='grip'></div> <div id='blg' class='grip'></div> <div id='brg' class='grip'></div> <div id='topBand' class='band'></div> <div id='botBand' class='band'></div> <!-- // bands --> <!-- The Face of the watch --> <div id='face'> <div id='glass'> <div id='twelve'>XII</div> <div id='three'>III</div> <div id='six'>VI</div> <div id='nine'>IX</div> <div id='center'> <div id='name' style="left:40px;">Rahul</div> <div id='smallHand'></div> <div id='midHand'></div> <div id='bigHand'></div> <div id='dot'></div> <div id='desc'>Yaduvanshi</div> </div> </div> </div> <!-- // face --> </div> |
CSS:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | body{ overflow: hidden; } #watch { position: relative; margin: 50px; } .grip { position: absolute; border: 1px solid #777; width: 12px; height: 30px; background: #eee; } #tlg { top: -11px; left: 50px; border-radius: 8px 4px 0 0; border-left: none; box-shadow: inset 0 1px 0px #444444, inset 0 2px 0 white, inset 0 -6px 3px #444444; } /* line 25, ../sass/s.scss */ #trg { top: -11px; left: 150px; border-radius: 4px 8px 0 0; border-right: none; box-shadow: inset 0 1px 0 #444444, inset 0 2px 0 white, inset 0 -6px 3px #444444; } /* line 32, ../sass/s.scss */ #blg { top: 151px; left: 50px; border-radius: 0 0 4px 8px; border-left: none; box-shadow: inset 0 -1px 0px #444444, inset 0 -2px 0 white, inset 0 6px 3px #444444; } /* line 39, ../sass/s.scss */ #brg { top: 151px; left: 150px; border-radius: 0 0 8px 4px; border-left: none; box-shadow: inset 0 -1px 0px #444444, inset 0 -2px 0 white, inset 0 6px 3px #444444; } /* Material */ /* line 47, ../sass/s.scss */ .band { background: linear-gradient(27deg, #ae4601 5px, transparent 5px) 0 5px, linear-gradient(207deg, #ae4601 5px, transparent 5px) 10px 0px, linear-gradient(27deg, #733206 5px, transparent 5px) 0px 10px, linear-gradient(207deg, #733206 5px, transparent 5px) 10px 5px, linear-gradient(90deg, #66381a 10px, transparent 10px), linear-gradient(#66381a 25%, #301402 25%, #301402 50%, transparent 50%, transparent 75%, #3c1902 75%, #3c1902); background-color: #512203; background-size: 20px 20px; width: 87px; height: 600px; position: absolute; } /* line 54, ../sass/s.scss */ #topBand { top: -80px; left: 63px; } /* line 59, ../sass/s.scss */ #botBand { top: 140px; left: 63px; } /* Starting with the face of the watch */ /* line 65, ../sass/s.scss */ #face { background-color: #fefefe; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFEFEFE', endColorstr='#FFFFFFFF'); background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #fefefe), color-stop(17%, #dbd9da), color-stop(50%, #0b0d0c), color-stop(51%, #0b0e0c), color-stop(59%, #b0b1b5), color-stop(71%, #aeadbd), color-stop(84%, #cfcfcd), color-stop(100%, #ffffff)); background-image: -webkit-linear-gradient(top, #fefefe 0%, #dbd9da 17%, #0b0d0c 50%, #0b0e0c 51%, #b0b1b5 59%, #aeadbd 71%, #cfcfcd 84%, #ffffff 100%); background-image: -moz-linear-gradient(top, #fefefe 0%, #dbd9da 17%, #0b0d0c 50%, #0b0e0c 51%, #b0b1b5 59%, #aeadbd 71%, #cfcfcd 84%, #ffffff 100%); background-image: -o-linear-gradient(top, #fefefe 0%, #dbd9da 17%, #0b0d0c 50%, #0b0e0c 51%, #b0b1b5 59%, #aeadbd 71%, #cfcfcd 84%, #ffffff 100%); background-image: linear-gradient(top, #fefefe 0%, #dbd9da 17%, #0b0d0c 50%, #0b0e0c 51%, #b0b1b5 59%, #aeadbd 71%, #cfcfcd 84%, #ffffff 100%); margin: 20px; padding: 10px 0 0 10px; width: 160px; height: 160px; border: 1px solid #999; border-radius: 50%; box-shadow: inset 0 0 3px #000; position: relative; } /* line 78, ../sass/s.scss */ #face:after { content: " "; display: block; width: 14px; height: 22px; position: absolute; right: -15px; top: 74px; z-index: -9; border-radius: 10px; border: 1px solid #888; background-color: #aaa; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FF282828'); background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(7%, #505050), color-stop(14%, #c5c7c6), color-stop(22%, #505050), color-stop(28%, #e6e4e7), color-stop(35%, #8d8c91), color-stop(42%, #e9e9e9), color-stop(49%, #8c8c8c), color-stop(57%, #e2e2e4), color-stop(65%, #c8c8c8), color-stop(72%, #808080), color-stop(76%, #b4b4b4), color-stop(85%, #fdfdfd), color-stop(92%, #b4b4b4), color-stop(100%, #282828)); background-image: -webkit-linear-gradient(top, #ffffff 0%, #505050 7%, #c5c7c6 14%, #505050 22%, #e6e4e7 28%, #8d8c91 35%, #e9e9e9 42%, #8c8c8c 49%, #e2e2e4 57%, #c8c8c8 65%, #808080 72%, #b4b4b4 76%, #fdfdfd 85%, #b4b4b4 92%, #282828 100%); background-image: -moz-linear-gradient(top, #ffffff 0%, #505050 7%, #c5c7c6 14%, #505050 22%, #e6e4e7 28%, #8d8c91 35%, #e9e9e9 42%, #8c8c8c 49%, #e2e2e4 57%, #c8c8c8 65%, #808080 72%, #b4b4b4 76%, #fdfdfd 85%, #b4b4b4 92%, #282828 100%); background-image: -o-linear-gradient(top, #ffffff 0%, #505050 7%, #c5c7c6 14%, #505050 22%, #e6e4e7 28%, #8d8c91 35%, #e9e9e9 42%, #8c8c8c 49%, #e2e2e4 57%, #c8c8c8 65%, #808080 72%, #b4b4b4 76%, #fdfdfd 85%, #b4b4b4 92%, #282828 100%); background-image: linear-gradient(top, #ffffff 0%, #505050 7%, #c5c7c6 14%, #505050 22%, #e6e4e7 28%, #8d8c91 35%, #e9e9e9 42%, #8c8c8c 49%, #e2e2e4 57%, #c8c8c8 65%, #808080 72%, #b4b4b4 76%, #fdfdfd 85%, #b4b4b4 92%, #282828 100%); } /* line 94, ../sass/s.scss */ #glass { box-shadow: inset 0 0 6px #000; background: #a6a39e; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFC8C5C0', endColorstr='#FFADA8A2'); background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c8c5c0), color-stop(100%, #ada8a2)); background-image: -webkit-linear-gradient(top, #c8c5c0 0%, #ada8a2 100%); background-image: -moz-linear-gradient(top, #c8c5c0 0%, #ada8a2 100%); background-image: -o-linear-gradient(top, #c8c5c0 0%, #ada8a2 100%); background-image: linear-gradient(top, #c8c5c0 0%, #ada8a2 100%); width: 150px; height: 150px; border: 1px solid #999; border-radius: 80px; position: relative; /* Numbers */ } /* line 107, ../sass/s.scss */ #glass div { position: absolute; font-size: 14px; } /* line 111, ../sass/s.scss */ #glass div:nth-child(2n) { transform: rotate(-90deg); } /* line 115, ../sass/s.scss */ #glass #twelve { top: 3px; left: 65px; } /* line 116, ../sass/s.scss */ #glass #three { top: 66px; left: 135px; } /* line 117, ../sass/s.scss */ #glass #six { top: 135px; left: 67px; } /* line 118, ../sass/s.scss */ #glass #nine { top: 66px; left: 5px; } /* line 121, ../sass/s.scss */ #glass #center { background: #e1ddd2; box-shadow: inset 0 1px 1px #777777, inset 0 -1px 1px #777777; width: 110px; height: 110px; border-radius: 50%; top: 20px; left: 20px; } /* line 130, ../sass/s.scss */ #glass #center div { top: 55px; left: 55px; } /* line 134, ../sass/s.scss */ #glass #center #name, #glass #center #desc { top: 10px; left: 32px; font-variant: small-caps; font-size: 8px; } /* line 140, ../sass/s.scss */ #glass #center #desc { top: 70px; margin-left: 0px; transform: none; } /* line 146, ../sass/s.scss */ #glass #center #dot { width: 8px; height: 8px; border-radius: 50%; background: #444e5e; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF444E5E', endColorstr='#FF4F4E5E'); left: 51px; top: 55px; } /* line 156, ../sass/s.scss */ #glass #center #smallHand, #glass #center #midHand, #glass #center #bigHand { background: #1c2252; width: 45px; height: 2px; border: 1px solid #4f4e5e; box-shadow: 0 0 1px #b5afaf; /* enables antialiasing */ border-radius: 80%; border-top-left-radius: 0; border-bottom-left-radius: 0; transform-origin: 0% 50%; transform: rotate(-45deg); -webkit-animation: hours 43200s infinite linear; -moz-animation: hours 43200s infinite linear; -ms-animation: hours 43200s infinite linear; -o-animation: hours 43200s infinite linear; animation: hours 43200s infinite linear; } /* line 169, ../sass/s.scss */ #glass #center #bigHand { width: 65px; height: 0; border-bottom: none; -webkit-animation: seconds 60s infinite linear; -moz-animation: seconds 60s infinite linear; -ms-animation: seconds 60s infinite linear; -o-animation: seconds 60s infinite linear; animation: seconds 60s infinite linear; } /* line 175, ../sass/s.scss */ #glass #center #midHand { width: 65px; height: 1px; -webkit-animation: minutes 3600s infinite linear; -moz-animation: minutes 3600s infinite linear; -ms-animation: minutes 3600s infinite linear; -o-animation: minutes 3600s infinite linear; animation: minutes 3600s infinite linear; } /* keyframes added with JS so that watch starts at local time */ @-webkit-keyframes seconds {0%{-webkit-transform: rotate(120deg);}to{-webkit-transform: rotate(480deg);}} @-webkit-keyframes minutes {0%{-webkit-transform: rotate(178deg);}to{-webkit-transform: rotate(538deg);}} @-webkit-keyframes hours {0%{-webkit-transform: rotate(130deg);}to{-webkit-transform: rotate(490deg);}} @-moz-keyframes seconds {0%{-moz-transform: rotate(120deg);}to{-moz-transform: rotate(480deg);}} @-moz-keyframes minutes {0%{-moz-transform: rotate(178deg);}to{-moz-transform: rotate(538deg);}} @-moz-keyframes hours {0%{-moz-transform: rotate(130deg);}to{-moz-transform: rotate(490deg);}} @-o-keyframes seconds {0%{-o-transform: rotate(120deg);}to{-o-transform: rotate(480deg);}} @-o-keyframes minutes {0%{-o-transform: rotate(178deg);}to{-o-transform: rotate(538deg);}} @-o-keyframes hours {0%{-o-transform: rotate(130deg);}to{-o-transform: rotate(490deg);}} @-ms-keyframes seconds {0%{-ms-transform: rotate(120deg);}to{-ms-transform: rotate(480deg);}} @-ms-keyframes minutes {0%{-ms-transform: rotate(178deg);}to{-ms-transform: rotate(538deg);}} @-ms-keyframes hours {0%{-ms-transform: rotate(130deg);}to{-ms-transform: rotate(490deg);}} @keyframes seconds {0%{transform: rotate(120deg);}to{transform: rotate(480deg);}} @keyframes minutes {0%{transform: rotate(178deg);}to{transform: rotate(538deg);}} @keyframes hours {0%{transform: rotate(130deg);}to{transform: rotate(490deg);}} </style> |
JavaScript to set the initial time and adding basic CSS transforms
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | var d = new Date(), hr = d.getHours()%12, min = d.getMinutes(), sec = d.getSeconds(), // Base Values (-90 since that's where 12 starts) baseDegSEC = -90 + Math.round(sec * 6), baseDegMIN = -90 + Math.round(min*6 + (6 / (60/sec))), baseDegHR = -90 + Math.round(hr*30 + (30 / ( (60/min)+(60/sec) )) ), // End Values endDegSEC = baseDegSEC + 360, endDegMIN = baseDegMIN + 360, endDegHR = baseDegHR + 360, keyframes = "", VENDORS = [ '-webkit-', '-moz-', '-o-', '-ms-', '' ]; for( var i = 0, len = VENDORS.length; i < len; i++ ) { keyframes += "@"+VENDORS[i]+"keyframes seconds {"+ "0%{"+VENDORS[i]+"transform: rotate("+baseDegSEC+"deg);}"+ "to{"+VENDORS[i]+"transform: rotate("+endDegSEC+"deg);}}"+ "@"+VENDORS[i]+"keyframes minutes {"+ "0%{"+VENDORS[i]+"transform: rotate("+baseDegMIN+"deg);}"+ "to{"+VENDORS[i]+"transform: rotate("+endDegMIN+"deg);}}"+ "@"+VENDORS[i]+"keyframes hours {"+ "0%{"+VENDORS[i]+"transform: rotate("+baseDegHR+"deg);}"+ "to{"+VENDORS[i]+"transform: rotate("+endDegHR+"deg);}}"; } // Add the Keyframes in a <style> tag in the <head> var cssAnimation = document.createElement('style'); cssAnimation.type = 'text/css'; var rules = document.createTextNode(keyframes); cssAnimation.appendChild(rules); document.getElementsByTagName("head")[0].appendChild(cssAnimation); // Reloading the stylesheets to fix Chrome bug? var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length; i++) { var link = links[i]; if (link.rel === "stylesheet") { link.href += "?"; } } |