如何實現「文字輸入高亮」的效果

簡評:TripAdvisor(中文網站為「貓途鷹」)的搜索輸入框有文字高亮的效果很有意思,本文將分享如何一步一步建立這種效果。

下圖即為 TripAdvisor 搜索輸入框的「文字輸入高亮」效果,這個實現涉及 CSS 和 JavaScript 的知識。

TripAdvisor 的搜索輸入框

這是已完成的 CodePen:Tripadvisor input highlight


1. 我們首先創建一個簡單的 React 組件

class App extends React.Component {n render() {n return (n <div className=input-wrapper>n <inputn placeholder=Search...n spellCheck={false}n />n </div>n );n }n}nReactDOM.render(n <App />,n document.getElementById(root)n);n

添加 CSS:

$input-font-size: 30px;n$input-line-height: 70px;n$font-family: Roboto Slab, sans-serif;nbody {n background-color: #222222;n}n.input-wrapper {n width: 500px;n margin: 50px auto;n}ninput {n height: 60px;n width: 100%;n min-width: 100%;n padding: 0;n border-radius: 0;n line-height: $input-line-height;n background-color: transparent;n color: white;n font-size: $input-font-size;n border: none;n outline: none;n border-bottom: 3px solid #333333;n font-family: $font-family;n}n

添加 HTML 容器:

<div id="root"></div>n

之後我們就得到下圖這個基本文字輸入界面:

2. 添加邊界

這一步實現難點在於寬度需要與文本的末尾保持一致,也需要與任何font-familyfont-size保持協同。

由於輸入元素width是固定的,我們需要一些其他方法來檢測文本的末尾。

我們通過提供一個道具來將輸入從非受控狀態切換到受控狀態value,於是 React 組件現在是這樣子的:

class App extends React.Component {n render() {n return (n <div className=input-wrapper>n <inputn placeholder=Search...n spellCheck={false}n value=basic input, bottom bordern />n <span className=input-highlight>n basic input, bottom bordern </span>n </div>n );n }n}n

添加以下 CSS 規則 input-highlight

注意:我們在這裡使用 SCSS 變數來確保和font之間的屬性相同:inputspan

.input-highlight {n font-size: $input-font-size;n line-height: $input-line-height;n font-family: $font-family;n max-width: 100%;n}n

效果是這樣:

接下來,添加一個頂部邊框span和位置,使其邊框疊加輸入的底部邊框。

.input-highlight {n font-size: $input-font-size;n line-height: $input-line-height;n font-family: $font-family;n max-width: 100%;n border-top: 3px solid white;n position: absolute;n left: 0;n bottom: 0;n height: 0;n}n.input-wrapper {n width: 500px;n margin: 50px auto;n position: relative;n}n

span 元素以文本結尾,這使得它的寬度與輸入文本寬度一致。

現在,簡單的部分是:每次輸入內容發生變化時,我們使用 JavaScript 來更新跨度中的文本。我們將使用 React state來同時更新輸入和跨度的值。

這是我們更新的組件:

class App extends React.Component {n constructor() {n super();n this.state = {n inputValue: n };n n this.onInputChange = this.onInputChange.bind(this);n }nonInputChange(e) {n const { value } = e.target;n this.setState({n inputValue: valuen });n }nrender() {n const { inputValue } = this.state;n n return (n <div className=input-wrapper>n <inputn onChange={this.onInputChange}n placeholder=Search...n value={inputValue}n spellCheck={false}n />n <span className=input-highlight>n { inputValue.replace(/ /g, "?") }n </span>n </div>n );n }n}n

.replace(/ /g, "?") 這部分是 React 正確處理空間所必需的。

然後,通過將以下行添加到input-highlightCSS 選擇器來隱藏該跨度:

color: transparent;nuser-select: none;noverflow: hidden;n

我們需要overflow: hidden跨度來限制其寬度,否則會導致容器水平拉伸

3. 大功告成

最後一步是為高光添加不同的onFocus顏色。

要做到這一點,我們需要一種基於輸入的焦點狀態來設置範圍的方式,我們將使用 CSS 兄弟選擇器(+)。

這裡是完整input選擇器的代碼,包括兄弟選擇器input-highlight

input {n height: 60px;n width: 100%;n min-width: 100%;n padding: 0;n border-radius: 0;n line-height: $input-line-height;n background-color: transparent;n color: white;n font-size: $input-font-size;n border: none;n outline: none;n border-bottom: 3px solid #333333;n font-family: $font-family;n &:focus {n + .input-highlight {n border-top: 3px solid #fbc91b;n }n }n}n

大概就這樣 ~


原文鏈接:Text input highlight, TripAdvisor style

推薦閱讀:YouTube 上有哪些自學編程的優質頻道

極光日報,極光開發者 的 Side Project,歡迎關注。


推薦閱讀:

新手向 · CSS選擇器
你還在記css的賦值順序嗎?
為什麼有些網站的版權不用©而用??
使用CSS技術實現Netflix Logo動畫效果

TAG:CSS | 前端开发 | TripAdvisor |