纯 CSS+JS 通用选项卡

来源:互联网 发布:网络主播直播用语 编辑:程序博客网 时间:2024/04/28 02:35

请看源码吧,各段都有详细注释。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>选项卡</title>
<style type="text/css">
/*核心:
选项页切换:先把各选项内容块设置成 display: none,再把当前选项的 .tabOn .tabContentBox 设置为 display: block;
选项页是分属不同的 li 的,要让它们定位到相同的位置,就要用到 position: absolute; 而这时又不是相对窗口的绝对定位,而是相对于整个选项组 ul 的定位,因为给 .tabList .tabBox 设置 position:relative;。
从 http://www.awflasher.com/blog/archives/731 学到,要让某个节点相对于其上级的节点绝对定位,而不是相对于窗口,就给要参照的上级节点设置 position:relative;。由选项这个例子可以知道,这个上级节点不必是直接的父节点,可以是若干级以上的节点,即某节点设置了 position:relative; 后,它的各级子节点再用 position: absolute; 是都将参照此节点而非窗口。
这里 top 的 30px 就是选项头 .tabBox  h4 的高度。
*/
 .tabBox {
height:100%;
position:relative;
background:#fff;
border:1px solid #99F;
}
.tabBox .tabContentBox {
margin:1px;
padding: 10px;
width:570px;
height:60px;
text-align: left;
overflow: hidden;
background: #fff;
position: absolute;
top: 30px;
left: 0;
display: none;
}

/*原例是鼠标悬停就切换,我要的是点击再切换,所以不用 .tabOption:hover 这个级联 */
.tabBox .tabOn .tabContentBox  {
display: block;
}

/* 初始化 */
body {
font: 12px/1 "宋体", SimSun, serif;
background:#fff;
color:#000;
}

/* 清除浏览器默认的margin和padding值 */
ul,li,dl,dt,dd {
margin:0;
padding:0;
}
ul,li {
list-style:none outside;  /* 清除浏览器中列表项默认的占位 */
}
a {
text-decoration:none;
}
a:hover {
text-decoration:underline;
}
/* 选项卡整体外观定义 */
.tabBox {
width:580px;
height:115px;
overflow:hidden;
}
/*百分比宽度居然支持 2 位小数,在 FF 里完美合成整条,而 IE 里还是有点空白。看来只好用 JS 算成像素值了,最后剩余的几像素都放在最后一个即可。
width:25%; 只是默认的 4 个选项时用的,选项个数不是 4 时,由 JS 均分出宽度。选项头的左右边框样式做到 li 下属的 h4 标签上,这样的好处是 JS 算宽度时只考虑 width 即可,不用管边框之类的零星数。*/
.tabBox li {
float:left;
width:25%;
text-align:center;
}
/*选项头的选中和未选样式。这里好像不能用 padding 来垂直居中,会让边框超出,只好改用 line-height 配 height。选项卡的样式刚好利用 li 里套的 h4 来实现:未选中时底边框和外框同色,左右边框和选项头背景同色;选中时底边框和内容的背景同色,左右边框和外框同色。*/
.tabBox  h4 {
 cursor:pointer;
 margin:0;
 padding: 0;
 height: 30px;
 line-height:30px;
 color:#036;
 font-size:12px;
 font-weight:normal;
 display:block;
 background:#edf2fa;
 border-bottom:1px solid #99F;
}
.tabBox .tabOn h4, .tabBox h4.tabOnFirst, .tabBox h4.tabOnFinal {
color:#06f;
background:#fff;
border-left:1px solid #99F;
border-right: 1px solid #99F;
border-bottom:1px solid #FFF;
}
.tabBox h4.tabOnFirst {
border-left:1px solid #fff;
border-bottom:1px solid #FFF;
}
.tabBox h4.tabOnFinal {
border-right:1px solid #fff;
border-bottom:1px solid #fff;
}
</style>
<script type="text/javascript" language="javascript">
<!--
/*
通用选项卡
2009-9-9 15:16:13
作者:雪峰
欢迎转载使用,请包含此段完整说明。

纯 CSS 样式,无需背景图实现选项卡样式。
不限选项个数,只需按此网页结构配置选项内容到 ul 列表即可。
完全无需节点 ID,同一页面中可以多次使用。
程序根据选项卡个数自动调整选项头的宽度样式。
JS 程序与页面元素彻底分离,只需要 window.onload = tabUl; 即可启用。
IE6/7, Firefox 2/3, Opera 9 兼容
*/
var tabUl = function()
{
 //取元素实际呈现的样式对象
 var getRealStyle = function(node)
 {
  var RealStyle;
  if (node.currentStyle)                            /*先试 IE 的 简单API */
  {
   RealStyle = node.currentStyle;
  }
  else if (window.getComputedStyle)              /* 再试 W3C API */
  {
   RealStyle = window.getComputedStyle(node, null);
  }
  return RealStyle;
 };

 //选中选项卡时的切换
 var tabOn = function()
 {
  var node = this;
  tabList = this.parentNode;
  tabOptions = tabList.getElementsByTagName("li");
  var tabNum = tabOptions.length;
  for (var i=0; i<tabNum; i++)
  {
   if (tabOptions[i].className.indexOf('tabOption') >= 0)
   {
    //先把各 li 都恢复成 tabOption
    tabOptions[i].className = "tabOption";
    //把各 li 里的 h4 都恢复成空 class
    var tabTitle = tabOptions[i].getElementsByTagName("h4");
    tabTitle[0].className = '';

    //当前的 li 增加 tabOn,当前 li 内的 h4 再根据位置增加 tabOnFirst 或 tabOnFinal
    if (tabOptions[i] == node)
    {
     this.className += ' tabOn';
     var classTab = (0==i) ? 'tabOnFirst':(((tabNum-1)==i)?'tabOnFinal':'');
     tabTitle[0].className = classTab;
    }
   }
  }
 };

 //找 class="tabBox" 的 ul 节点,批量注册事件处理函数及处理样式
 var ul = document.getElementsByTagName('ul');
 for (var i=0; i<ul.length; i++)
 {
  if (ul[i].className.indexOf('tabBox') >= 0)
  {
   //均分选项头宽度
   var realStyle = getRealStyle(ul[i]);
   //做选项卡的 UL 通常都显式定义像素宽度,不用判断直接用 realStyle 了。

   var boxWidth = parseInt(realStyle.width);

   var li = ul[i].getElementsByTagName('li');
   var tabNum = li.length;

   //选项头的左右边框样式做到 li 下属的 h4 标签上,这样的好处是 JS 算宽度时只考虑 width 即可,不用管边框之类的零星数。
   for (var j=0; j<tabNum; j++)
   {
    //先取平均分的宽度的下限值
    var liWidth = Math.floor(boxWidth/tabNum);
    //最末一个取整体宽度前去前面各个选项头的宽度剩下的
    if ((j+1) == tabNum)
    {
     liWidth = boxWidth - liWidth * j;
    }
    li[j].style.width = liWidth +'px';
    //这里可以选择注册给点击或悬停事件
    li[j].onmouseover = tabOn;
    //li[j].onclick = tabOn;
   }
  }
 }
};

window.onload = tabUl;
-->
</script>

</head>
<body>
<h1>通用选项卡演示</h1>
  <ul class="tabBox">
  <!-- 给默认选中的项设置 li 的 class="tabOption tabOn", h4 的 class="tabOnFirst"  -->
    <li class="tabOption tabOn">
      <h4 class="tabOnFirst">选项1</h4>
      <div class="tabContentBox">
      1的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
    <li class="tabOption">
      <h4>选项2</h4>
      <div class="tabContentBox">
    2的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
    <li class="tabOption">
      <h4>选项3</h4>
      <div class="tabContentBox">
        3的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
  </ul>


<br /><br /><br /><br /><br /><br />
  <ul class="tabBox">
    <li class="tabOption tabOn">
      <h4 class="tabOnFirst">选项1</h4>
      <div class="tabContentBox">
        1的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
    <li class="tabOption">
      <h4>选项2</h4>
      <div class="tabContentBox">
    2的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
    <li class="tabOption">
      <h4>选项3</h4>
      <div class="tabContentBox">
        3的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
    <li class="tabOption">
      <h4>选项4</h4>
      <div class="tabContentBox">
        4的具体内容<br /><a href="http://www.snowpeak.org" target="_blank">www.snowpeak.org</a>
      </div>
    </li>
  </ul>
</body>
</html>