CSS构建下拉列表
特别声明:此篇文章由Jekst根据PeHaa的英文文章原名《Css-only Alternative to the Select Element》进行翻译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://pepsized.com/css-only-alternative-to-the-select-element以及作者相关信息
——作者:PeHaa
——译者:Jekst
在这篇文章中,我会给大家展示一个select表单标签的替代解决方案。这个方案由纯CSS构建,虽然看起来简单但效果确实很好。我们使用了一列radio元素,给它加上了下拉列表的样式,这样看起来和select元素的表现行为很相近。
当然你不得不为移动设备(如果你原意也可以是IE8)提供一些可靠的支持。本篇的最后部分我会简要的讨论这些。先看看demo吧,选择你最喜欢的方案。
第1步——HTML
这是我们在表单里使用的html代码。
<fieldset class="radio-container">
<div class="radio-options">
<div class="toggle">Choose your beer</div>
<ul>
<li>
<input type="radio" name="my-beer" id="choice1" value="choice1">
<label for="choice1">Cul Dorcha</label>
</li>
<li>
<input type="radio" name="my-beer" id="choice2" value="choice2">
<label for="choice2">Rowers Red Ale</label>
</li>
<li>
<input type="radio" name="my-beer" id="choice3" value="choice3">
<label for="choice3">Belfast Ale</label>
</li>
<li>
<input type="radio" name="my-beer" id="choice4" value="choice4">
<label for="choice4">O'Hara Irish Stout</label>
</li>
</ul>
</div>
</fieldset>
第2步——设计思路
为了让它简单些我会尽力讲明我的思路。我希望大家看了下面展示的图片能够有足够清晰的思路。

第3步——CSS样式
根据上述方案提出的思路,我们给元素加上CSS样式。为了本文的简洁,我省略了一些只是为了外观而添加的CSS样式(如三角形箭头)——在附件里大家会看到完整的CSS样式。
请注意,同样为了简洁,浏览器前缀也省略了。
下面是最外层容器(”.radio-container”)的样式:
radio-container {
position: relative;
height: 4em; /* 3em (being the max-height of the inner container) + 1em ("margin") */
}
.radio-container:hover {
z-index: 9999;
}
下面是里层.radio-options的样式:
.radio-options {
position: absolute;
max-height: 3em;
width: 100%;
overflow: hidden;
transition: 0.7s;
}
.radio-options:hover {
max-height: 100em;
}
下一步:
.radio-options .toggle {
position: relative;
cursor: pointer;
padding: 0.75em;
background: darkgreen;
border-radius: 10px;
z-index: 1;
}
/* li are stacked at the same position as .toggle, only .toggle is visible */
.radio-options li {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.radio-options label {
display: block;
opacity: 0;
transition: 0s;
}
为了看不到input元素,我们可以直接把它的display属性设置为display:none,但是这样设置后,在浏览器中(一些移动设备的浏览器同样也是)点击label元素时就不能使相关联的input元素获得焦点,input(radio)元素也就不起作用了。为了使input元素看不见并且点击label时能够关联到相应的input元素上,我们这样设置input元素的样式:
.radio-options input {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 3em;
opacity: 0;
z-index:1;
cursor: pointer;
}
第4步——悬浮时的CSS样式
现在我们来看一下当悬浮的时候这些元素的样式发生了什么变化:radio-container设置了一个值很大的z-index属性,radio-options的max-height属性的值增大了。悬浮时我们还会添加li和label的样式:
/* li elements have a normal flow within the .radio-options container */
.radio-options:hover li {
position: relative;
}
.radio-options:hover label {
opacity: 1;
transition: 0.5s;
}
第5步——input:checked样式
为了给选中的项设置样式,我们使用了兄弟选择器。它使用波浪符组合器(E~F),匹配给定的元素的兄弟结点。第一个元素(E)出现在第二个元素(F)之前,他们具有相同的父元素(在我们的例子中父元素是li)。下面是选中时label的样式。
.radio-options input:checked ~ label {
position: absolute;
top: 0;
left: 0;
right: 0;
opacity: 1;
/* is above the .toggle so is visible */
z-index: 2;
/* has tha same styles as .toggle */
padding: 0.75em;
background: darkgreen;
border-radius: 10px;
}
悬浮在.radio-options上时,选中的label元素又设置为文档标准流状态。
.radio-options:hover input:checked ~ label {
position: static;
border-radius: 0;
}
第6步——关于移动设备
由于是在鼠标悬浮的时候才激活元素,所以我们不得不为触摸设备提供一些支持。一个解决方案就是让radio和label元素始终看得见,不只是在悬浮的时候。
这是我的解决方案来保证下拉列表的效果。我是使用自定义的modernizr来检测触摸设备上的效果的。添加了以下的js代码。
$(document).ready(function(){
if (Modernizr.touch) {
$(".radio-options").bind("click", function(event) {
if (!($(this).parent('.radio-container').hasClass("active"))) {
$(this).parent('.radio-container').addClass("active");
event.stopPropagation();
}
});
$(".toggle").bind("click", function(){
$(this).parents('.radio-container').removeClass("active");
return false;
});
}
})
我修改了每个:hover元素的样式,如下所示:
.no-touch .radio-container:hover, .active.radio-container {
z-index: 9999;
}
.no-touch .radio-options:hover, .active .radio-options {
max-height: 100em;
}
.no-touch .radio-options:hover li, .active .radio-options li {
position: relative;
}
.no-touch .radio-options:hover label, .active .radio-options label {
opacity: 1;
transition: 0.5s;
}
....
第7步——支持IE8
在本篇文章中可靠的解决方案不是重点,但你也可想一个解决办法,这完全取决去你自己。这是我的解决办法。
<!--[if (IE 8)]>
<script>
$(document).ready(function(){
$(".radio-options li").bind("click", function() {
$(this).siblings(".checked").removeClass("checked");
$(this).addClass("checked");
});
});
</script>
<![endif]-->
我在CSS文件中添加.checked类的声明等(可以看附件里的完整版本):
.radio-options .checked label {
position: absolute;
top: 0;
left: 0;
right: 0;
padding: 0.75em;
background: #1b9e4d;
visibility: visible;
z-index: 2;
}
....
以上就是本文的所有内容,希望这个技术对大家有用,我很期望大家能告诉我你们的想法,我将不胜感激。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
关于Jekst
常用昵称jekst,目前就职于北京一家信息技术公司,主要从事。net系列的开发,热爱前端,对css、jQuery有浓厚兴趣,喜欢参加技术交流活动。欢迎交流共勉:新浪微博。
如需转载烦请注明出处:
英文原文:http://pepsized.com/css-only-alternative-to-the-select-element
中文译文:http://www.w3cplus.com/css/css-only-alternative-to-the-select-element.html



