CSS构建下拉列表

特别声明:此篇文章由Jekst根据的英文文章原名《Css-only Alternative to the Select Element》进行翻译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://pepsized.com/css-only-alternative-to-the-select-element以及作者相关信息

——作者:

——译者:Jekst

在这篇文章中,我会给大家展示一个select表单标签的替代解决方案。这个方案由纯CSS构建,虽然看起来简单但效果确实很好。我们使用了一列radio元素,给它加上了下拉列表的样式,这样看起来和select元素的表现行为很相近。

当然你不得不为移动设备(如果你原意也可以是IE8)提供一些可靠的支持。本篇的最后部分我会简要的讨论这些。先看看demo吧,选择你最喜欢的方案。

demodownload

第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步——设计思路

为了让它简单些我会尽力讲明我的思路。我希望大家看了下面展示的图片能够有足够清晰的思路。

BEM

第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; 
}
....	

以上就是本文的所有内容,希望这个技术对大家有用,我很期望大家能告诉我你们的想法,我将不胜感激。

demodownload

译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!

关于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

返回顶部