[转]使用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.概述 大家在项目中或多或少的可能会 ...
随机推荐
- hd1496---->这道题是水水的数论吗?
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1496 题意: Consider equations having the following form: ...
- loutsScript 常用代码
1.FTSearch搜索: Set dc=db.Ftsearch("name",0) '0位置为最大的查询数,0为所有匹配的文件 FTSearch必须创建数据库索引 Set doc ...
- shell script针对参数已经有配置好变量名称
/path/to/scriptname opt1 opt2 opt3 opt4 $ $ $ $ $ 这样够清楚了吧?运行的脚本档名为 $0 这个变量,第一个接的参数就是 $1 啊- 所以,只要我们在 ...
- [转]-Gradle使用手册(二):项目结构
原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Using-sourceCompatibility-1. ...
- python成长之路【第一篇】:python简介和入门
一.Python简介 Python(英语发音:/ˈpaɪθən/), 是一种面向对象.解释型计算机程序设计语言. 二.安装python windows: 1.下载安装包 https://www.pyt ...
- poj3855Blast the Enemy!(多边形重心)
链接 #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> ...
- poj1066Treasure Hunt(线段相交)
链接 很纠结的找到了所有线段的中点,又很纠结的找到了哪些中点可以直接相连,最后bfs一下求出了最短路.. #include <iostream> #include<cstdio> ...
- 值类型,引用类型,栈,堆,ref,out
在网上收集... C#的值类型,引用类型,栈,堆,ref,out C# 的类型系统可分为两种类型,一是值类型,一是引用类型,这个每个C#程序员都了解.还有托管堆,栈,ref,out等等概念也是每个C# ...
- ECMAScript 6入门 - let和const命令
详细学习链接: http://es6.ruanyifeng.com/#docs/let let命令 基本用法 ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命 ...
- phalcon: 表单
以实例为说明: controller <?php use \Phalcon\Forms\Form; use \Phalcon\Forms\Element\Text; use \Phalcon\F ...