修改 input type=''range'' 之 CSS 樣式

MOMOJ 哞哞人
MO Learning
Published in
10 min readFeb 16, 2021

◆ 使用 webkit 排版引擎之 CSS 偽元素(pseudo-element)修改滑動條預設樣式

為了練習 DOM 操作,以網頁版 RGB 轉換器當作題目,想要修改<input type=''range''> 之 CSS 樣式時遇到了一些困難,以此文章記錄解決過程。

這是 RGB 轉換器的畫面,有三個滑動條可以改動顏色三通道的數值 : 紅色 (R)、綠色 (G)、藍色 (B),滑動條數值介於 0~255 之間,滑動的同時可以改動背景顏色,也會顯示對應的 16 進制色碼。

RGB 轉換器網頁介面
RGB 轉換器網頁介面

畫面中的滑動條是用 HTML <input> 所建立出來的,用法如下 : input 型態為 range、滑動條最小值設 0、滑動條最大值設 255、滑動步輻設 1、滑動條初始值設 128。而畫面中所呈現的滑動條是預設的 CSS 樣式。

<input type="range" min="0" max="255" step="1" value="128">

在修改 CSS 環節發現 input range 樣式沒有反應,網路查找才發現由於 range 是 input 的一種類型,因此無法用一般 CSS 編輯方法修改樣式。欲修改的目標樣式,就只有單純呈現滑動軌道灰色,滑動鈕為白色,其他形狀樣式與預設相同即可,找了幾篇文章嘗試修改,卻都得不到想要的效果,最後才在 stackoverflow 上找到比較容易理解的修改方法,並補強一些概念知識。

input range 樣式修改目標
input range 樣式修改目標

CSS 偽元素(pseudo-element)與偽類(pseudo-class)

這邊選用了::-webkit-slider-thumb 與 ::-webkit-slider-runnable-track 兩種 CSS 偽元素來修改 input range 樣式,因此先來簡單介紹一下 CSS pseudo-element。

A CSS pseudo-element is used to style specified parts of an element. — w3schools

Pseudo-elements create abstractions about the document tree beyond those specified by the document language. — W3C Recommendation

根據上面對偽元素的解釋 :

  • 若要對一個元素的指定部分進行樣式修改,可以使用偽元素進行操作。
  • 偽元素不存在於 DOM tree 中,其概念就是,針對 DOM tree 元素的指定部分,創造出一個新的抽象元素。

舉例來說 ::first-line 是一個常見的偽元素,對應到選取元素的第一行內容,但在 DOM tree 中並不會有一個節點,存放某元素的第一行內容;::first-letter也是一個常見的偽元素,對應到選取元素的第一個字,同理,在 DOM tree 中並不會有一個節點,存放某元素的第一個字。

這邊列出常見的偽元素 :

  • ::first-letter 選取元素的第一個字
  • ::first-line 選取元素的第一行
  • ::before 在選取元素之前插入內容
  • ::after 在選取元素之後插入內容
  • ::selection 選取元素被使用者反白的部分內容

在 CSS 中,若在選擇器後看到單冒號 (:),代表是使用偽類(pseudo-class) ;而看到雙冒號 (::),代表是使用偽元素(pseudo-element) 。這篇主要使用偽元素,因此偽類只會提一點概念,有機會再寫一篇來介紹。

A pseudo-class is used to define a special state of an element. — w3schools

偽類是用來定義 DOM tree 元素的某一種狀態。例如 :hover 是常使用的偽類,用來定義當滑鼠經過某個 DOM tree 元素上方時的狀態; :active 也是常使用的偽類,用來定義當點選某個 DOM tree 元素時的狀態。

偽類與偽元素兩者的差異,我的理解大概就是,前者是操作存在元素的狀態為主,而後者是操作元素的指定部分為主。

修改 input range 之 CSS 樣式

簡單介紹完偽元素以後,修改 input range 之 CSS 樣式方法就比較好理解了 !

前面提到我們選用了::-webkit-slider-thumb 與 ::-webkit-slider-runnable-track 兩種 CSS 偽元素來修改 input range 樣式,前者可以操作 input range 的滑動鈕部分;後者則可以操作 input range 的滑動軌道部分。

我們需要先將預設樣式關閉才可以做自訂義的樣式修改,這邊會動到 webkit 的 appearance 屬性,預設是 normal,讓一些 HTML 元素呈現瀏覽器預設介面樣式,該屬性是可以進行修改的。將 -webkit-appearance 設定成 none 即可。

The CSS -webkit-appearance property enables web authors to change the appearance of HTML elements to resemble native User Interface (UI) controls. — Quackit

/* remove default style */
input[type="range"],
input[type="range"]::-webkit-slider-runnable-track,
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
}
取消 input range 預設樣式
取消 input range 預設樣式

從上面 CSS 可以發現, input range 元素被拆成三個部分來設定 : input range 元素主體、滑動軌道與滑動鈕。將預設樣式關閉後,就可以把自訂義樣式慢慢構建出來,圖示為修改範例,透過三種顏色與不同大小的區塊,幫助理解元素拆解關係,白底對應到 input range 元素主體,滑動軌道與滑動鈕算是 input range 元素主體的內容;灰底對應到滑動軌道;而紅底對應到滑動鈕。

input range 元素拆解
input range 元素拆解

滑動軌道與滑動鈕的寬高會受到 input range 主體影響,因此先設定 input range 主體的 CSS 樣式是比較恰當的,接著再設定滑動軌道與滑動鈕樣式。圖示的上列呈現樣式修改的過程結果,分別為 input range 主體樣式結果、加上滑動軌道樣式結果、加上滑動鈕樣式結果。而圖示的下列則是我希望的呈現結果,把為了解釋方便的背景色樣式改掉而已。

/* CSS */
/* input range 主體樣式 */
input[type="range"] {
height: 30px;
width: 180px;
overflow: hidden;
cursor: pointer; /* 滑鼠放上會改變鼠標樣式 */
outline: none; /* 取消底線效果 */
background-color: white; /* 為了解釋方便所設定 */
/* background-color: grey; */ /* 我的目標樣式 */
margin: 0 10px 0;
}
/* 滑動軌道 樣式 */
input[type="range"]::-webkit-slider-runnable-track {
height: 6px;
width: 180px;
border-radius: 4px;
background: #aaa;
}
/* 滑動鈕 樣式 */
input[type="range"]::-webkit-slider-thumb {
position: relative;
height: 16px;
width: 16px;
margin-top: -5px; /* 會受到寬高影響定位,需微調 */
background-color: tomato; /* 為了解釋方便所設定 */
/* background-color: white; */ /* 我的目標樣式 */
border-radius: 50%;
border: 1px solid black;
}
input range 樣式修改過程與最終結果
input range 樣式修改過程與最終結果

有嘗試發現,除了直接用 input[type="range"] 修改樣式外,亦能使用選擇器對不同滑動條,修改出不同的樣式。

/* 使用 id 選擇器 改動不同滑動條的樣式 */
#bar-red,
#bar-red::-webkit-slider-runnable-track,
#bar-red::-webkit-slider-thumb { /* CSS setting A */ }
#bar-green,
#bar-green::-webkit-slider-runnable-track,
#bar-green::-webkit-slider-thumb { /* CSS setting B */ }
#bar-blue,
#bar-blue::-webkit-slider-runnable-track,
#bar-blue::-webkit-slider-thumb { /* CSS setting C*/ }

input range 的 CSS 樣式已經成功自訂義修改了,最後就是用 JavaScript 操作 DOM,動態更改 input range 背景色,與當下色碼對應即可。下面只列出 input range 之 HTML 設定與部分 Javascript 處理代碼,動態改動三個 input range 背景色的部分。

<!--HTML-->
<!--input range HTML 設定-->
<input class="value-selector" type="range" min="0" max="255" step="1" value="128">
// JavaScript
const valueSelector = document.querySelectorAll(".value-selector");
// input 事件監聽器掛在父元素上
xxxxxx.addEventListener("input", (event) => {

// some code

valueSelector.forEach((valueSelect) => {
valueSelect.style.backgroundColor = `${currentRGB}`;
});
}
RGB 轉換器最終樣式成果
RGB 轉換器最終樣式成果

※ 有任何錯誤或描述不夠精準之處,歡迎給予指教,非常感謝您的閱覽。

※ 如果喜歡我的文章,請幫我拍拍手哦 !

--

--

MOMOJ 哞哞人
MO Learning

哞哞人_在軟體工程的路上_慢慢爬~ 技術筆記文章傳送門:https://medium.com/mo-learning