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