天気 ウィジェット 9選 — 温度・時計・アイコンをコピペOK
天気 ウィジェットとは、今の空・温度・時刻を一枚の小さなカードにまとめてページへ貼る表示部品のことです。九つともHTML・SCSS・数行のJavaScriptだけで作ってあり、貼った場所でそのまま動くコピペOKの部品で、天気のAPIは一つも使いません。九つのうち一つは、実際の時計が空の色と挨拶を一日分進めていきます。
自動再生 · タイルを押すとその項目へ · すべて1つのzip
- 01 条件を変えると空色も文面も一緒に変わる現在のカード
- 02 止まっていない天気アイコン — 太陽・雲・雨・雪
- 03 今の時間のマスに灯がつく時間ごとの帯
- 04 一週間の範囲の中で場所を見つける5日予報の帯
- 05 一日の太陽がアーチを上りまた沈む道
- 06 針が等級の帯を指して止まる紫外線ゲージ
- 07 降水確率が育つ棒と風向を指すコンパス
- 08 一度押せばカード内の全温度が換算される単位トグル
- 09 実際の時間が進むと空も挨拶も変わる時計ウィジェット
並びは作りの難しさではなく、一日が進む順です。今の空を一枚で伝えるカード(01)で始まり、条件を絵で示すアイコン(02)が続き、時間ごとの帯(03)が今夜までを、5日の帯(04)が一週間の先までを受け持ちます。太陽の道(05)で日の出から日の入りをたどり、紫外線のゲージ(06)と雨・風のカード(07)で外の様子を確かめ、単位の切り替え(08)で旅先の温度表記に合わせると、最後の時計(09)で一日がまた動き出します。九つは同じ色・間隔・動きの速さの値を共有しているので、何枚かを一枚の画面に混ぜて貼っても、まとまりは崩れません。
01条件を変えると空色も文面も一緒に変わる現在のカード
晴れ・曇り・雨・雪の四つのボタンから空の状態を選ぶと、重ねた二枚の下地が入れ替わってカードの空が変わり、アイコンと温度・状態の文・最高最低の数字も同じ瞬間にそろって切り替わります。空の入れ替えはopacityをsteps(1, end)のカットで行うので二つの空が半透明に重なって見えるコマがなく、ボタンを押したときはアイコンが一度沈んでから跳ね上がって戻ります。測定では24コマのうち11コマに動きがあり、累積面積は33.208%・強度の平均58.2で、ダッシュボード上部の天気のまとめや、旅行・屋外イベントのページに貼る一枚です。
// 空の下地を二枚重ねる — 晴れ(a)と雨(b)。既定はa。
.wc__sky {
position: absolute;
inset: 0;
pointer-events: none;
}
.wc__sky--a { background: linear-gradient(170deg, #bfe3ff 0%, #dcefff 46%, #ffe9b0 100%); }
.wc__sky--b { background: linear-gradient(170deg, #93a7c8 0%, #b7c5de 60%, #cdd8ea 100%); opacity: 0; }
.wc.is-cloudy .wc__sky--a,
.wc.is-rainy .wc__sky--a,
.wc.is-snowy .wc__sky--a { opacity: 0; }
.wc.is-cloudy .wc__sky--b,
.wc.is-rainy .wc__sky--b,
.wc.is-snowy .wc__sky--b { opacity: 1; }
02止まっていない天気アイコン — 太陽・雲・雨・雪
六つのアイコンが一つの格子の中で、それぞれの周期で動き続けます。太陽は光条がその場で一回転し、雲は横へ流れ、雨粒は三つが少しずつ遅れて落ちながら端で薄れて消え、雪片は落ちながら半回転ほど回り、雷は薄く灯ったまま休んでから二度だけ光り、風は右へ流れて戻ります。周期はどれも設定の2秒の約数に揃えてあるので2秒の収録に一周分が収まり、測定では24コマのうち23コマに動きがあって累積面積は2.443%・強度の平均58.6で、予報リストの条件を示すアイコンや天気アプリの最初の画面に向きます。
// 雨粒は三つ: 1秒周期、ディレイでずらす — 終わりで薄れて消えるところまで含める
@keyframes wi-dropfall {
0% { transform: translateY(0); opacity: 0; }
18% { opacity: 1; }
72% { opacity: 1; }
100% { transform: translateY(12px); opacity: 0; }
}
.wi__drop {
position: absolute;
top: 20px;
color: $subject-blue;
animation-name: wi-dropfall;
animation-duration: 1s;
animation-timing-function: $easing;
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
.wi__drop--1 { left: 14px; }
.wi__drop--2 { left: 27px; animation-delay: .33s; }
.wi__drop--3 { left: 40px; animation-delay: .66s; }
03今の時間のマスに灯がつく時間ごとの帯
これから夜までの時間のマスが横に並び、開いた時刻に一番近いマスに点が灯って、そのマスだけが少し前に出ます。横のスクロールはoverflow-x: autoの窓が受け持ち、scroll-snap-type: x mandatoryがマスの幅ごとにぴたりと止め、今のマスはJavaScriptが時刻との差が一番小さいマスを選んでaria-currentで示します。測定では24コマのうち7コマに動きがあり、累積面積は10.719%・強度の平均50.8で、時間ごとの予報や、登下校の時間帯の案内に向きます。
.hs__viewport {
margin-top: $sp-2;
overflow-x: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
&::-webkit-scrollbar { display: none; }
&:focus-visible { outline: 2px solid $subject-blue; outline-offset: 2px; border-radius: $r-control; }
}
.hs__cell {
position: relative;
display: grid;
justify-items: center;
gap: $sp-1;
padding: $sp-2 0 $sp-1;
border-radius: $r-control;
background: rgba(23, 20, 26, .06);
scroll-snap-align: start;
font-variant-numeric: tabular-nums;
}
04一週間の範囲の中で場所を見つける5日予報の帯
五つの日付の最低から最高までの温度帯が、一週間全体の最も低い値から最も高い値までの範囲の中でそれぞれの場所に収まり、振れの大きい日は帯がその分だけ長く伸びます。場所はJavaScriptがleftとwidthを週の範囲に対する割合で計算して静かに置くので値を差し替えても並びが自動でそろい、帯の登場はwidthでもscaleXでもなくclip-pathの幕開けにして幅の再計算も丸い端の潰れも避けてあり、五つの行が0.12秒ずつ遅れて開きます。測定では24コマのうち18コマに動きがあり、累積面積は2.413%・強度の平均80.5で、週間予報のリストや、服装・荷物の準備の案内に貼ります。
// 温度の範囲トラック — 棒は内側の割合で置く
.dr__track {
position: relative;
height: 6px;
border-radius: $r-pill;
background: rgba(23, 20, 26, .08);
}
.dr__bar {
position: absolute;
top: 0;
bottom: 0;
border-radius: $r-pill;
background: linear-gradient(90deg, #7cc3f2, #f2a94c);
}
var drSpan = drMax - drMin;
for (var j = 0; j < drDays.length; j++) {
var d = drDays[j];
var bar = d.row.querySelector('.dr__bar');
bar.style.left = ((d.lo - drMin) / drSpan * 100) + '%';
bar.style.width = ((d.hi - d.lo) / drSpan * 100) + '%';
}
05一日の太陽がアーチを上りまた沈む道
アーチの上の太陽が選んだ時刻の高さに張り付き、時刻を動かすと太陽がアーチを転がって、下の空が朝・昼・夕の三つの色に切り替わります。位置をtopやleftで三角関数から求める必要はなく、offset-path: path("M 20 71 A 120 60 0 0 1 220 71")がアーチの曲線をそのまま道にしてoffset-distanceだけが進み、offset-rotate: 0degが太陽の傾きを止め、空の入れ替えはカットです。道の二つの半径と両端のxは下に描いたSVGのアーチと同じで、yだけを太陽アイコン18pxの半分にあたる9px持ち上げてあるので、アイコンの中心が線の上を転がります。測定では24コマのうち23コマに動きがあり、累積面積は16.797%・強度の平均79.1で、日の出・日の入りのカードや、屋外撮影の時間の案内に使えます。
.sa__sun {
position: absolute;
left: 50%;
bottom: $sp-1;
width: 240px;
height: 90px;
margin-left: -120px;
pointer-events: none;
color: #e8960c;
// アーチをたどる道 — SVGのアーチ(M 20 80 A 120 60 0 0 1 220 80)と半径・両端のxは同じで
// yだけを9px(太陽アイコン18pxの半分)持ち上げた。太陽の中心が道に乗るので、アイコンが線をたどって転がる。
// 狭い画面(340px)の道は下のメディアクエリに同じやり方で手で一組書いておく — 自動で追従はしない
offset-path: path("M 20 71 A 120 60 0 0 1 220 71");
offset-distance: 57%;
offset-rotate: 0deg;
display: grid;
place-items: center;
filter: drop-shadow(0 2px 2px rgba(23, 20, 26, .25));
}
06針が等級の帯を指して止まる紫外線ゲージ
半円の文字盤に「低い」から「危険」まで五段階の色帯が並び、値を動かすと針が角度を取って該当する帯に止まり、等級名と助言の文が一緒に替わります。文字盤は正方形の円盤にconic-gradientで36度ずつの五帯を描いて上の半分だけを見せたもので、針の動きはtransform-originをハブの中心(針の足より1px上)に置いたrotateだけです。測定では24コマのうち20コマに動きがあり、累積面積は2.125%・強度の平均74.1で、紫外線・大気指数のカードや、屋外活動の案内に貼る部品です。
// 半円ダイヤル — 正方形の円盤をborder-radius: 50%で描き、conicで五段階の帯を入れたうえで
// clip-pathで上半分だけを見せる(水平線の下にすき間が残らないよう中心線まで切る)
.uv__dial {
position: relative;
width: 120px;
height: 64px;
}
.uv__disc {
position: absolute;
top: 0;
left: 0;
width: 120px;
height: 120px;
border-radius: 50%;
background: conic-gradient(from 270deg at 50% 50%,
#7ed957 0 36deg, #ffe45c 36deg 72deg, #ffb020 72deg 108deg, #f2691f 108deg 144deg, #d7263d 144deg 180deg,
rgba(255, 247, 230, 0) 180deg 360deg);
clip-path: inset(0 0 60px 0);
}
07降水確率が育つ棒と風向を指すコンパス
時間ごとの降水確率の棒が下から順に伸び上がり、隣のコンパスの針は風の方位へ回って、速度の数字と方位の名前が同じ瞬間に替わります。棒の高さは--hに静的に置いて伸びる動きだけをtransform-origin: bottomのscaleYが担い、針は北を指す半分だけを赤く塗ってあるので向きが遠くからでも読めます。測定では24コマのうち23コマに動きがあり、累積面積は3.967%・強度の平均105.1で、降水確率と風のカード、洗濯や屋外の予定を決めるときの案内に使います。
.pw__bar {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: var(--h);
border-radius: $r-xs $r-xs 0 0;
// 伸びる起点 — 棒は底から育つ(既定の50% 50%だと真ん中から広がる)
transform-origin: bottom;
background: linear-gradient(180deg, #4a9fe8, $subject-blue);
}
.pw__needle {
position: absolute;
left: calc(50% - 1px);
top: calc(50% - 25px);
width: 2px;
height: 50px;
border-radius: $r-pill;
background: linear-gradient(180deg, $error 0 50%, rgba(23, 20, 26, .35) 50% 100%);
transform-origin: 50% 50%;
transform: rotate(315deg);
}
08一度押せばカード内の全温度が換算される単位トグル
摂氏・華氏のどちらかを押すと、大きい温度・時間ごとのマス・週間の行の数字が同じ瞬間にすべて換算され、目印のつまみが枠の中を滑って移ります。元の値はどの要素もdata-cに摂氏で持たせてあり、華氏への換算はMath.round(c * 9 / 5 + 32)の一行だけで、選んだ単位はlocalStorageに保存して次に開いたときに読み戻します。測定では24コマのうち8コマに動きがあり、累積面積は1.576%・強度の平均114.6で、単位が国ごとに分かれるサービスの設定や、旅行者向けの天気カードに向きます。
// 単位を選ぶとカード内の全温度が同じ瞬間に換算され、選んだ値は保存されて次に開いてもそのまま。
function utShow(unit) {
for (var i = 0; i < utCells.length; i++) {
var c = Number(utCells[i].getAttribute('data-c'));
utCells[i].textContent = unit === 'f' ? String(Math.round(c * 9 / 5 + 32)) : String(c);
}
for (var j = 0; j < utSuffixes.length; j++) {
utSuffixes[j].textContent = unit === 'f' ? '°F' : '°C';
}
for (var k = 0; k < utButtons.length; k++) {
var on = utButtons[k].getAttribute('data-unit') === unit;
utButtons[k].classList.toggle('is-on', on);
utButtons[k].setAttribute('aria-pressed', on ? 'true' : 'false');
}
utRoot.classList.toggle('is-f', unit === 'f');
}
function utRemember(unit) {
try { localStorage.setItem('ut-unit', unit); } catch (err) { /* 保存が禁じられた窓ではこの画面だけ */ }
}
09実際の時間が進むと空も挨拶も変わる時計ウィジェット
setIntervalは毎秒回りますが、文字が書き換わるのは分が変わる瞬間だけで、時刻に合わせて空の色が朝・昼・夕・夜の四つに移り変わり、挨拶の文と曜日も同じ瞬間に替わります。昼は太陽の光条が回り、夜は月が静かに上下し、空の帯がカードの幅いっぱいに広がって時間帯ごとに丸ごと色が替わるため、測定の累積面積は11.155%に届き、強度の平均は84.3、24コマのうち16コマに動きがありました。ダッシュボード上部の時計・挨拶や、キオスクの待ち画面に置く一枚です。
function lcTick() {
var d = new Date();
if (d.getMinutes() !== lcLastMinute) {
lcLastMinute = d.getMinutes();
lcNow.textContent = lcPad(d.getHours()) + ':' + lcPad(d.getMinutes());
lcDate.textContent = lcWeek[d.getDay()] + ' · ' + (d.getMonth() + 1) + '/' + d.getDate();
lcHi.textContent = lcGreeting(d.getHours());
lcRoot.classList.remove('is-morning', 'is-noon', 'is-evening', 'is-night');
lcRoot.classList.add(lcTheme(d.getHours()));
// 格子ループに重ねた次の分の文字も本物の時刻から作る — 合わない時間が画面に残らないように
var nx = new Date(d.getTime() + 60000);
var alt = lcRoot.querySelector('.lc__swap .lc__alt');
if (alt) { alt.textContent = lcPad(nx.getHours()) + ':' + lcPad(nx.getMinutes()); }
}
}
setInterval(lcTick, 1000);
lcTick();
どこで壊れるか — 落とし穴
最初に手間取ったのは、06の紫外線ゲージの水平線でした。conic-gradientは円盤の中心から全周へ色を配る性質なので、上の半分だけを見せようと円盤の高さを半分に縮めると、水平線の下に薄く色の付いたすき間が一本残ります。直し方は、円盤を正方形のまま作ることでした。五つの帯を描いた円盤をclip-path: inset(0 0 60px 0)で中心線まで切り落とすと、すき間は消えて等級の帯だけがきれいに半円へ並びます。
二番目は、08の°記号の重なりでした。°C/°Fの接尾辞を最初は::afterの重ねで置いていたのですが、数字と記号の替わる瞬間がずれ、代表として選ばれたコマには、華氏に替わった数字の上へ摂氏の記号が重なって、75°Cという実在しない温度が写りました。直し方は、接尾辞も数字と同じ作りにそろえることでした。二つの値を重ねて置いたvとaltの組をsteps(1, end)のカットで同時に入れ替えると、重なって見える瞬間が消えます。
三番目は、03の帯を動かす仕組みそのものでした。scroll-snap-type: x mandatoryは、中の要素が少しでも動くと最も近いマスの位置へ引き寄せ直す性質を持ちます。プレビューのループが枠をtranslateXで滑らせても、スナップがそれを捕まえてマスの位置へ戻すので、動きが丸ごと見えなくなりました。.is-demoのあいだだけ窓をscroll-snap-type: noneに切り替え、人が実際に触る経路ではマス単位の止まり方を生かすように二つの状況を分けました。
四番目は、遅れを持つループの最初のコマです。animation-delayの待ち時間のあいだ、要素はアニメーションが始まる前の、自分そのままの姿で待っています。雨粒や帯の幕開けのように最初の姿と完成した姿が違う動きに遅れを付けると、0コマ目に完成した姿がちらりと写ってしまいます。animation-fill-mode: backwardsを遅れの付いたループすべてに足して、待ち時間のあいだも最初の姿を保たせました。
九つが頼りにする三つの性質の対応は、2026年9月12日時点のcaniuseでこう並んでいます。offset-pathはChrome 46+・Safari 16+・Firefox 72+・Edge 79+で全体の96.35%(CSS Motion Path)、scroll-snap-typeはChrome 69+・Safari 11+・Firefox 68+・Edge 79+で96.8%(Scroll Snap)、conic-gradientはChrome 69+・Safari 12.1+・Firefox 83+・Edge 79+で96.44%(Conic Gradients)です。九つのソースはこの記事に書いた値のまま圧縮ファイルに入っており、開くときのパスワードは639h7wyhです。
アクセシビリティ
動きを減らしてほしいという設定(prefers-reduced-motion: reduce)では、九つとも自動で回る動きを止めて、今の値と状態だけを残します。01は選ばれた空と温度を、02は静止したアイコンを、03は灯の付いた今のマスを、04は伸びきった帯を、05は選んだ時刻の高さの太陽を、06は止まった角度の針を、07は伸びきった棒と風の方位を、08は選ばれた単位を、09は今の時刻の空と時計を、それぞれ静止して見せます。この設定の宣言にはすべて!importantが付いています。プレビューのループの規則がクラスを重ねた形で書かれていて、通常の書き方では詳細度で負けて中途半端に動き続けてしまうからです。
読み上げの備えも項目ごとに違います。09の時計はrole="timer"にaria-live="off"を組み合わせ、毎秒の書き換えが読み上げの嵐にならないように黙らせてあります。08の単位と01の空の状態のボタンはaria-pressedが押された側を伝え、03の今のマスはaria-currentが位置を示します。ボタン・帯の窓・時刻のつまみには:focus-visibleの枠が付き、キーボードだけで操作していても今どこにいるかが分かります。
FAQ
天気APIは必要ですか?
いいえ、九つともAPIも通信も使いません。温度も降水確率も、HTMLのdata-c・data-lo・data-hiのような属性に書いた値で動きます。手元の数字に差し替えて貼るだけで動き、後からAPIの値を流し込む形に組み替えることもできます。
offset-pathはSafariで動きますか?
動きます。Safariは16から対応し、Chromeは46+、Firefoxは72+、Edgeは79+で、caniuseの全体対応は96.35%です。05の太陽の道はoffset-pathとoffset-distanceだけで転がるので、対応している環境なら追加の準備は要りません。
単位の選択はどう保存されますか?
localStorageにut-unitというキーで保存し、次に開いたときに読み戻します。保存も読み出しもtry/catchで囲ってあり、シークレットウィンドウのように保存が禁じられた環境ではその場の表示だけが変わります。保存がないときは摂氏に戻ります。
変種 — 値をひとつだけ変える
九つは設定の値をひとつ差し替えるだけで顔が変わります。差し替える場所はどれも一箇所です。
| 変種 | 変える値 | 様子 |
|---|---|---|
| 倍速のループ | $duration 2s → 1s |
アイコンと時計の周期が半分に縮み、画面が忙しい朝の空気になります |
| 計器の針 | $ease-spring → linear |
針とつまみから跳ねが消え、精密機器のような無機質な動きになります |
| 夕の空 | 01の空の青 #bfe3ff → オレンジ系 |
晴れのカードが昼から夕の顔に変わり、温度の数字まで暖かく見えます |
貼る場所に迷ったら、埋め込みウィジェットのパターンを集めた隣の記事が同じ土台の作りを紹介しています。活動の流れを見せるフィードの部品や単独で立つダッシュボードの部品も同じ色と間隔で作ってあるので、混ぜて並べられます。まずは今の空の一枚(01)を画面のいちばん上に置き、その隣に時計(09)を足すところから始めるのが整えやすい並びです。