[转]使用CSS3实现树形控件
下面是一个使用HTML的ul标签制作的关于国家区划的组织结构图。
- 中国
- 北京
- 广东省
- 广州市
- 韶关市
- 海南省
- 海口市
- 美兰区
- 龙华区
- 秀英区
- 琼山区
- 三亚市
- 海口市
- 安徽省
- 合肥市
- 安庆市
- United States of America
- Washington
- Florida
我们的目标是,在保持最干净的HTML源码不变的情况下,只使用CSS,将上面的结构图转换为下面的树形效果。
Ready? Go!
先看HMTL的代码。
- <ul class="domtree">
- <li>中国
- <ul>
- <li>北京</li>
- <li>广东省
- <ul>
- <li>广州市</li>
- <li>韶关市</li>
- </ul>
- </li>
- <li>海南省
- <ul>
- <li>海口市
- <ul>
- <li>美兰区</li>
- <li>龙华区</li>
- <li>秀英区</li>
- <li>琼山区</li>
- </ul>
- </li>
- <li>三亚市</li>
- </ul>
- </li>
- <li>安徽省
- <ul>
- <li>合肥市</li>
- <li>安庆市</li>
- </ul>
- </li>
- </ul>
- </li>
- <li>United States of America
- <ul>
- <li>Washington</li>
- <li>Florida</li>
- </ul>
- </li>
- </ul>
遵循惯例,先将ul的margin及padding置0。
- ul.domtree, ul.domtree ul {
- margin: 0;
- padding: 0;
- }
失去了层次结构。需将padding-left设为非零值。同时将li前面的项目图标去掉。
- ul.domtree, ul.domtree ul {
- margin: 0;
- padding: 0 0 0 2em;
- }
- ul.domtree li {
- list-style: none;
- }
上面的图例中,海口市的四个区有最深的层次。为简化思路,我们从最深一级,即美兰区开始思考解决问题的方法。在海口市与美兰区之间应有一条直角线段“└”将它们连起来。
鉴于美兰区是一个li元素,我们先画出其方框看看。
- ul.domtree li {
- list-style: none;
- border: 1px solid black;
- }
现在,方框围住了美兰区,我们需要将此方框推到美兰区的左边。也就是,在美兰区的左边应有一方框。因为上面已经澄清了目标,我们不能动HTML源码,因此我们可以通过CSS的before伪元素来为我们添加这个方框。
- ul.domtree li {
- list-style: none;
- }
- ul.domtree li:before {
- content: '';
- width: 1em;
- height: 1em;
- border: 1px solid black;
- }
先把li元素本身的边框去掉。因为我们只需一个方框而无需实质内容,因此content为空值。长、宽各设为1em的正方形。边框为黑线。
如上图所示,并没有出现一个正方形的边框。我们可以在content中输入实际内容,并较大幅度地增加长、宽值,比较其效果。
- ul.domtree li:before {
- content: 'a';
- width: 10em;
- height: 10em;
- border: 1px solid black;
- }
前面的围绕字符a的边框出现了,但尽管长宽值均设为10em,边框的面积还是不起变化。由于before伪元素的本意是在特定元素之前添加内容,应与该元素并排显示,因此被设定为inline型。而对处于流布局中的inline型设置具体的长宽不会有效果。此外,流布局元素也不能定位。解决的方法是将其脱离流布局即可。
- ul.domtree li {
- list-style: none;
- position: relative;
- }
- ul.domtree li:before {
- position: absolute;
- content: '';
- top: 0;
- left: 0;
- width: 1em;
- height: 1em;
- border: 1px solid black;
- }
因为content的内容隶属于li元素,因此我们先将其父元素li的position设为relative,再在li:before中将position设为absolute,这样可使content的内容脱离原来的流布局,且相对于li元素的位置来定位。注意上面的content已经恢复为空值,且长、宽恢复为1em。
别为上图的边框恰好围住一个汉字而搞晕了,看看图中的Florida,并没有围住单个字符。因此长、宽各为设1em碰巧围住了一个汉字而已。content的内容为空值也证明了边框面积与内容无关,而仅与长、宽值有关。同样,也别因为边框碰巧围住一个汉字而误以为边框会随汉字的移动而移动。再次重申,碰巧而已,这个边框是可以独立移动的。
现在,我们已经有了一个可以独立移动的边框,为了得到“└”的连线效果,还需做以下事情:
- 我们只需保留边框的左边及底边
- 把这两条边往左推至美兰区之前
- 调整这两条边的位置及长度
根据以上思路,调啊调,最终调成下面的数值及效果。
- ul.domtree li:before {
- position: absolute;
- content: '';
- top: -0.1em;
- left: -0.5em;
- width: 0.4em;
- height: 0.615em;
- border-style: none none solid solid;
- border-width: 0.05em;
- }
已经初具雏形了。但海口市下面的四个区应使用一条竖线将它们连通贯穿起来。此外,海口市与三亚市也应连起来。
由于海口市的四个区太密集了,这回换位思考,先看如何将海口市与三亚市连起来。
现在的问题变成:按照上面的思路,如果这条竖线也是通过边框的方式来实现,那么,在CSS中应选择哪个元素进行相应设置?是海口,还是三亚?先假设这条线已经调好相应的位置,则应顺着海南省的南字下边的竖线一直连向三亚市左边的竖线,贯穿了整个海口市所在区域。因此,应选择海口市的li元素。且由于三亚市左边的竖线已经高于其文字上端,因此,三亚市无需再设置竖线。
同样道理,北京连广东连海南连安徽,只需设置北京、广东和海南所在区域的竖线,而安徽无需设置。而对于中国与United States of America,只需设置中国。
找到规律了吗?如果没有,让我们借助图形来洞悉事实的真相。
上图中,红色部分表示需要设置连线的元素,而灰色表示无需设置连线的元素。
其规律是,每一层级的最后一项元素,无需设置连线;不是最后一项元素,则需设置连线。
如何找出最后一项元素,以及,不是最后一项的元素?幸喜CSS提供了这样的选择器。上图的效果所用到的CSS内容如下:
- ul.domtree li:last-child {
- color: gray;
- }
- ul.domtree li:not(:last-child) {
- color: red;
- }
既然已经甄别出来,显而易见,只需对li:not(:last-child)进行设置即可。
我们上面已经使用before的伪元素设置了li元素之前的连线,这回,我们使用其搭档after伪元素设置左边的竖线。严格来说,after伪元素是在元素的后面添加新的内容。但由于我们通过绝对定位的方式,即使是后面的,我们也可将其调至前面来。参照之前的例子,设置CSS如下:
- ul.domtree li:not(:last-child):after {
- position: absolute;
- content: '';
- top: 0;
- left: 0;
- height: 1em;
- border-style: none none none solid;
- border-width: 0.05em;
- }
因为我们只需要一条线,因此无需设边框的宽度,且此边取值于边框的左线。
各个li元素的竖线已经站在其左边待命,但不够长。上面的height取固定值1em,显然不能应付各种长度不一致的的场合,如中国连向United States of America的连线就比海口市连向三亚市的连线要长。
如果说height是从top往下计算的数值,则bottom则是从下向上计算的数值。使用bottom代替height,可使这条直线的长度自动延伸到足以覆盖该元素的整个高度,而不管该元素的具体高度是多少。
- ul.domtree li:not(:last-child):after {
- position: absolute;
- content: '';
- top: 0;
- left: 0;
- bottom: 0;
- border-style: none none none solid;
- border-width: 0.05em;
- }
已经胜利在望了,剩下需做的,就是将left值往左调。最后,将上面显示不同颜色的CSS代码去掉,就可得到下面的效果。
Game Over.
因篇幅不长,这里列出上述CSS的全部源码。
- ul.domtree, ul.domtree ul {
- margin: 0;
- padding: 0 0 0 2em;
- }
- ul.domtree li {
- list-style: none;
- position: relative;
- }
- ul.domtree li:before {
- position: absolute;
- content: '';
- top: -0.1em;
- left: -0.5em;
- width: 0.4em;
- height: 0.615em;
- border-style: none none solid solid;
- border-width: 0.05em;
- }
- /*
- ul.domtree li:last-child {
- color: gray;
- }
- ul.domtree li:not(:last-child) {
- color: red;
- }
- */
- ul.domtree li:not(:last-child):after {
- position: absolute;
- content: '';
- top: 0;
- left: -0.5em;
- bottom: 0;
- border-style: none none none solid;
- border-width: 0.05em;
- }
注::before及:after伪元素始自于CSS2.1,:last-child伪类及:not伪类始于CSS3。因此,本文的实现需要支持CSS3的浏览器支持。
from:http://blog.csdn.net/tanghw/article/details/7102077
[转]使用CSS3实现树形控件的更多相关文章
- js树形控件—zTree使用总结
0 zTree简介 树形控件的使用是应用开发过程中必不可少的.zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. 0.0 ...
- 关于 DevExpress.XtraTreeList.TreeList 树形控件 的操作
作为一个C#程序员,在写程序时一直以来都使用的微软那一套控件,用起来特别爽,可是最近公司的一个项目用到了DevExpress框架,不用不知道,一用吓一跳,不得不承认这个框架确实很强大,效果也很炫,但是 ...
- 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>
上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...
- js树形控件
js树形控件 ztree http://www.treejs.cn/
- TreeView树形控件递归绑定数据库里的数据
TreeView树形控件递归绑定数据库里的数据. 第一种:性能不好 第一步:数据库中查出来的表,字段名分别为UNAME(显示名称),DID(关联数据),UTYPE(类型) 第二步:前台代码 <% ...
- Devexpress treelist 树形控件 实现带三种状态的CheckBox
树形控件是使用频率很高的一种控件.对于属性控件往往需要下面两个功能 1.TreeList带有CheckBox,并且节点要有三种状态(所有的子节点都选中,所有的子节点都没选择,一部分子节点选中).使用 ...
- Qt树形控件QTreeView使用1——节点的添加删除操作 复选框的设置
QtreeView是ui中最常用的控件,Qt中QTreeWidget比QTreeView更简单,但没有QTreeView那么灵活(QTreeWidget封装的和MFC的CTreeCtrl很类似,没有m ...
- SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题
转:http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发--关于TreeView树形控 ...
- Android 打造任意层级树形控件 考验你的数据结构和设计
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会 ...
随机推荐
- python计算文件的行数和读取某一行内容的实现方法
一.计算文件的行数 最简单的办法是把文件读入一个大的列表中,然后统计列表的长度.如果文件的路径是以参数的形式filepath传递的,那么只用一行代码就可以完成我们的需求了:count = len(op ...
- iOS - UITabBarController
前言 NS_CLASS_AVAILABLE_IOS(2_0) @interface UITabBarController : UIViewController <UITabBarDelegate ...
- [转]ubuntu下安装程序的三种方法
出处:http://www.cnblogs.com/xwdreamer/p/3623454.html 引言 在ubuntu当中,安装应用程序我所知道的有三种方法,分别是apt-get,dpkg安装de ...
- jquery+ajax(用ajax.dll)实现无刷新分页
利用ajax.dll那种方式的无刷新,在这就不说了,新朋友可以看下我的另一片文件http://www.cnblogs.com/dachuang/p/3654632.html 首先,这里用的是jquer ...
- 转!!MAC和PHY的区别
一块以太网网卡包括OSI(开方系统互联)模型的两个层,物理层和数据链路层.物理层定义了数据传送与接收所需要的电与光信号.线路状态.时钟基准.数据编码和电路等,并向数据链路层设备提供标准接口.数据链路层 ...
- php错误以及常用笔记
//语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. /* [命名规则] */ 常量名 类常量建议全大写,单词间用下划线分隔 // MIN_WIDTH 变量名建 ...
- Linux里设置环境变量的方法(export PATH)
1.动态库路径的设置 Linux下调用动态库和windows不一样.linux 可执行程序是靠配置文件去读取路径的,因此有些时候需要设置路径 具体操作如下 export LD_LIBRARY_PATH ...
- 添加无线服务wzcsvc服务,Eventlog服务
<添加eventlog服务.reg> Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentCont ...
- sizeof和strlen()的区别
二者有本质上的区别 从定义可以知道sizeof只是一个operator,而strlen()则是定义一个定义在<string.h>中的函数;所以sizeof(string)是在计算strin ...
- jqury.jqzoom插件--放大镜
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...