使用 display: flex 水平折叠输入

Horizontally collapse input with display: flex

我有两个搜索框出现在(移动)页面的顶部:

所需的焦点行为(即在其中一个框内单击)是:

这是转换后的样子:

这是代码:

<div class="navigation--mobile__search">
    <div class="header-searchfield" id="kurssuche">
        <input type="text" class="header-searchfield__input" placeholder="Search1">
            <a href="">
                <span class="icon icon--lupe">
                    <svg class="icon__svg">
                        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/svg/svg-symbol.svg#lupe"></use>
                    </svg>
                </span>
            </a>
    </div>
    <div class="header-searchfield" id="volltextsuche">
        <input type="text" class="header-searchfield__input" placeholder="Search2">
            <a href="">
                <span class="icon icon--lupe">
                    <svg class="icon__svg">
                        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/svg/svg-symbol.svg#lupe"></use>
                    </svg>
                </span>
            </a>
    </div>                      
    <span class="icon icon--close-x header-searchfield__close-button" style="display: none;">
        <svg class="icon__svg">
            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/svg/svg-symbol.svg#close-x"></use>
        </svg>
    </span>
</div>

对应的LESS-类:

.navigation--mobile__search {
        background: @common-quarks-color--cd-anthracite;
        display: flex;
        padding: .625rem .75rem;
        position: relative;
        .header-searchfield {
            display: flex;
            flex: 1;
            &__input {
                flex-grow: 1;
                padding: .5625rem 2rem .5625rem .8125rem;
            }
            &__close-button {
                flex: 0 0 1.8rem;
                color: white;
                display: none;
                margin: .7rem 0 .7rem .5rem;
                svg {
                    fill: @searchfield--border-color;
                    height: .8125rem;
                    width: .8125rem;
                }
            }
        }
    }

和javascript:

$(function () {
  $("#kurssuche")
    .focusin(function() {
      $("#volltextsuche").hide(500);
      $(".header-searchfield__close-button").show(500);
      $(".navigation--mobile__search-results").animate({height: "400px"}, 500);
    })
    .focusout(function() {
      $("#volltextsuche").show(500);
      $(".header-searchfield__close-button").hide(500);
      $(".navigation--mobile__search-results").animate({height: "0"}, 500);
    });
  $("#volltextsuche")
    .focusin(function() {
      $("#kurssuche").hide(500);
      $(".header-searchfield__close-button").show(500);
      $(".navigation--mobile__search-results").animate({height: "400px"}, 500);
    })
    .focusout(function() {
      $("#kurssuche").show(500);
      $(".header-searchfield__close-button").hide(500);
      $(".navigation--mobile__search-results").animate({height: "0"}, 500);
    });
  $(".header-searchfield__close-button").on('click', function() {
    $(".header-searchfield__input").val("");
  });
});

问题

对于所需的水平折叠行为,我通常只抓取 div 和未选中的输入并将宽度设置为 0。这不起作用,因为包装器 div 是 display: flex - 我尝试使用 flex:-Attribute 进行试验,但它似乎没有用。是否有将 flex-divs 设置为宽度 0 的技巧?

Fiddle: https://jsfiddle.net/amear6x0/

您实际上可以只使用 CSS 来实现您想要做的事情。诀窍如下:

  1. 使用类 表示各个组件的shown/hidden 状态。我们仍然可以使用 jQuery 来切换这些 类。这样我们就可以去掉繁琐的 jQuery .aninmation() 函数 ;)
  2. 根据状态在输入元素和关闭按钮的 0100% 宽度之间切换。宽度的过渡可以由浏览器平滑地动画化。我选择使用 500ms 的持续时间(正如您在 jQuery 代码中指出的那样),并使用 ease-in-out 仅补间 width 属性定时功能。你当然可以定义任何你想要的贝塞尔曲线。
  3. 使用 focusblur 函数代替 focusinfocusout——但这只是我个人的偏好

一些额外的提示:

  • 使用box-sizing: 0防止输入元素的额外填充占用额外的space
  • 当元素父宽度折叠为 0 时,使用 overflow: hidden 隐藏溢出的内容。
  • 为了可扩展性,避免为执行相同目的的元素重复相同的功能。我可以将每个输入元素的 hide/show 切换折叠到一个函数中,只需结合使用 .closest().siblings() 来执行元素的上下文相关过滤。

这是一个概念验证示例(参见 updated fiddle here):

$(function() {
  $('.header-searchfield input')
    .on('focus', function() {
    
      // Context-dependent filtering to reduce code redundancy :)
      // Search for siblings of parent wrapper, and hide them
      $(this).closest('.header-searchfield').siblings('.header-searchfield').addClass('hide');
    
      // Show the close button
      $('.header-searchfield__close-button').addClass('show')
    })
    .on('blur', function() {
    
      // Context-dependent filtering to reduce code redundancy :)
      // Search for siblings of parent wrapper, and show them
      $(this).closest('.header-searchfield').siblings('.header-searchfield').removeClass('hide');
    
      // Hide the close button
      $('.header-searchfield__close-button').removeClass('show');
    });

  $('.header-searchfield__close-button').on('click', function() {
    $('.header-searchfield__input').val('');
  });
});
* {
  box-sizing: border-box;
}
.navigation--mobile__search {
  background: #28373c;
  display: flex;
  padding: .625rem .75rem;
  position: relative;
}
.navigation--mobile__search .header-searchfield {
  flex: 1 1 auto;
  width: 100%;
  overflow: hidden;
  transition: .5s width ease-in-out;
}
  .navigation--mobile__search .header-searchfield.hide {
    width: 0;
  }
.navigation--mobile__search .header-searchfield__input {
  padding: .5625rem 2rem .5625rem .8125rem;
}
.navigation--mobile__search .header-searchfield__close-button {
  flex: 0 0 auto;
  color: white;
  margin: .7rem 0 .7rem .5rem;
  width: 0;
  overflow: hidden;
  transition: .5s width ease-in-out;
}
  .navigation--mobile__search .header-searchfield__close-button.show {
    width: 1.8rem;
  }
.navigation--mobile__search .header-searchfield__close-button svg {
  fill: #fff;
  height: .8125rem;
  width: .8125rem;
}

.header-searchfield {
  position: relative;
  margin: 0 .3125rem;
}
.header-searchfield__input {
  background: none;
  border: 1px solid #fff;
  border-radius: 1rem;
  padding: .5rem 2rem .5rem .8125rem;
  color: #fff;
  font-size: .8125rem;
  width: 100%;
}
.header-searchfield__input:focus {
  outline: 0 none;
  box-shadow: none;
}
.icon {
  width: 0.875rem;
  height: 0.875rem;
  fill: currentColor;
  display: inline-block;
}
.icon__svg {
  height: 100%;
  vertical-align: top;
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navigation--mobile__search">
  <div class="header-searchfield" id="kurssuche">
    <input type="text" class="header-searchfield__input" placeholder="Search1">
  </div>
  <div class="header-searchfield" id="volltextsuche">
    <input type="text" class="header-searchfield__input" placeholder="Search2">
  </div>
  <span class="icon header-searchfield__close-button">
    <svg class="icon__svg">
      <path xmlns="http://www.w3.org/2000/svg" d="M7.4 6l4.3-4.3a1 1 0 0 0 0-1.4 1 1 0 0 0-1.4 0L6 4.7 1.7.3A1 1 0 0 0 .3.3a1 1 0 0 0 0 1.4L4.6 6 .3 10.3a1 1 0 0 0 0 1.4 1 1 0 0 0 1.4 0L6 7.3l4.3 4.4a1 1 0 0 0 1.4-1.4z"/>
    </svg>
  </span>
</div>