纯CSS实现可展开搜索框

@Pelom  November 18, 2021

前言

常用的搜索图标是一个放大镜,不需要任何文字描述,人们就知道点击它进行搜索。很久之前看到一个奇妙的搜索图标,点击之后放大镜的圈会展开成为一个搜索框,而放大镜的柄会变成一个叉,点击之后就可以整个再折叠回去。当初看到的时候感到很有趣,前不久又想起来,决定复刻一下

示例

实现

  1. 思路是用伪元素充当放大镜的柄,但可惜的是,<input type="text">并不支持伪元素(因为它没有内容物),因此只能再用一个<div></div>包起来

    <div id="searchbox">
        <input type="text" placeholder="Type to search" autocomplete="off">
    </div>
  2. 先来给<input>加上展开的效果:触发:focus后,直接用padding把圈撑大,再让width增加
    transition中设置延时(第三个参数),如果在原处和伪类处设置不同的transition,那么会由于覆盖导致正向和反向时有不同的效果

    • 记得设置outline: none,不然点击后有外框

      #searchbox>input{
       width: 1.2rem;
       height: 1.2rem;
       position: absolute;
       top: 0;
       right: 0;
       box-sizing: border-box;
       outline: none;
       padding: .6rem;
       border: .2rem solid skyblue;
       border-radius: 2rem;
       background: transparent;
       transition: width .3s, padding .1s .4s;
      }
      #searchbox>input:focus{
       width: 20rem;
       padding: 1rem;
       background: whitesmoke;
       transition: width .3s .2s, padding .1s;
      }
  3. 然后考虑放大镜的柄,分别用<div>的两个伪元素实现(定位需要仔细找一下)
    由于伪元素在父元素上,<input>:focus不能触发它,所以我们使用:focus-within伪类,它可以被focus事件的冒泡触发

    • 记得设置z-index,不然会被<input>遮住

      #searchbox::before, #searchbox::after{
       content: '';
       width: .9rem;
       height: .1rem;
       position: absolute;
       right: -.4rem;
       top: 1.1rem;
       background-color: skyblue;
       transform: rotate(45deg);
       z-index: 1;
       transition: top .1s .4s, right .1s .4s, transform .1s .2s;
      }
      #searchbox:focus-within::before, #searchbox:focus-within::after{
       top: .75rem;
       right: .75rem;
       transition: right .1s, top .1s, transform .2s .2s cubic-bezier(.18,.89,1,1.42);
      }
      #searchbox:focus-within::after{
       transform: rotate(135deg);
      }

      为了更好的用户体验,我们将两个伪类的可点击范围扩大一点。可以用border拓宽,不过需要特别设置一下background-clip: padding-box,不然border上也会有背景颜色

      #searchbox::before, #searchbox::after{
       border-top: .4rem solid transparent;
       border-bottom: .4rem solid transparent;
       background-clip: padding-box;
      }
  4. 现在来分析一下效果:

    • 当点击放大镜时,分别触发<input>:focus和伪元素的:focus-within,导致放大镜展开为搜索框,并且柄变成一个叉
    • 再点击叉或者页面其他位置,都会导致<input>失去:focus状态(因为点击伪元素是算在父元素上的),于是整体回到放大镜状态
  5. 最后,当然你还是要用js<input>绑上事件。按下回车开始搜索(回车的keyCode13

    document.querySelector('#searchbox>input').addEventListener('keydown', function(e){
        if(e.keyCode == 13){
    
        }
    });

添加新评论

  1. Terrasse

    Orz

    Reply