13-实战篇:实战大操作-切换控件
juejin_logo copyCreated with Sketch.

前言

前几章学习了很多零零散散的CSS神操作骚技巧,每个单独的技巧都很强大,若组合起来岂不是更强大?本章以及后两章都是对这些学习过的CSS神操作骚技巧做一个总结与应用。学到的东西必须学以致用才行,不然就白学了。

以下准备三个jQuery时代Web组件,当然它们不是基于jQuery开发,而是基于CSS开发。合理将CSS神操作骚技巧结合,可制作出一些出乎意料的效果。

本章的主题是切换控件,主要是用于鼠标悬浮或点击时选中组件中单个部分的效果。常见控件有手风琴折叠面板

手风琴

手风琴在jQuery时代很常见,主要用于电商网站的商品栏目展示。我清楚记得十多年前淘宝首页的Banner就有手风琴效果,不过那时CSS3作为一个新生代的Web技术,因为兼容问题也很难应用到网页中。

手风琴

鼠标悬浮到组件的某个部分,该部分就会扩张开来并挤压旁边的部分,当鼠标离开时就恢复原状。若鼠标快速在其上面略过,就会产生手风琴的弹琴效果。

使用JS实现手风琴效果,必须监听mouseentermouseleave两个鼠标事件,而:hover可代替两者,所以CSS实现手风琴效果的关键就是:hover,核心代码如下。

li {
	// 鼠标未悬浮状态
	&:hover {
		// 鼠标悬浮状态
	}
}

手风琴的静态效果是一个内部横向排列着等宽子容器的大容器。换成CSS术语就是子节点水平排列且高度一样,在不触发悬浮效果时各个子节点的宽度都一样。根据其特征可用Flex布局完成该排版。

<ul class="accordion">
	<li></li>
	<li></li>
	<li></li>
	<li></li>
	<li></li>
	<li></li>
</ul>

当鼠标悬浮在任意子节点时会触发:hover,此时让li:hover声明一些相关状态,为了让<li>在悬浮前与悬浮后的外观过渡不那么生硬,声明transition:all 300ms会更好。

.accordion {
	display: flex;
	width: 600px;
	height: 200px;
	li {
		flex: 1;
		cursor: pointer;
		transition: all 300ms;
		&:nth-child(1) {
			background-color: #f66;
		}
		&:nth-child(2) {
			background-color: #66f;
		}
		&:nth-child(3) {
			background-color: #f90;
		}
		&:nth-child(4) {
			background-color: #09f;
		}
		&:nth-child(5) {
			background-color: #9c3;
		}
		&:nth-child(6) {
			background-color: #3c9;
		}
		&:hover {
			flex: 2;
			background-color: #ccc;
		}
	}
}

后续出现相关状态切换的节点,最好都声明transition,这样能让整个动画过渡变得更自然。

折叠面板

折叠面板其实是手风琴的一个垂直版本,手风琴的子节点水平排列,而折叠面板的子节点垂直排列。折叠面板通常都是点击子菜单,显示更多的子菜单,可同时打开也可单独打开。本次通过CSS完成一个多选的折叠面板。

折叠面板

还记得在第9章中<input><label>的巧妙搭配吗?在此也可通过<input><label>模拟按钮的点击事件。

<input><article>成为同胞元素且让<input>放置在最前面,是为了方便使用+/~<input>触发:checked时带动<article>进入选中状态。

input:checked + article {}
input:checked ~ article {}

此时可通过上述代码让<article>动起来。因为将<input>的鼠标选择事件转移到<label>中,由<label>控制选中状态,所以需对<input>设置hidden将其隐藏起来。

<div class="accordion">
	<input id="collapse1" type="checkbox" hidden>
	<input id="collapse2" type="checkbox" hidden>
	<input id="collapse3" type="checkbox" hidden>
	<article>
		<label for="collapse1">列表1</label>
		<p>内容1<br>内容2<br>内容3<br>内容4</p>
	</article>
	<article>
		<label for="collapse2">列表2</label>
		<p>内容1<br>内容2<br>内容3<br>内容4</p>
	</article>
	<article>
		<label for="collapse3">列表3</label>
		<p>内容1<br>内容2<br>内容3<br>内容4</p>
	</article>
</div>

上述结构未为<article>设置单独类,因为同级结构中存在<input><article>,所以不能使用:nth-child(n),而是使用:nth-of-type(n)选择指定<article>

折叠内容在实际场景的高度是不固定或很难预测,有些同学会声明height:auto。若声明了transtionheight0变更到auto会无任何过渡效果,跟不声明transtion一样显得很生硬,但max-height可借助transtion过渡,在隐藏折叠内容时声明max-height:0,在展开折叠内容时声明max-height:1000px1000px只是一个示例,反正比预计的高度大即可,声明2000px也无所谓。当然还必须声明overflow:hidden隐藏超出内容区域的内容。

这个max-height最好根据需求合理安排,太小会无法显示全部内容,太大会导致过渡效果显得唐突。

.accordion {
	width: 300px;
	article {
		cursor: pointer;
		& + article {
			margin-top: 5px;
		}
	}
	input {
		&:nth-child(1):checked ~ article:nth-of-type(1) p,
		&:nth-child(2):checked ~ article:nth-of-type(2) p,
		&:nth-child(3):checked ~ article:nth-of-type(3) p {
			border-bottom-width: 1px;
			max-height: 600px;
		}
	}
	label {
		display: block;
		padding: 0 20px;
		height: 40px;
		background-color: #f66;
		cursor: pointer;
		line-height: 40px;
		font-size: 16px;
		color: #fff;
	}
	p {
		overflow: hidden;
		padding: 0 20px;
		border: 1px solid #f66;
		border-top: none;
		border-bottom-width: 0;
		max-height: 0;
		line-height: 30px;
		transition: all 500ms;
	}
}

留言
Ctrl + Enter
全部评论(3)
dodoto的头像
删除
折叠面板那个为什么关闭的时候有延迟啊
点赞
2
删除
(作者)
可以在选中状态时追加transition,将其贝塞尔曲线调整下来抵消这个延迟
1
回复
删除
应该是transition导致的
点赞
回复