こんにちは。KOUKIです。
本記事は、Udemyの「50 Projects In 50 Days – HTML, CSS & JavaScript」で学習したことを載せています。
<目次>
実装するもの
今回は、cssでアナログ時計のスタイリングをします。
demoは「こちら」で確認できます。
ワークスペース
必要なファイルは、以下の通りです。
1 2 3 4 5 6 |
$ tree . ├── index.html ├── script.js └── style.css |
JavaScript版
HTML & JavaScript
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 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="style.css" /> <title>Theme Clock</title> </head> <body> <!-- Inspired by this dribbble shot https://dribbble.com/shots/5958443-Alarm-clock --> <button class="toggle">Dark mode</button> <div class="clock-container"> <div class="clock"> <div class="needle hour"></div> <div class="needle minute"></div> <div class="needle second"></div> <div class="center-point"></div> </div> <div class="time"></div> <div class="date"></div> </div> <script src="script.js"></script> </body> </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 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 |
// 要素を取得する const hourEl = document.querySelector('.hour') const minuteEl = document.querySelector('.minute') const secondEl = document.querySelector('.second') const timeEl = document.querySelector('.time') const dateEl = document.querySelector('.date') const toggle = document.querySelector('.toggle') // 日付要素 const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // clickイベントの登録 toggle.addEventListener('click', (e) => { // html要素を取得 const html = document.querySelector('html') // darkクラスの存在確認 if(html.classList.contains('dark')) { // darkクラスを除去 html.classList.remove('dark') // ボタンの名称を変更 e.target.innerHTML = 'Dark Mode' } else { // darkクラスを付与 html.classList.add('dark') // ボタンの名称を変更 e.target.innerHTML = 'Light Mode' } }) function setTime() { // 日時取得 const time = new Date(); const month = time.getMonth() const day = time.getDay() const date = time.getDate() const hours = time.getHours() const hoursForClock = hours >= 13 ? hours % 12 : hours; const minutes = time.getMinutes() const seconds = time.getSeconds() const ampm = hours >= 12 ? 'PM' : 'AM' // 日時の設定 hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 11, 0, 360)}deg)` minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 59, 0, 360)}deg)` secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 59, 0, 360)}deg)` // 画面に表示 timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}` dateEl.innerHTML = `${days[day]}, ${months[month]} <span class="circle">${date}</span>` } // StackOverflow https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers const scale = (num, in_min, in_max, out_min, out_max) => { return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } // 日付をセット setTime() // 時計の針を動かす setInterval(setTime, 1000) |

スタイリング
cssでスタイリングをしていきます。項目のhtmlやbodyは、HTML要素です。
全体の設定
全体の設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* フォント */ @import url("https://fonts.googleapis.com/css?family=Heebo:300&display=swap"); * { /* ボックスの大きさを算出 */ box-sizing: border-box; } /* 変数を定義 */ :root { --primary-color: #000; --secondary-color: #fff; } |
bodyの設定
bodyの設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
body { font-family: "Heebo", sans-serif; /* ページビューに対して高さ100% */ height: 100vh; /* スクロールを非表示 */ overflow: hidden; margin: 0; /* flexアイテムにする */ display: flex; /* flex重点の真ん中 */ align-items: center; /* flex横軸の真ん中 */ justify-content: center; } |

toggleの設定
toggleの設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
.toggle { cursor: pointer; background-color: var(--primary-color); color: var(--secondary-color); /* 枠線なし */ border: 0; /* 角を丸く */ border-radius: 4px; /* 上下 | 左右 */ padding: 8px 12px; /* 親要素(html)からの絶対位置 */ position: absolute; top: 100px; } /* ボタンを押下した時 */ .toggle:focus { /* 青線を非表示 */ outline: none; } |

clock-containerの設定
clock-containerの設定をします。
1 2 3 4 5 6 7 8 9 10 |
.clock-container { display: flex; /* flexアイテムを積み重ねるように配置 */ flex-direction: column; /* 各アイテムを均等に配置し 最初のアイテムは先頭に寄せ、 最後のアイテムは末尾に寄せる */ justify-content: space-between; align-items: center; } |

clockの設定
clockの設定をします。
1 2 3 4 5 |
.clock { position: relative; width: 200px; height: 200px; } |

needleの設定
needleの設定をします。
1 2 3 4 5 6 7 8 9 10 11 |
.needle { background-color: var(--primary-color); position: absolute; top: 50%; left: 50%; height: 65px; width: 3px; /* 要素の変形transformにおける原点を設定 */ transform-origin: bottom center; transition: all 0.5s ease-in; } |

時計針の設定
時計針の設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.needle.hour { transform: translate(-50%, -100%) rotate(0deg); } .needle.minute { transform: translate(-50%, -100%) rotate(0deg); height: 100px; } .needle.second { transform: translate(-50%, -100%) rotate(0deg); height: 100px; background-color: #e74c3c; } |

center-pointの設定
全体の設定をします。
1 2 3 4 5 6 7 8 9 10 |
.center-point { background-color: #e74c3c; width: 10px; height: 10px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; } |

疑似クラスの設定
疑似クラスの設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 |
/* 疑似クラス */ .center-point::after { content: ""; background-color: var(--primary-color); width: 5px; height: 5px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; } |

timeの設定
timeの設定をします。
1 2 3 |
.time { font-size: 60px; } |

dateの設定
dateの設定をします。
1 2 3 4 5 6 |
.date { color: #aaa; font-size: 14px; letter-spacing: 0.3px; text-transform: uppercase; } |

circleの設定
circleの設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.date .circle { background-color: var(--primary-color); color: var(--secondary-color); border-radius: 50%; height: 18px; width: 18px; display: inline-flex; align-items: center; justify-content: center; line-height: 18px; transition: all 0.5s ease-in; font-size: 12px; } |

darkの設定
darkの設定をします。Dark Modeを押下すると背景色が変化します。
1 2 3 4 5 6 7 8 9 10 |
html { transition: all 0.5s ease-in; } html.dark { --primary-color: #fff; --secondary-color: #333; background-color: #111; color: var(--primary-color); } |

これで、完成です。
おわりに
アナログ時計のスタイリングも面白いですね。工夫次第ではなんでもできるなと感じました^^
もっと勉強して、色々なWebアプリを作れるようになりたいですね。
それでは、また!
CSSまとめ
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 |
/* フォント */ @import url("https://fonts.googleapis.com/css?family=Heebo:300&display=swap"); * { /* ボックスの大きさを算出 */ box-sizing: border-box; } /* 変数を定義 */ :root { --primary-color: #000; --secondary-color: #fff; } html { transition: all 0.5s ease-in; } html.dark { --primary-color: #fff; --secondary-color: #333; background-color: #111; color: var(--primary-color); } body { font-family: "Heebo", sans-serif; /* ページビューに対して高さ100% */ height: 100vh; /* スクロールを非表示 */ overflow: hidden; margin: 0; /* flexアイテムにする */ display: flex; /* flex重点の真ん中 */ align-items: center; /* flex横軸の真ん中 */ justify-content: center; } .toggle { cursor: pointer; background-color: var(--primary-color); color: var(--secondary-color); /* 枠線なし */ border: 0; /* 角を丸く */ border-radius: 4px; /* 上下 | 左右 */ padding: 8px 12px; /* 親要素(html)からの絶対位置 */ position: absolute; top: 100px; } /* ボタンを押下した時 */ .toggle:focus { /* 青線を非表示 */ outline: none; } .clock-container { display: flex; /* flexアイテムを積み重ねるように配置 */ flex-direction: column; /* 各アイテムを均等に配置し 最初のアイテムは先頭に寄せ、 最後のアイテムは末尾に寄せる */ justify-content: space-between; align-items: center; } .clock { position: relative; width: 200px; height: 200px; } .needle { background-color: var(--primary-color); position: absolute; top: 50%; left: 50%; height: 65px; width: 3px; /* 要素の変形transformにおける原点を設定 */ transform-origin: bottom center; transition: all 0.5s ease-in; } .needle.hour { transform: translate(-50%, -100%) rotate(0deg); } .needle.minute { transform: translate(-50%, -100%) rotate(0deg); height: 100px; } .needle.second { transform: translate(-50%, -100%) rotate(0deg); height: 100px; background-color: #e74c3c; } .center-point { background-color: #e74c3c; width: 10px; height: 10px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; } /* 疑似クラス */ .center-point::after { content: ""; background-color: var(--primary-color); width: 5px; height: 5px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; } .time { font-size: 60px; } .date { color: #aaa; font-size: 14px; letter-spacing: 0.3px; text-transform: uppercase; } .date .circle { background-color: var(--primary-color); color: var(--secondary-color); border-radius: 50%; height: 18px; width: 18px; display: inline-flex; align-items: center; justify-content: center; line-height: 18px; transition: all 0.5s ease-in; font-size: 12px; } |
コメントを残す
コメントを投稿するにはログインしてください。