内容过滤是一个在Web上常见的一个功能,特别是在电商网站,为了让用户过滤内容,仅显示符合自己的要求的内容。截个图来说,能更好的说明这样的功能,比如淘宝网:
如上图所示,用户想购买一件裙子,在整个产品列表中,显示的产品数量太多了。顾客不知道如何选择自己所需要的裙子。在顶部提供了一个分类,顾客选择需要的选项,产品中就会过滤掉不符合条件的产品。上图选择了”气质优雅“的裙子。当然还可以选择更多的条件。这里就不我多说了。
话说回来,以前实现这样一个效果都需要借助于JavaScript(或者基于jQuery插件)来做。比如 CodyHouse 的 内容过滤 示例。但对于一枚不懂JavaScript的同学来说(不懂不是理由),要实现类似的一个功能,的确是一件难事(偶有切身体会,欲哭无泪,谁叫当初没好好读书)。
所幸的事,如今天偶也可以不借助JavaScript来实现。也就是纯CSS来实现一个功能简单一点的内容过滤器,不是难事。这也是今天要与大家一起分享的。
先来看一个简单的示例,页面加载时,会有女装、男装和童装一起出现,当你做下面的操作时,有意想不到的效果:
当然这个案例的功能没有淘宝网的那么NB,但好呆也是完成了一个类似内容过滤的功能。
实现这个功能的原理其实并不太复杂,只是大家平时并未关注过。我归纳起来就是两个方面:
实现这个功能,主要依赖于强大的CSS选择器中的 通用兄弟选择器( E~F
) 和 伪类选择器 :checked
。当某个单选按钮选中时,其他类的内容隐藏起来:
input[type="radio"]{ &[id="men"]:checked { ~ .women, ~ .children{ .... } } }
要通过上面样式来控制对应的 .women
和 .children
元素,必须保证元素与 input
元素是兄弟元素。这也是下面要说的第二个关键之处。
仅利用CSS制作这个功能,需要有严谨的结构,因为结构的错乱直接会影响到需要的效果。这也是其中不足之处。其中之一就是借助单选按钮”radio“和 label
匹配。为了外观的好看,不想显示 <input type="radio">
,需要通过 label
的 for
属性来控制选中的”radio“。所以 input
的 id
值要和 label
的 for
值匹配。另外所有的 input
的 name
值一样,告诉浏览器,他们是属于一组的。如:
<input type="radio" id="men" name="clothing" /> <label for="men">男装</label> <input type="radio" id="women" name="clothing"/> <label for="women">女装</label> <input type="radio" id="children" name="clothing"/> <label for="children">童装</label> <input type="radio" id="reset" name="clothing"/> <label for="reset">重置</label>
了解实现原理之后,要完成文章开头示例的效果就简单的多了。
HTML结构其实非常简单,只需要注意 input
和 label
的匹配以及将要过滤内容元素与其是兄弟元素。比如此例,内容元素主要有三类:男装 .men
、女装 .women
和童装 .children
。
<div class="container"> <!-- 必须保证input和label匹配 --> <input type="radio" id="men" name="clothing " /> <label for="men">男装</label> <input type="radio" id="women" name="clothing "/> <label for="women">女装</label> <input type="radio" id="children" name="clothing "/> <label for="children">童装</label> <input type="radio" id="reset" name="clothing "/> <label for="reset">重置</label> <!-- 要被过滤的内容元素需要与input元素是兄弟元素 --> <div class="tile men"> <img src="" alt=""> </div> <div class="tile women"> <img src="" alt=""> </div> <div class="tile children"> <img src="" alt=""> </div> <!-- 此处省略N个.men、.women和.children元素 --> </div>
明白原理,就简单多了,首先来看整体的代码:
body{ margin:0; text-align:center; font-family: Verdana; background:#f5f5f5; } h1 { text-align:center; } .container { width:90%; margin:0 auto; } input[type="radio"] { display:none; } label { width:23%; float:left; text-align:center; background:#ffffff; box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); color:#222222; padding:0.5%; margin:0.5%; margin-bottom:30px; cursor:pointer; } input[type="radio"]{ &[id="men"]:checked { * label { background:#6666ff; } ~ .women, ~ .children { width:0; height:0; padding:0; margin:0; opacity:0; } } &[id="women"]:checked { * label { background:#ff4466; } ~ .men, ~ .children { width:0; height:0; padding:0; margin:0; opacity:0; } } &[id="children"]:checked { * label { background:#66dd99; } ~ .men, ~ .women { width:0; height:0; padding:0; margin:0; opacity:0; } } } .tile { width:23%; float:left; transition:all 1s; margin:0.5%; padding:0.5%; background:#6666ff; img { width: 100%; } }
简单的解析一下这个样式代码。
为了页面好看,首先把 <input>
隐藏掉:
input[type="radio"] { display:none; }
我们通过 label
的 for
属性来控制 radio
有没有选中。美化一下 label
样式:
label { width:23%; float:left; text-align:center; background:#ffffff; box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); color:#222222; padding:0.5%; margin:0.5%; margin-bottom:30px; cursor:pointer; }
接下来样式代码也是最关键的一部分,当 input
选中之后 label
的样式:
input[type="radio"]{ &[id="men"]:checked { + label { background:#6666ff; } } ... }
上面的代码表示的是 <input type="radio" id="men">
选择中 :checked
时,其相邻的 label
改变背景颜色。
根据前面的原理介绍,可以得知,当我们选择了”男装“,那么”女装“和”童装“就需要隐藏,在这里通过假像来隐藏,也就是 input[type="radio"][id="men"]
选中,其相通兄弟元素 .women
和 .children
隐藏掉:
input[type="radio"]{ &[id="men"]:checked { ... ~ .women, ~ .children { width:0; height:0; padding:0; margin:0; opacity:0; } } }
其他两个选项也是类似的,就不在做过多的阐述。
美化的样式,这里就不说了,大家都懂的。
通过这个过程下来,你就能看到前面 DEMO 展示的效果了。
本文主要介绍了如何依赖于CSS的属性选择器、通用相邻兄弟选择器和伪类选择器来实现一个简单的内容过滤的功能。在整个实例当中,要把握的是严谨的HTML结构,因为相邻兄弟选择器对于结构的依赖程度非常的强。也就是说结构修改之后,你的选择器和样式都要做一定的修改。
通篇下来,是不是觉得非常的简单。如果你感兴趣的话,可以借助这个案例的思路,通过”复选框“按钮来实现多项内容过滤的效果。也就是符合多个条件的内容显示,不符合的隐藏。试试呗,你一定行。
如果你有更好的想法,或都对这个功能有何不同的建议,欢迎在下面的评论中留言。
常用昵称“大漠”,W3CPlus, Sass中国 创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。