使用display:flex水平折叠输入

时间:2016-10-18 08:48:32

标签: javascript css html5 css3 less

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

start state

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

  • 所选框展开
  • 另一个框水平折叠
  • 右侧展开了一个关闭图标。

过渡后的情况如下:

end state

这是代码:

<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-Classes:

.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: - 属性,但它似乎没有用。是否有一个技巧可以将flex-divs设置为宽度为0?

小提琴: https://jsfiddle.net/amear6x0/

1 个答案:

答案 0 :(得分:6)

您实际上可以使用CSS来实现您尝试执行的操作。诀窍如下:

  1. 使用类来指示各个组件的显示/隐藏状态。我们仍然可以使用jQuery来切换这些类。然后我们可以丢失繁琐的jQuery .aninmation()函数;)
  2. 根据状态在输入元素和关闭按钮的宽度0100%之间切换。浏览器可以平滑地调整宽度的过渡。我选择使用500ms的持续时间(正如您在jQuery代码中指出的那样),并使用width计时功能来补充ease-in-out属性。您当然可以定义所需的任何贝塞尔曲线。
  3. 使用focusblur函数代替focusinfocusout - 但这只是我的个人偏好
  4. 一些额外提示:

    • 使用box-sizing: 0防止输入元素的额外填充占用额外空间
    • 当元素父宽度折叠为0时,使用overflow: hidden隐藏溢出的内容。
    • 为了扩展性,请避免为执行相同目的的元素重复相同的功能。我可以将您拥有的每个输入元素的隐藏/显示切换折叠到一个函数中,只需使用.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>