使用 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 来实现您想要做的事情。诀窍如下:
- 使用类 表示各个组件的shown/hidden 状态。我们仍然可以使用 jQuery 来切换这些 类。这样我们就可以去掉繁琐的 jQuery
.aninmation()
函数 ;)
- 根据状态在输入元素和关闭按钮的
0
和 100%
宽度之间切换。宽度的过渡可以由浏览器平滑地动画化。我选择使用 500ms
的持续时间(正如您在 jQuery 代码中指出的那样),并使用 ease-in-out
仅补间 width
属性定时功能。你当然可以定义任何你想要的贝塞尔曲线。
- 使用
focus
和 blur
函数代替 focusin
和 focusout
——但这只是我个人的偏好
一些额外的提示:
- 使用
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>
我有两个搜索框出现在(移动)页面的顶部:
所需的焦点行为(即在其中一个框内单击)是:
- 所选框展开
- 另一个盒子水平折叠
- 关闭图标在右侧展开。
这是转换后的样子:
这是代码:
<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 来实现您想要做的事情。诀窍如下:
- 使用类 表示各个组件的shown/hidden 状态。我们仍然可以使用 jQuery 来切换这些 类。这样我们就可以去掉繁琐的 jQuery
.aninmation()
函数 ;) - 根据状态在输入元素和关闭按钮的
0
和100%
宽度之间切换。宽度的过渡可以由浏览器平滑地动画化。我选择使用500ms
的持续时间(正如您在 jQuery 代码中指出的那样),并使用ease-in-out
仅补间width
属性定时功能。你当然可以定义任何你想要的贝塞尔曲线。 - 使用
focus
和blur
函数代替focusin
和focusout
——但这只是我个人的偏好
一些额外的提示:
- 使用
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>