簡評: TripAdvisor(中文網站爲「貓途鷹」)的搜索輸入框有文字高亮的效果頗有意思,本文將分享如何一步一步創建這種效果。
下圖即爲 TripAdvisor 搜索輸入框的「文字輸入高亮」效果,這個實現涉及 CSS 和 JavaScript 的知識。git
TripAdvisor 的搜索輸入框
這是已完成的 CodePen:Tripadvisor input highlightgithub
1. 咱們首先建立一個簡單的 React 組件app
class App extends React.Component { render() { return ( <div className='input-wrapper'> <input placeholder='Search...' spellCheck={false} /> </div> ); } } ReactDOM.render( <App />, document.getElementById('root') );
添加 CSS:網站
$input-font-size: 30px; $input-line-height: 70px; $font-family: Roboto Slab, sans-serif; body { background-color: #222222; } .input-wrapper { width: 500px; margin: 50px auto; } input { height: 60px; width: 100%; min-width: 100%; padding: 0; border-radius: 0; line-height: $input-line-height; background-color: transparent; color: white; font-size: $input-font-size; border: none; outline: none; border-bottom: 3px solid #333333; font-family: $font-family; }
添加 HTML 容器:this
<div id="root"></div>
以後咱們就獲得下圖這個基本文字輸入界面:spa
2. 添加邊界code
這一步實現難點在於寬度須要與文本的末尾保持一致,也須要與任何font-family
和font-size
保持協同。ip
因爲輸入元素width
是固定的,咱們須要一些其餘方法來檢測文本的末尾。get
咱們經過提供一個道具來將輸入從非受控狀態切換到受控狀態value,因而 React 組件如今是這樣子的:input
class App extends React.Component { render() { return ( <div className='input-wrapper'> <input placeholder='Search...' spellCheck={false} value='basic input, bottom border' /> <span className='input-highlight'> basic input, bottom border </span> </div> ); } }
添加如下 CSS 規則 input-highlight
注意:咱們在這裏使用 SCSS 變量來確保和font
之間的屬性相同:inputspan
.input-highlight { font-size: $input-font-size; line-height: $input-line-height; font-family: $font-family; max-width: 100%; }
效果是這樣:
接下來,添加一個頂部邊框span和位置,使其邊框疊加輸入的底部邊框。
.input-highlight { font-size: $input-font-size; line-height: $input-line-height; font-family: $font-family; max-width: 100%; border-top: 3px solid white; position: absolute; left: 0; bottom: 0; height: 0; } .input-wrapper { width: 500px; margin: 50px auto; position: relative; }
span 元素以文本結尾,,這使得它的寬度與輸入文本寬度一致。
如今,簡單的部分是:每次輸入內容發生變化時,咱們使用 JavaScript 來更新跨度中的文本。咱們將使用 React state來同時更新輸入和跨度的值。
這是咱們更新的組件:
class App extends React.Component { constructor() { super(); this.state = { inputValue: '' }; this.onInputChange = this.onInputChange.bind(this); } onInputChange(e) { const { value } = e.target; this.setState({ inputValue: value }); } render() { const { inputValue } = this.state; return ( <div className='input-wrapper'> <input onChange={this.onInputChange} placeholder='Search...' value={inputValue} spellCheck={false} /> <span className='input-highlight'> { inputValue.replace(/ /g, "\u00a0") } </span> </div> ); } }
.replace(/ /g, "\u00a0")
這部分是 React 正確處理空間所必需的。
而後,經過將如下行添加到input-highlightCSS
選擇器來隱藏該跨度:
color: transparent; user-select: none; overflow: hidden;
咱們須要overflow: hidden
跨度來限制其寬度,不然會致使容器水平拉伸
3. 大功告成
最後一步是爲高光添加不一樣的onFocus
顏色。
要作到這一點,咱們須要一種基於輸入的焦點狀態來設置範圍的方式,咱們將使用 CSS 兄弟選擇器(+
)。
這裏是完整input
選擇器的代碼,包括兄弟選擇器input-highlight
:
input { height: 60px; width: 100%; min-width: 100%; padding: 0; border-radius: 0; line-height: $input-line-height; background-color: transparent; color: white; font-size: $input-font-size; border: none; outline: none; border-bottom: 3px solid #333333; font-family: $font-family; &:focus { + .input-highlight { border-top: 3px solid #fbc91b; } } }
大概就這樣 ~