こんにちは。KOUKIです。
本記事は、Udemyの「50 Projects In 50 Days – HTML, CSS & JavaScript」で学習したことを載せています。
実装するもの
今回は、フィードバック機能を実装します。
demoは「こちら」で確認できます。
ワークスペース
必要なファイルは、以下の通りです。
1 2 3 4 5 |
$ 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 |
<!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>Custom Range Slider</title> </head> <body> <h2>Custom Range Slider</h2> <div class="range-container"> <input type="range" id="range" min="0" max="100"> <label for="range">50</label> </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 |
// 要素の取得 const range = document.getElementById('range') // レンジスライダーの状態変化時のイベント range.addEventListener('input', (e) => { // レンジスライダーの値を取得 // + は、string -> numberに変化させる const value = +e.target.value // label要素を取得 const label = e.target.nextElementSibling // レンジスライダーに設定されているwidth(XXpx)を取得 const range_width = getComputedStyle(e.target).getPropertyValue('width') // ラベルに設定されているwidth(XXpx)を取得 const label_width = getComputedStyle(label).getPropertyValue('width') // pxをとる(300px -> 300)、かつ、+でnum化 const num_width = +range_width.substring(0, range_width.length - 2) const num_label_width = +label_width.substring(0, label_width.length - 2) // レンジスライダーに設定している最大値、最小値 const max = +e.target.max const min = +e.target.min // レンジスライダーのleftスタイルに設定する値の計算 // レンジスライダーの値 * (レンジスライダーの幅 / レンジスライダーのmax値) - ラベルの幅 / 2 + スケール const left = value * (num_width / max) - num_label_width / 2 + scale(value, min, max, 10, -10) // スタイルへ適用 label.style.left = `${left}px` // labelの更新 label.innerHTML = value }) // scaleの計算 // 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; } |

スタイリング
これからCSSでスタイリングしていきます。項目に出てくるbodyやh2はHTMLの要素です。
また、今回は、ブラウザによってスタイルに影響が出やすいので、Chrome前提で実装を進めていきます。
全体の設定
1 2 3 4 5 6 7 |
/* フォント */ @import url("https://fonts.googleapis.com/css?family=Lato&display=swap"); * { /* padding/borderをwidth/heightに含める */ box-sizing: border-box; } |
bodyの設定
1 2 3 4 5 6 7 8 9 10 11 |
body { background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); font-family: "Lato", sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; overflow: hidden; margin: 0; } |

h2の設定
1 2 3 4 |
h2 { position: absolute; top: 10px; } |

range-containerの設定
1 2 3 |
.range-container { position: relative; } |

input[type=”range”]の設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
input[type="range"] { width: 300px; margin: 18px 0; /* WebKit ベースのブラウザー (Safari など) と Blink ベースのブラウザー (Chrome, Opera など) で 同じことを実現するために使用される。 なお、 Firefox や Edge もまた、互換性の理由から -webkit-appearance に対応している。 */ -webkit-appearance: none; } input[type="range"]:focus { /* 青線を消す */ outline: none; } |

input[type=”range”] + labelの設定
1 2 3 4 5 6 7 8 9 10 11 |
input[type="range"] + label { background-color: #fff; position: absolute; top: -25px; left: 110px; width: 80px; padding: 5px 0; text-align: center; border-radius: 4px; box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); } |

input[type=”range”]::-webkit-slider-runnable-trackの設定
1 2 3 4 5 6 7 8 |
/* Chrome & Safari */ input[type="range"]::-webkit-slider-runnable-track { background-color: purple; border-radius: 4px; width: 100%; height: 10px; cursor: pointer; } |

input[type=”range”]::-webkit-slider-thumbの設定
1 2 3 4 5 6 7 8 9 10 |
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; height: 24px; width: 24px; background: #fff; border-radius: 50%; border: 1px solid purple; margin: -7px; cursor: pointer; } |

これで、完成です。
その他ブラウザの設定
ついでに、他のブラウザの設定も記載しておきます。
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 |
/* Firefox */ input[type='range']::-moz-range-track { background: purple; border-radius: 4px; width: 100%; height: 13px; cursor: pointer; } input[type='range']::-moz-range-thumb { -webkit-appearance: none; height: 24px; width: 24px; background: #fff; border-radius: 50%; border: 1px solid purple; margin-top: -7px; cursor: pointer; } /* IE */ input[type='range']::-ms-track { background: purple; border-radius: 4px; width: 100%; height: 13px; cursor: pointer; } input[type='range']::-ms-thumb { -webkit-appearance: none; height: 24px; width: 24px; background: #fff; border-radius: 50%; border: 1px solid purple; margin-top: -7px; cursor: pointer; } |
おわりに
今回は、ブラウザの種類により、スタイリングの切り替えが必要でしたね。
私の場合は、Chrome100%なのであまり気にしていませんでしたが、Webデザインを専業にしている人たちは、このあたりも考慮してデザインしているのでしょうね。大変そうです。
実装するときは、Chrome,Safari, Firefox, IEあたりの主要なブラウザをインストールしておいて、動作確認したほうがいいと思います^^
それでは、また!
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 |
/* フォント */ @import url("https://fonts.googleapis.com/css?family=Lato&display=swap"); * { /* padding/borderをwidth/heightに含める */ box-sizing: border-box; } body { background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); font-family: "Lato", sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; overflow: hidden; margin: 0; } h2 { position: absolute; top: 10px; } .range-container { position: relative; } input[type="range"] { width: 300px; margin: 18px 0; /* WebKit ベースのブラウザー (Safari など) と Blink ベースのブラウザー (Chrome, Opera など) で 同じことを実現するために使用される。 なお、 Firefox や Edge もまた、互換性の理由から -webkit-appearance に対応している。 */ -webkit-appearance: none; } input[type="range"]:focus { /* 青線を消す */ outline: none; } input[type="range"] + label { background-color: #fff; position: absolute; top: -25px; left: 110px; width: 80px; padding: 5px 0; text-align: center; border-radius: 4px; box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); } /* Chrome & Safari */ input[type="range"]::-webkit-slider-runnable-track { background-color: purple; border-radius: 4px; width: 100%; height: 10px; cursor: pointer; } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; height: 24px; width: 24px; background: #fff; border-radius: 50%; border: 1px solid purple; margin: -7px; cursor: pointer; } /* Firefox */ input[type="range"]::-moz-range-track { background: purple; border-radius: 4px; width: 100%; height: 13px; cursor: pointer; } input[type="range"]::-moz-range-thumb { -webkit-appearance: none; height: 24px; width: 24px; background: #fff; border-radius: 50%; border: 1px solid purple; margin-top: -7px; cursor: pointer; } /* IE */ input[type="range"]::-ms-track { background: purple; border-radius: 4px; width: 100%; height: 13px; cursor: pointer; } input[type="range"]::-ms-thumb { -webkit-appearance: none; height: 24px; width: 24px; background: #fff; border-radius: 50%; border: 1px solid purple; margin-top: -7px; cursor: pointer; } |
コメントを残す
コメントを投稿するにはログインしてください。