JavaScript 3/30: CSS變數

ZoeeeZhang發表於2019-03-03

JavaScript30 為Wes Bos推出的一項為期30天的挑戰,旨在幫助人們用純JavaScript來實現效果,初學者若想在JS方面快速精進,不妨一試。本題為第三題。

實現效果

本題當實現這樣的效果,利用JavaScript及CSS3來改變CSS的值,使得拖動滑塊及選中顏色時,可以實時調整圖片的內邊距(padding)、模糊度(blur)及背景顏色(background),同時標題中JS二字的顏色也隨之更改。

JavaScript 3/30: CSS變數

頁面基礎佈局

  <h2>Update CSS Variables with
    <span class='hl'>JS</span>
  </h2>

  <div class="controls">
    <label for="spacing">Spacing:</label>
    <input id="spacing" type="range" name="spacing" min="10" max="200" value="10" data-sizing="px">

    <label for="blur">Blur:</label>
    <input id="blur" type="range" name="blur" min="0" max="25" value="10" data-sizing="px">

    <label for="base">Base Color</label>
    <input id="base" type="color" name="base" value="#ffc600">
  </div>

  <img src="DSC01672.jpg">
複製程式碼

解題思路有兩種

一、

  • 獲取對應input元素;
  • 建立changeImg動作,獲取對應input元素的value值,並賦值給圖片的內邊距(padding)、模糊度(blur)及背景顏色(background);
  • 為每個input元素新增監聽事件,當發生change或是mouseover動作時,觸發changeImg動作,即時改變顏色或者滑塊值;

檢視我的demo程式碼

二、

  • CSS部分
    • 宣告全域性CSS變數;
    • 將變數與對應元素<img><hl >關聯;
  • JavaScript部分
    • 獲取對應input元素;
    • 建立changeImg動作,獲取對應input元素引數名及引數值,賦值給對應CSS變數blurspacingcolor
    • 為每個input元素新增監聽事件,當發生change或是mouseover動作時,觸發changeImg動作,即時改變顏色或者滑塊值。

檢視我的demo程式碼

第一種方法程式碼如下:

CSS部分程式碼

    body {
      text-align: center;
      background: #193549;
      color: white;
      font-family: 'helvetica neue', sans-serif;
      font-weight: 100;
      font-size: 50px;
    }

    img {
      width: 364.8px;
      height: 547.2px;
    }

    .controls {
      margin-bottom: 50px;
    }

    input {
      width: 100px;
    }
複製程式碼

JavaScript完整程式碼:

    const inputs = document.querySelectorAll('.controls input');
    const spacing = document.querySelector('#spacing');
    const blur = document.querySelector('#blur');
    const base = document.querySelector('#base');
    const image = document.querySelector('img');
    const h = document.querySelector('.hl');

    function changeImg() {
      image.style.padding = `${spacing.value}px`;
      image.style.filter = `blur(${blur.value}px)`;
      image.style.background = `${base.value}`;
      h.style.color = `${base.value}`;
    }

    inputs.forEach(input => input.addEventListener('mouseover', changeImg));
    inputs.forEach(input => input.addEventListener('change', changeImg));
複製程式碼

知識點

  • input標籤中type="range",呈現效果為可左右移動的滑動杆,如下所示:
  • 使用querySelectorAll('.controls input')獲得的 inputs,可返回一個nodelist,與Array有所區別,但同樣可以用forEach遍歷。
  • CSS濾鏡filter,即圖片濾鏡,可調整圖片特效,常見如模糊度blur(),明暗brightness(),對比度contrast()等,可以一次設定一個濾鏡也可以同時設定多個濾鏡,具體參考此處

第二種方法程式碼如下:

CSS部分程式碼

    :root {
      --spacing: 10px;
      --blur: 10px;
      --base: #ffffff;
    }

    img {
      padding: var(--spacing);
      filter: blur(var(--blur));
      background: var(--base);
      width: 364.8px;
      height: 547.2px;
    }

    .hl {
      color: var(--base);
    }

    body {
      text-align: center;
      background: #193549;
      color: white;
      font-family: 'helvetica neue', sans-serif;
      font-weight: 100;
      font-size: 50px;
    }

    .controls {
      margin-bottom: 50px;
    }

    input {
      width: 100px;
    }
複製程式碼

JS部分程式碼

    const inputs = document.querySelectorAll('.controls input');

    function changeImg() {
      const suffix = this.dataset.sizing || '';
      document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
    }

    inputs.forEach(input => input.addEventListener('change', changeImg));
    inputs.forEach(input => input.addEventListener('mouseover', changeImg));
複製程式碼

解題難點

1.如何處理引數值(前兩個有單位 px 、第三個沒有)

<input type="range" name="blur" min="0" max="25" value="10" data-sizing="px">
<input type="color" name="base" value="#8aa8af">
複製程式碼

可見前兩個input元素中,已設定data-sizing: "px",而只要加上 data- 字首,我們就可以運用dataset屬性來訪問所有含有data-的值。在JavaScript中,可以通過dataset.sizing來獲取單位。

const suffix = this.dataset.sizing || ''; 
複製程式碼

表示,針對前兩個引數值的單位為'px',針對顏色為空,以防報錯。

2.如何用 JavaScript 改變 CSS 屬性值?

JavaScript中,document.documentElement 即代表文件根元素。所以要改變全域性的 CSS 變數,可以這樣寫:

document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
複製程式碼

為了更好理解setProperty及聯絡解題思路一:

style.setProperty('padding', '15px');
/* 等同於 */
style.padding = '15px';
複製程式碼

實際應用中,前者的做法會更方便帶引數進去。

知識點

1.CSS變數

方法二的亮點在於建立了CSS變數,實際上,當我們需要構建大型站點時,使用CSS變數,能避免程式碼冗餘,可重複使用,同時,變數名稱本身包含語義資訊,使得CSS檔案更易。具體使用方法如下:

宣告一個全域性CSS 變數:
:root {
  --global-color: #666;
  --pane-padding: 5px 42px;
}
複製程式碼
使用一個全域性CSS 變數:
.demo{
   color: var(--global-color);
}
複製程式碼

其中:root 表示DOM元件的根元素,相當於<html>,常見於宣告全域性CSS變數。關於CSS變數,若想深入理解,可參閱這裡

2.模板字串

關於模板字串,其實在第一題就有提到,但值得注意的是,在寫法上,是使用反引號``包裹字串,而非'',記錄一筆,不能再犯,以防小哥哥再嚴肅地批評我!

相關文章