2007-02-12

使用HTML+CSS编写一个灵活的Tab页

关键字: HTML CSS Tab页
最近在研究CSS,正好结合项目做了一个灵活的Tab页,使用纯HTML+CSS实现,正好总结一下。

首先看一下预览界面:

样例HTML可以访问:http://www.demo2do.com/htmldemo/school/attendance/AttendanceGlobal.html

下面开始讲述一下完成上述页面的步骤。

1. 构建HTML
构建HTML是整个过程最基础的部分。我们构建HTML比较关键的一个原则就是“还HTML标签其本来的含义”。所以在这里,我们应该合理分析一下期望做到的HTML的结构的情况,并加以分析,选择比较合适的HTML标签,而不是采用非标准的Table布局或者充斥着大量div和class的布局方式。事实上,现在存在着一种误区,就是凡事采用了DIV+CSS的方式进行页面编程的就是Web标准的,其实这是完全错误的观点,很容易就导致了“多div症”(divitus)或者“多类症”(classitis)。
回到正题,我们分析一下页面样式,可以将整个Tab页分成2个部分,分别是一级菜单和二级菜单,他们有类似的特点,并以横向方式排列。HTML标签中的无序列表就可以反映出这种逻辑关系。所以我们分别采用2个无序列表来表示一级菜单和二级菜单。代码如下:
<div class="navg">
	<div id="attendance" class="mainNavg">
		<ul>
			<li id="attendanceNavg"><a href="#">考勤管理</a></li>
			<li id="teachNavg"><a href="#">教学管理</a></li>
			<li id="communicationNavg"><a href="#">家校互通</a></li>
			<li id="systemNavg"><a href="#">系统管理</a></li>
		</ul>
	</div>	
	<div id="dailyAttendance" class="secondaryNavg">
		<ul>
			<li id="dailyAttendanceNavg"><a href="#">当天考勤</a></li>
			<li id="leaveApproveNavg"><a href="#">请假审批</a></li>
			<li id="attendanceStatisticsNavg"><a href="#">考勤统计</a></li>
			<li id="attendanceCollectNavg"><a href="#">考勤汇总</a></li>
		</ul>
	</div>
</div>


其中,2个div将菜单级别划分开。其实在以后还会有其他的功效。此时,我们不妨View一下这张页面,我们可以惊喜的发现,这张页面就想Word文档一样,是可读的,这一点我们可以在整个过程做完以后再一次验证。



2. 构建基本CSS

先简单的让ul横向排列,这里面要注意元素float之后要注意清理

然后通过分别在LI 和 A 元素上应用背景来实现主菜单样式,这里有个比较重要的地方是A这个元素变成块级元素(display: block),这样可以便于我们下面做一些处理,也能使整个菜单应用到链接样式。
而其中的line-height,恰恰可以使A中的字纵向居中。text-align使得A中的字横向居中。
.navg .mainNavg UL {
	margin: 0;
	padding: 0;
	list-style: none;
}
.navg .mainNavg UL LI {
	float: left;	
	background-color: #E1E9F8;
	background: url(../images/tab_right.gif) no-repeat right top;
	margin: 10px 3px;
	height: 25px;
}

.navg .mainNavg UL LI A {
	display: block;
	height: 25px;
	padding: 0 25px;
	line-height: 24px;
	background-color: #E1E9F8;
	background: url(../images/tab_left.gif) no-repeat left top;
	text-decoration: none;
	float: left;
	text-align:center;
	color: #fff;
	font-weight: bold;	
}


3. 使宽度自适应

我们在这里使用滑动门技术来做宽度自适应。下面简单介绍一下滑动门技术

简单来说,就是在LI上应用一幅大图像背景,并让这个背景居于右侧



然后在A上应用一个小图像背景,并让这个背景居于左侧,遮住大图像边缘



这样无论菜单文字内容长度怎么变,都不会破坏原来的结构了。

4. 当前菜单高亮显示

如果高亮当前页面,这个有很多种做法,最死板的是在每个页面上显式的定义类。
但是对于web项目来说,页面多数是动态的,所以这样不是最理想的方法。

我这里采用的方法是CSS选择器的灵活使用

#attendance #attendanceNavg,
#teach #teachNavg,
#communication #communicationNavg,
#system #systemNavg {
	background: url(../images/tab_right_on.gif) no-repeat right top;
}
#attendance #attendanceNavg A,
#teach #teachNavg A,
#communication #communicationNavg A,
#system #systemNavg A {
	background: url(../images/tab_left_on.gif) no-repeat left top;
	color: #0000ff;
}


在<div id="attendance" class="mainNavg">的代码中,我们可以使用不同的id作为选择器,由于CSS中的选择器id的优先级将大于class,所以只要根据id配合上li上面的id,就可以达到动态选择高亮选中的目的。

事实上,由于我们的页面都是动态的,所以id可以由后台生成,这样就可以通过id的不同组合非常精巧的实现了我们的需求。

5. 小技巧

最后可能还有一个问题你在想怎么实现的,就是高亮的tab如何把下面的横线遮掉的

很简单,图片上的小技巧。将高亮的图片高度设置为25px,而普通的图片设置为24px。然后通过padding,就可以将那根横线遮去了。


我们可以使用类似的方式,把二级菜单也做出来,这里就不详细叙述了。大家可以结合源码试一下。

附件为
评论
micrexp 2007-05-08
downpour 写道
最近在研究CSS,正好结合项目做了一个灵活的Tab页,使用纯HTML+CSS实现,正好总结一下。

首先看一下预览界面:

样例HTML可以访问:http://www.demo2do.com/htmldemo/school/attendance/AttendanceGlobal.html

下面开始讲述一下完成上述页面的步骤。

1. 构建HTML
构建HTML是整个过程最基础的部分。我们构建HTML比较关键的一个原则就是“还HTML标签其本来的含义”。所以在这里,我们应该合理分析一下期望做到的HTML的结构的情况,并加以分析,选择比较合适的HTML标签,而不是采用非标准的Table布局或者充斥着大量div和class的布局方式。事实上,现在存在着一种误区,就是凡事采用了DIV+CSS的方式进行页面编程的就是Web标准的,其实这是完全错误的观点,很容易就导致了“多div症”(divitus)或者“多类症”(classitis)。
回到正题,我们分析一下页面样式,可以将整个Tab页分成2个部分,分别是一级菜单和二级菜单,他们有类似的特点,并以横向方式排列。HTML标签中的无序列表就可以反映出这种逻辑关系。所以我们分别采用2个无序列表来表示一级菜单和二级菜单。代码如下:


顺便贴一个我写的

 <!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>
    <title>Untitled Page</title>
    <link type="text/css" href="gridstyle.css" rel="StyleSheet"/>
    <script language="javascript" type="text/javascript">
        var HK_TabItem = function(){
            this.tabControl = null;
            var button = document.createElement("div");           
            var items = new Array();
            var active = false;
            this.appendItem = function(value){
                items[items.length] = value;
                value.oldVisible = value.style.display;
                value.style.display = "none";
            }
            this.getElement = function(){
                return button;
            }
            this.setCaption = function(value){
                button.innerText = value;
            }
            this.setActive = function(){
                if(active){return};
                button.className = "tab_tabbuttonactive";
                this.tabControl.setActiveTab(this);
                for(var i=0;i<items.length;i++){
                    items[i].style.display = items[i].oldVisible;
                }
                active = true;
            }
            this.deActive = function(){
                button.className = "tab_tabbutton";
                for(var i=0;i<items.length;i++){
                    items[i].style.display = "none";
                }
                active = false;
            }
            function onClick(){
                button.tab.setActive();
            }
            button.attachEvent("onclick",onClick);
            button.className = "tab_tabbutton";
            button.tab = this;
        }
        var HK_TabControl = function(){
            var activeTab = null;
            var banner =document.createElement("div");
            var head = document.createElement("div");
            var line = document.createElement("div");
            var tab = document.createElement("div");
            var padding = document.createElement("div");
            banner.className = "tab_banner";
            head.className = "tab_head";
            line.className = "tab_line";
            padding.className = "tab_padding";
            line.innerHTML = " ";
            tab.appendChild(banner);
            tab.appendChild(line);
            banner.appendChild(head);            
            this.tabs = new Array();
            this.setActiveTab = function(value){
                if(activeTab!=null){
                    activeTab.deActive();
                }             
                activeTab = value;   
            }
            this.getActiveTab = function(){
                return activeTab;
            }
            this.appendTab = function(){
                var tab = new HK_TabItem();
                banner.appendChild(tab.getElement());
                tab.tabControl = this;
                return tab;
            }
            this.parent = null;  
            this.init = function(){
                this.parent.appendChild(tab);
                banner.appendChild(padding);
                padding.style.pixelWidth = banner.offsetWidth - padding.offsetLeft-2;
            }          
        }
    </script>
</head>
<body>
<div id="test"></div>
    <div id="test1" style="width: 100px; height: 100px">
        <input id="Button1" type="button" value="button" />
        asdfasdf</div>
    <div id="test2" style="width: 100px; height: 100px">
        asdfasdf<input id="Text1" type="text" /></div>
    <div id="test3" style="width: 100px; height: 100px">
        <input id="Checkbox1" type="checkbox" />asdfasdf</div>
    <div id="test4" style="width: 100px; height: 100px">
        asdfasdf<input id="Hidden1" type="hidden" /></div>
        <script>
            var tabcontrol = new HK_TabControl();
            var tab = tabcontrol.appendTab();    
            tab.setCaption("test1");
            tab.appendItem(document.getElementById("test1"));                  
            var tab = tabcontrol.appendTab();    
            tab.setCaption("test2");
            tab.appendItem(document.getElementById("test2"));     
            var tab = tabcontrol.appendTab();    
            tab.setCaption("test3");
            tab.appendItem(document.getElementById("test3"));     
            var tab = tabcontrol.appendTab();    
            tab.setCaption("test4");
            tab.appendItem(document.getElementById("test4"));     
            tab.setActive();            
            tabcontrol.parent = document.getElementById("test");
            tabcontrol.init();
        </script>

</body>
</html>

css:

tab_tabbuttonactive
{
    cursor:hand;
    text-align:center;
    vertical-align:middle;
    background-color: #cde6f8;
    border-width:1px;
    border-top:solid 1px #336699;
    border-left:solid 1px #336699;
    border-right:solid 1px #336699;
    display:inline;
    float:left;  
    height:26px;
    width:80px;
    text-align:center;
    vertical-align:middle;
    line-height:2;
}
.tab_padding
{
    cursor:hand;
    text-align:center;
    vertical-align:middle;
    border-bottom:solid 1px #336699; 
    border-width:1px;
    background-color: #98b1c4; 
    display:inline;
    float:left;  
    height:27px;
}
.tab_tabbutton
{
    cursor:hand;
    text-align:center;
    vertical-align:middle;
    border-bottom:solid 1px #336699; 
    border-width:1px;
    background-color: #98b1c4; 
    display:inline;
    float:left;  
    height:26px;
    width:80px;
    text-align:center;
    vertical-align:middle;
    line-height:2;
}
.tab_banner
{
    cursor:hand;
    text-align:center;
    vertical-align:middle;
    background-color: #98b1c4; 
    height:27px;  
}
.tab_head
{
    cursor:hand;
    text-align:center;
    vertical-align:middle;
    border-bottom:solid 1px #336699; 
    border-width:1px;
    background-color: #98b1c4; 
    display:inline;
    float:left;  
    width:12px;
    height:27px;
}
.tab_line
{
    background-color:#cde6f8;
    line-height: 6px;
}
InnocentBoy 2007-05-08
总体感觉不太细腻,效果是有了。
zyl123456 2007-05-07
可能我表达不清楚,我的意思是通过调用一个head文件,点不同栏目的时候,该栏目就高亮显示,就是要这种效果...

就是要在head.asp这个文件里动态调用<div id="attendanceNavg">这个里的id值,那么这个id值如何才能实现动态啊.

比如现在前台栏目有:栏目一、栏目二、栏目三,如何能让id的值分别对应到这三个栏目。。。
zyl123456 2007-05-07
动态取得ID后,是不是在CSS样式表也要加上相应的样式啊
zyl123456 2007-05-07
大哥,能否指点小妹一下,后台相关菜单的ID是怎么写的啊,怎么样才能动态生成那个ID号,就是前面li调用的那个ID。我用的是ASP,不知道怎么写啦,不然要高光显示各栏目,就得做很多个head文件了。。。小妹谢谢了。。。
比如后台功能菜单有公司简介、产品展示、联系我们,那么如何才能生成那个ID号呢?
gs.liutong 2007-05-06
CSS真不错,就是不太会用,有时间要学学了。
kj23 2007-04-30
可能你只着眼与tab的效果实现了

我提问过很多次了,当几十张乃至更多的页面在这里切换

都写在一个页面上恐怕不现实吧,这才是设计的初衷,否则上面很多朋友介绍的作品都比这个好吧

代码建议在ff下面跑一下,和ie下看到的差别还是蛮大的,主要是css上需要调整一下
laochake 2007-04-30
kj23 写道
M是不是立体的这个问题其实不属于View设计的范畴。

这个页面设计的再好一点,就是让2级菜单成为一级菜单的一个子项。

这样就能体现zkj说的立体模型了


在lz的基础上修改
1.去除了css对id的依赖
2.把2级菜单成为一级菜单的一个子项,选中时,通过一小段js将其显示
laochake 2007-04-30
kj23 写道
M是不是立体的这个问题其实不属于View设计的范畴。

这个页面设计的再好一点,就是让2级菜单成为一级菜单的一个子项。

这样就能体现zkj说的立体模型了



我修改了一下:
1.去除了 css 文件对 id 的依赖
2.把2级菜单设为一级菜单的一个子项,选中某个一级菜单时,用一小段js将二级详细显示出来


欢迎拍砖
kj23 2007-04-24
.net 写成UserControl更加方便,而且还可以实现编辑器视图,比java爽多了。

二级菜单转为子项也很简单啊


<asp:Repeater id=Repeater1 runat="server">
<ul>
<ItemTemplate>
<li>
   <ul>
     <li/>
   </ul>
</li>
</ItemTemplate>
</ul>
</asp:Repeater>



差不多就是这个意思

css要调整一下,改成下来或者抽屉式的都很方便的
iostrip 2007-04-24
楼主做的真的很漂亮,而且正是我想要得。但是,我是使用Asp.net的。没有看明白楼主的JSP代码(将这段HTML的片断抽取到一个JSP中,然后include到真正的业务页面上)。
能不能请楼主再辛苦一下,做一个菜单让2级菜单成为一级菜单的一个子项(用javascript也不要紧),或者给详细讲解一下在程序中自动调用的过程呢!
我的项目中正好需要一个这样的菜单。恳请楼主帮忙了!
cherami 2007-04-17
不错,值得参考
Janson Mike 2007-04-16
你提供的源代码怎样登录呀,就是用户名和密码是多少?
kj23 2007-03-28
Js的解决方案有很多,仁者见仁,智者见智了

这个tab也有一模一样的一个js版本,但是项目中,如果使用js,我就用到frame来切换了,开发就变得不那么方便了
hred 2007-03-28
附件是Jquery 下的一个plugin ,N种tab效果。对比一下。
blu3leaf 2007-03-28
这东西好啊~~正愁界面呢~~多谢lz大人
huansinho 2007-03-25
我觉得CSS在开发时可以很好的解决编程人员和网页设计人员的问题
chenxu 2007-03-08
非常的不错,可以直接拿来用到项目中
kj23 2007-03-07
那不是又回到当年用table去模拟layout的老路上去了

这种做法的唯一好处,就是可以无级变色,换skin用,代码上来说非常多的无语义标签掺杂其中
pissa 2007-03-07
<code>
<html>
<head>
<title>css圆角</title>
<meta http-equiv="content-type" content="text/html; charset=gb2312">
<style type="text/css">
div.RoundedCorner{background: #9BD1FA}
b.rtop, b.rbottom{display:block;background: #FFF}
b.rtop b, b.rbottom b{display:block;height: 1px;overflow: hidden; background: #9BD1FA}
b.r1{margin: 0 5px}
b.r2{margin: 0 3px}
b.r3{margin: 0 2px}
b.rtop b.r4, b.rbottom b.r4{margin: 0 1px;height: 2px}
</style>
</head>
<body>
<div class="RoundedCorner">
<b class="rtop">
<b class="r1"></b>
<b class="r2"></b>
<b class="r3"></b>
<b class="r4"></b>
</b>
<br>无图片实现圆角框<br><br>
<b class="rbottom">
<b class="r4"></b>
<b class="r3"></b>
<b class="r2"></b>
<b class="r1"></b>
</b>
</div>
</body>
</html>

</code>

这样就没有图片了,其实就是线条的长短构成圆角:
--------
--------------
----------------
----------------
----------------
----------------
----------------
----------------
--------------
----------
downpour
搜索本博客
存档
最新评论