1. 程式人生 > >CSS並不簡單--個性化輸入框的實踐

CSS並不簡單--個性化輸入框的實踐

這次通過這個個性化的輸入框,給大家介紹一些容易忽略的知識點。(新手注意:本文的html採用的是jade,css採用的sass,js採用的vue)

一、效果

 大家先看一下效果動態圖,思考一波,帶著你的思考來看接下來的內容,可能效果更好一點。

image

二、需求

 當我們開始做一樣東西的時候一定要先分析它的需求:
 * 當輸入框獲取焦點時,提示文字發生上移動畫,同時下面線條產生動畫;
 * 當輸入框失去焦點時,並且未填寫內容時,提示文字和線條恢復之前的狀態。
 * 當輸入框失去焦點時,填寫內容時,狀態不變。

三、結構

 看了上面的效果圖,首先就是要確定html的結構:

div.item
    input(type="text" name="card" id="card" placeholder="身份證" v-card="" maxlength="18")
    label(for="card") Card
    div.focusline

 這裡唯一遺憾的是input不支援偽元素(::after、::before),所以不得不採用一個額外的div。
 這裡額外提一下,maxlength 只能用於input的type為password和text的情況,所以不要再問為什麼maxlength不起作用了。

四、表現

 其實對於上面所要實現的效果,我們完全可以通過JS來控制,但是一直在強調表現(CSS)與行為(JS)分離

,所以我們完全通過CSS的特性解決表現上的問題,更加完美。但是並不是所有CSS屬性瀏覽器多支援(這就尷尬了)。這裡我要用的幾個特性,大家最好在Chrome中實驗。

 其實需求1與需求2是同一個需求,通過偽類focus和過渡屬性就能搞定。

    input:focus + label {
        color: rgb(82,97,107);
        transform: translate(10px, 0) scale(.9);
    }
    input:focus ~ div {
        width: 100%;
    }

 對於第三個需求,我們就得用一些新玩意了,第一個就是偽元素placeholder(偽類採用: 而偽元素採用::

), 這裡我們要隱藏placeholder,好顯示我們的label:

    input {
      &:placeholder {
          opacity: 0;
      }
    }

 我們知道當輸入文字後,placeholder就不再顯示了,所以這裡來了一個偽類placeholder-shown(可以通過can i use 查一下它的相容性):

    input:not(:placeholder-shown) + label {
      color: rgb(82,97,107);
      transform: translate(10px, 0) scale(.9);
    }
    input:not(:placeholder-shown) ~ div {
      width: 100%;
    }

五、行為

 這裡我還要嘮叨一下,從上面可以看出這是一個身份證輸入框,我們多知道身份證是由數字和字母,而且字母只出現在第18位,而且只能是字母x。所以我上面採用了text型別的輸入框,為了讓使用者很好的輸入,會出現這幾種問題:
 * 切換為中文輸入法時存在的問題;
 * 複製貼上的問題;
 * 輸入其他非法字元的處理。

 這裡我們主要通過input、compositionstart、compositionend、paste四個事件解決。

    let legalContent, //開啟輸入法之前的輸入內容
        LOCK = false; //是否開啟中文輸入法
    el.addEventListener('compositionstart', (e) => {
      /**
       * --------------
       *  開啟中文輸入法
       * --------------
       */
      legalContent = e.target.value; //儲存中文輸入法之前的內容
      LOCK = true; //加上鎖
    }, false);

    el.addEventListener('compositionend', (e) => {
      /**
       * ---------------------
       *  結束中文輸入法
       * ---------------------
       */
      e.target.value = legalContent;
      LOCK = false; // 解鎖
    }, false);


    el.addEventListener('input', (e) => {
      const len = e.target.value.length;

      /**
       * 在中文觸發時 不進行處理
       * 當身份證號碼少於18位時只能輸入數字
       * 當身份證號碼為18位時可以輸入數字和字母
       */
      if (!LOCK) {
        if (len <= 17) {
          e.target.value = e.target.value.replace(/\D/,'');
        } else {
          e.target.value = e.target.value.replace(/[^0-9Xx]/,'');
        }
      }

    }, false);


    el.addEventListener('paste', (e) => {
      /**
       * ----------
       *  貼上
       * ----------
       */
      e.preventDefault();  //阻止預設事件
    }, false);

覺得不錯的同學,來一波關注吧,你的關注就是我寫作的動力。
更多文章 簡書
原始碼: GitHub