ブランドの一貫性を保つ範囲スライダー

ネイティブの範囲入力を使用する

<div> 要素やカスタム ポインタ ハンドラを使用してスライダーを再作成するのではなく、ラベル付きの <input type="range"> を使用します。ネイティブ コントロールでは、キーボードとポインタの操作、タッチ動作、ユーザー補助機能のサポートが維持されます。ユースケースに合わせて min、max、step、value を構成します。

<label for="range-slider">Volume</label>
<input type="range" id="range-slider" value="70"/>

値にフォーマットされたラベルまたは単位が必要な場合は、通常の DOM コンテンツで公開し、変更時に aria-valuetext を更新します。フォーム コントロールで生成されたコンテンツは相互運用できないため、スライダーの疑似要素で ::before または ::after を使用しないでください。つまみに追従するツールチップが必要な場合は、CSS アンカー ポジショニングを使用してつまみに固定します。反転しても正しい向きを維持するツールチップについては、位置認識ツールチップをご覧ください。

スタイル設定方法を選択する

簡単な色のカスタマイズには、ブランドの一貫性を保つフォームを使用し、ブラウザのネイティブ レンダリングを保持します。

input[type="range"] {
  accent-color: var(--brand-color);
}

accent-color は、完全なスライダー スタイル設定 API ではありません。つまみ、トラック、塗りつぶしへの影響は、ユーザー エージェントによって異なります。トラック、つまみ、サイズ、形状、塗りつぶしを制御する必要がある場合は、以下の疑似要素を使用します。

トラックとつまみのスタイルを設定する

appearance: none、margin: 0、border: 0 を使用して、デフォルトの OS スタイルをリセットします。クロスブラウザ レンダリングを正規化するには、WebKit と Firefox の疑似要素を別々のルールブロックで宣言し、margin-block-start: calc((var(--slider-track-size) - var(--slider-thumb-size)) / 2) を使用して WebKit のつまみを中央に配置します(Firefox ではつまみが自動的に中央に配置されます)。テーマが疑似要素を直接ターゲットにしないように、一般ユーザー向けの値を入力のカスタム プロパティとして保持します。

input[type="range"] {
  --slider-track-size: 0.5rem;
  --slider-thumb-size: 1.25rem;
  --slider-track-radius: 999px;
  --slider-thumb-radius: 50%;
  --slider-track-color: #d9d9d9;
  --slider-fill-color: #06c;
  --slider-thumb-color: var(--slider-fill-color);
  --slider-direction: to right;

  /* reverse gradient direction for right-to-left layouts */
  &:dir(rtl) {
    --slider-direction: to left;
  }

  /* Read min and max from attributes; --control-value is synced by the script below. */
  --attr-min: attr(min type(<number>), 0);
  --attr-max: attr(max type(<number>), 100);
  --control-value: attr(value type(<number>), 50);
  --slider-progress: calc(
    progress(var(--control-value), var(--attr-min), var(--attr-max)) * 100%
  );

  appearance: none;
  inline-size: 100%;
  block-size: 2.5rem; /* Preserve a generous interaction area. */
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}

/* WebKit/Blink. */
input[type="range"]::-webkit-slider-runnable-track {
  block-size: var(--slider-track-size);
  border: 0;
  border-radius: var(--slider-track-radius);
  background: linear-gradient(
    var(--slider-direction),
    var(--slider-fill-color) var(--slider-progress),
    var(--slider-track-color) var(--slider-progress)
  );
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  inline-size: var(--slider-thumb-size);
  block-size: var(--slider-thumb-size);
  margin-block-start: calc(
    (var(--slider-track-size) - var(--slider-thumb-size)) / 2
  );
  border: 0;
  border-radius: var(--slider-thumb-radius);
  background: var(--slider-thumb-color);
}

/* Firefox. */
input[type="range"]::-moz-range-track {
  block-size: var(--slider-track-size);
  border: 0;
  border-radius: var(--slider-track-radius);
  background: var(--slider-track-color);
}

input[type="range"]::-moz-range-progress {
  block-size: var(--slider-track-size);
  border-radius: var(--slider-track-radius);
  background: var(--slider-fill-color);
}

input[type="range"]::-moz-range-thumb {
  inline-size: var(--slider-thumb-size);
  block-size: var(--slider-thumb-size);
  border: 0;
  border-radius: var(--slider-thumb-radius);
  background: var(--slider-thumb-color);
}

ネイティブの外観を削除した後は、必ずキーボード フォーカス インジケーターを表示します。色だけを使用しない:

input[type="range"]:focus-visible {
  outline: 2px solid var(--slider-fill-color);
  outline-offset: 4px;
}

アクティビティ追跡のスタイルを設定する

トラックの塗りつぶされた部分が塗りつぶされていないトラックとは異なるスタイルになっている場合、Firefox は ::-moz-range-progress を介してそれを公開します。WebKit / Blink には同等の疑似要素がないため、input イベントでライブ入力値を --control-value に同期します。

const slider = document.querySelector('#range-slider');

function syncSliderValue() {
  slider.style.setProperty('--control-value', slider.value);
}

syncSliderValue();
slider.addEventListener('input', syncSliderValue);

制限事項

  • WebKit と Firefox の疑似セレクタを 1 つのカンマ区切りのリスト(::-webkit-slider-thumb, ::-moz-range-thumb など)に結合しないでください。認識されないベンダーの疑似要素が検出されると、ブラウザはルール全体を破棄します。

フォールバック

accent-color のフォールバックとブラウザ サポート

accent-color プロパティはプログレッシブ エンハンスメントです。このプロパティをサポートしていないブラウザでは、このプロパティは無視され、デフォルトの UI カラーが使用されます。

progress() と attr() のフォールバックとブラウザ サポート

progress() がサポートされていない場合は、calc() を使用して --slider-progress を計算します。

@supports not (opacity: progress(1, 0, 100)) {
  input[type="range"] {
    --slider-progress: calc(
      (var(--control-value) - var(--attr-min)) /
      (var(--attr-max) - var(--attr-min)) * 100%
    );
  }
}

型指定された attr() がサポートされていない場合は、JavaScript で入力の min 属性と max 属性から --attr-min と --attr-max を同期します。

function syncSliderValue() {
  slider.style.setProperty('--attr-min', slider.min || 0);
  slider.style.setProperty('--attr-max', slider.max || 100);
  slider.style.setProperty('--control-value', slider.value);
}