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

clipboard.png

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

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

clipboard.png

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

clipboard.png

2. 添加邊界code

這一步實現難點在於寬度須要與文本的末尾保持一致,也須要與任何font-familyfont-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%;
}

效果是這樣:

clipboard.png

接下來,添加一個頂部邊框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;
}

v2-1fe27e5cf17e125a6689e9651ab47632_hd.jpg

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跨度來限制其寬度,不然會致使容器水平拉伸

v2-5f903690cf9e06a1477556a72b7d5f30_b.gif

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;
    }
  }
}

大概就這樣 ~

原文連接:Text input highlight, TripAdvisor style

相關文章
相關標籤/搜索