CSS 實現搜尋相關互動

XboxYan發表於2021-11-03

先來看一個很常見的搜尋框的互動,大概邏輯如下

  1. 當輸入框有內容才顯示清除按鈕
  2. 點選清除按鈕輸入框會清空
  3. 當輸入框有內容並且處於聚焦情況下才顯示搜尋結果浮層
  4. 點選搜尋條目後關閉整個搜尋結果浮層

示意如下

Kapture 2021-10-30 at 16.00.02

看著邏輯好像很多的樣子,其實也是可以純 CSS 實現的,花兩三分鐘一起看看吧

一、輸入框清除按鈕的互動

首先來看原生的實現方式。

1. HTML5 新增表單元素

在 HTML5 中新增了type=search的表單,如下

<input class="input" type="search" placeholder="請輸入關鍵詞">

天然就支援清除功能

Kapture 2021-10-30 at 14.26.30

然後只需要美化一下預設的清除按鈕就可以了,chrome 中可以使用::-webkit-search-cancel-button,ie 中可以使用::ms-clear,這裡以 chrome 為例

[type=search]::-webkit-search-cancel-button{
    -webkit-appearance: none;
    width: 36px;
    height: 36px;
    border: 0;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'%3E%3C/path%3E %3C/svg%3E") center no-repeat;
    background-size: 16px;
    cursor: pointer;
    opacity: .4;
    transition: .2s;
}

這樣就可以了

Kapture 2021-10-30 at 15.27.02

2. firefox 下的實現

不過呢,上面這種方式在 firefox 中是無效的,firefox 中並沒有清除按鈕,表現和普通輸入框一致(下圖為firefox表現)

Kapture 2021-10-30 at 15.30.16

如果是 PC 端並且面向使用者,firefox 還是不能忽略的,那如何處理呢?

可以先手動新增一個按鈕

<input class="input" type="search" placeholder="請輸入關鍵詞">
<button class="clear"></button>

然後適當美化一下(相信不是什麼難事),可以得到這樣的效果

image-20211029172242444

現在清除按鈕和輸入框沒啥關聯,如何做到有輸入內容時才顯示清除按鈕呢?

可以這樣來思考:有內容表示非空,表示必填項,提到必填項可以想到 required 屬性,當有內容時,表示合法的,可以匹配:valid選擇器,這樣就能區分開來了。具體實現如下

input加一個required屬性

<input class="input" placeholder="請輸入關鍵詞" required>
<button class="clear"></button>

然後預設隱藏清除按鈕,配合相鄰選擇器+就可以實現啦~

.clear{
    visibility: hidden;
}
.input:valid+.clear{
    visibility: visible;
}

效果如下(下圖為firefox表現)

Kapture 2021-10-29 at 17.43.54

然後是清除輸入框的功能,如果不借助 JS,有什麼辦法可以清空輸入框呢?

在 HTML5 表單中,可以通過 type=reset直接重置所有內容,所以這裡需要修改一下結構,將外層 div改為form,然後給button新增type=reset屬性,如下

<form class="search">
    <input class="input" placeholder="請輸入關鍵詞">
      <button class="clear" type="reset"></button>
</form>

這樣就能清空搜尋框了(下圖為firefox表現),當然其他瀏覽器也是支援的

Kapture 2021-10-29 at 19.03.37

這種方式略有遺憾的地方是清除以後輸入框沒能聚焦

二、搜尋提示浮層自動顯示

先加上搜尋提示的 HTML 結構

<div class="search">
  <input class="input" placeholder="請輸入關鍵詞" />
  <div class="search-list">
        <a class="search-item">搜尋結果1</a>
        <a class="search-item">搜尋結果2</a>
        <a class="search-item">搜尋結果3</a>
    </div>
</div>

搜尋結果預設是隱藏的,然後在輸入框有內容(:valid),並且在聚焦情況下(:focus)才顯示,配合兄弟選擇器~可以實現如下:

.search-list{
      position: absolute;
    visibility: hidden;
}
.input:focus:valid~.search-list{
    visibility: visible;
}

效果如下

Kapture 2021-10-30 at 16.00.02

三、搜尋提示浮層上的事件

上面的效果看著好像沒啥問題,點選搜尋條目後整個搜尋結果確實關閉了。

但其實只要是有問題的,點選關閉是由於輸入框失去了焦點,如果在搜尋條目上新增點選事件,有可能還沒觸發事件就關閉了,比如

<form class="search">
    <input class="input" placeholder="請輸入關鍵詞">
    <div class="search-list">
        <a class="search-item" onclick="console.log(1)">搜尋結果1</a>
        <a class="search-item">搜尋結果2</a>
        <a class="search-item">搜尋結果3</a>
    </div>
</form>

效果如下,在點選的時候並沒有觸發 click 事件(控制檯沒有列印)

Kapture 2021-10-29 at 19.28.24

原因其實很簡單,click 其實可以看成是 mousedown → mouseup,在 mousedown 後立刻失焦,還沒等 mouseup 就關閉提示懸浮層了,所以事件並未觸發。

為了解決這個問題,可以把 onclick換成onmousedown,但是這樣顯然沒有從根本解決,比如很多時候搜尋條目上是href屬性

<div class="search-list">
   <a class="search-item" href="?id=1">搜尋結果1</a>
</div>

這樣也無法正確的跳轉。

那如何解決呢?

這裡有一個非常簡單的小技巧,在點選的時候強制顯示不就可以了嗎?點選可以用:active來匹配,所以可以這樣來實現:

.input:focus:valid~.search-list,
.search-list:active{ /*點選的時候也顯示*/
    visibility: visible;
}

這樣就能正常的觸發點選和跳轉事件了(控制檯有列印)

Kapture 2021-10-29 at 19.44.01

完整程式碼可以訪問 CSS search (codepen.io)

相容 firefox 的完整程式碼可以訪問 CSS search firefox (codepen.io)

四、總結和說明

以上實現了一個搜尋輸入相關的互動效果,沒有佈局方面的技巧,核心在於選擇器的合理使用,下面總結一下實現重點:

  1. 輸入框可以使用 HTML5 新增的 type=search屬性,天然支援清除功能,可惜 firefox 不支援
  2. 輸入框設定 requred 屬性後結合 :valid 選擇器可以判斷是否有內容
  3. form 表單裡可以通過 type=resetbutton 重置輸入的內容
  4. 點選失效的原因是輸入框先於點選事件失焦,可以用 :active來匹配點選相關行為
  5. 各種選擇器結合使用可以實現更加靈活的互動效果
  6. 相容性 IE 10+,幾乎可以生產環境使用

使用 CSS 完成互動的好處是容錯率更高,不會導致網站崩潰,效能也更好,很多時候 js 出現錯誤導致整個網站直接白屏,完全不可用,CSS 就不存在這樣的問題啦~ 如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤

相關文章