下面是一个使用HTML的ul标签制作的关于国家区划的组织结构图。

  • 中国

    • 北京
    • 广东省
      • 广州市
      • 韶关市
    • 海南省
      • 海口市

        • 美兰区
        • 龙华区
        • 秀英区
        • 琼山区
      • 三亚市
    • 安徽省
      • 合肥市
      • 安庆市
  • United States of America
    • Washington
    • Florida

我们的目标是,在保持最干净的HTML源码不变的情况下,只使用CSS,将上面的结构图转换为下面的树形效果。

Ready? Go!

先看HMTL的代码。

  1. <ul class="domtree">
  2. <li>中国
  3. <ul>
  4. <li>北京</li>
  5. <li>广东省
  6. <ul>
  7. <li>广州市</li>
  8. <li>韶关市</li>
  9. </ul>
  10. </li>
  11. <li>海南省
  12. <ul>
  13. <li>海口市
  14. <ul>
  15. <li>美兰区</li>
  16. <li>龙华区</li>
  17. <li>秀英区</li>
  18. <li>琼山区</li>
  19. </ul>
  20. </li>
  21. <li>三亚市</li>
  22. </ul>
  23. </li>
  24. <li>安徽省
  25. <ul>
  26. <li>合肥市</li>
  27. <li>安庆市</li>
  28. </ul>
  29. </li>
  30. </ul>
  31. </li>
  32. <li>United States of America
  33. <ul>
  34. <li>Washington</li>
  35. <li>Florida</li>
  36. </ul>
  37. </li>
  38. </ul>

遵循惯例,先将ul的margin及padding置0。

  1. ul.domtree, ul.domtree ul {
  2. margin: 0;
  3. padding: 0;
  4. }

失去了层次结构。需将padding-left设为非零值。同时将li前面的项目图标去掉。

  1. ul.domtree, ul.domtree ul {
  2. margin: 0;
  3. padding: 0 0 0 2em;
  4. }
  5. ul.domtree li {
  6. list-style: none;
  7. }

上面的图例中,海口市的四个区有最深的层次。为简化思路,我们从最深一级,即美兰区开始思考解决问题的方法。在海口市与美兰区之间应有一条直角线段“└”将它们连起来。

鉴于美兰区是一个li元素,我们先画出其方框看看。

  1. ul.domtree li {
  2. list-style: none;
  3. border: 1px solid black;
  4. }

现在,方框围住了美兰区,我们需要将此方框推到美兰区的左边。也就是,在美兰区的左边应有一方框。因为上面已经澄清了目标,我们不能动HTML源码,因此我们可以通过CSS的before伪元素来为我们添加这个方框。

  1. ul.domtree li {
  2. list-style: none;
  3. }
  4. ul.domtree li:before {
  5. content: '';
  6. width: 1em;
  7. height: 1em;
  8. border: 1px solid black;
  9. }

先把li元素本身的边框去掉。因为我们只需一个方框而无需实质内容,因此content为空值。长、宽各设为1em的正方形。边框为黑线。

如上图所示,并没有出现一个正方形的边框。我们可以在content中输入实际内容,并较大幅度地增加长、宽值,比较其效果。

  1. ul.domtree li:before {
  2. content: 'a';
  3. width: 10em;
  4. height: 10em;
  5. border: 1px solid black;
  6. }

前面的围绕字符a的边框出现了,但尽管长宽值均设为10em,边框的面积还是不起变化。由于before伪元素的本意是在特定元素之前添加内容,应与该元素并排显示,因此被设定为inline型。而对处于流布局中的inline型设置具体的长宽不会有效果。此外,流布局元素也不能定位。解决的方法是将其脱离流布局即可。

  1. ul.domtree li {
  2. list-style: none;
  3. position: relative;
  4. }
  5. ul.domtree li:before {
  6. position: absolute;
  7. content: '';
  8. top: 0;
  9. left: 0;
  10. width: 1em;
  11. height: 1em;
  12. border: 1px solid black;
  13. }

因为content的内容隶属于li元素,因此我们先将其父元素li的position设为relative,再在li:before中将position设为absolute,这样可使content的内容脱离原来的流布局,且相对于li元素的位置来定位。注意上面的content已经恢复为空值,且长、宽恢复为1em。

别为上图的边框恰好围住一个汉字而搞晕了,看看图中的Florida,并没有围住单个字符。因此长、宽各为设1em碰巧围住了一个汉字而已。content的内容为空值也证明了边框面积与内容无关,而仅与长、宽值有关。同样,也别因为边框碰巧围住一个汉字而误以为边框会随汉字的移动而移动。再次重申,碰巧而已,这个边框是可以独立移动的。

现在,我们已经有了一个可以独立移动的边框,为了得到“└”的连线效果,还需做以下事情:

  1. 我们只需保留边框的左边及底边
  2. 把这两条边往左推至美兰区之前
  3. 调整这两条边的位置及长度

根据以上思路,调啊调,最终调成下面的数值及效果。

  1. ul.domtree li:before {
  2. position: absolute;
  3. content: '';
  4. top: -0.1em;
  5. left: -0.5em;
  6. width: 0.4em;
  7. height: 0.615em;
  8. border-style: none none solid solid;
  9. border-width: 0.05em;
  10. }

已经初具雏形了。但海口市下面的四个区应使用一条竖线将它们连通贯穿起来。此外,海口市与三亚市也应连起来。

由于海口市的四个区太密集了,这回换位思考,先看如何将海口市与三亚市连起来。

现在的问题变成:按照上面的思路,如果这条竖线也是通过边框的方式来实现,那么,在CSS中应选择哪个元素进行相应设置?是海口,还是三亚?先假设这条线已经调好相应的位置,则应顺着海南省的南字下边的竖线一直连向三亚市左边的竖线,贯穿了整个海口市所在区域。因此,应选择海口市的li元素。且由于三亚市左边的竖线已经高于其文字上端,因此,三亚市无需再设置竖线。

同样道理,北京连广东连海南连安徽,只需设置北京、广东和海南所在区域的竖线,而安徽无需设置。而对于中国与United States of America,只需设置中国。

找到规律了吗?如果没有,让我们借助图形来洞悉事实的真相。

上图中,红色部分表示需要设置连线的元素,而灰色表示无需设置连线的元素。

其规律是,每一层级的最后一项元素,无需设置连线;不是最后一项元素,则需设置连线。

如何找出最后一项元素,以及,不是最后一项的元素?幸喜CSS提供了这样的选择器。上图的效果所用到的CSS内容如下:

  1. ul.domtree li:last-child {
  2. color: gray;
  3. }
  4. ul.domtree li:not(:last-child) {
  5. color: red;
  6. }

既然已经甄别出来,显而易见,只需对li:not(:last-child)进行设置即可。

我们上面已经使用before的伪元素设置了li元素之前的连线,这回,我们使用其搭档after伪元素设置左边的竖线。严格来说,after伪元素是在元素的后面添加新的内容。但由于我们通过绝对定位的方式,即使是后面的,我们也可将其调至前面来。参照之前的例子,设置CSS如下:

  1. ul.domtree li:not(:last-child):after {
  2. position: absolute;
  3. content: '';
  4. top: 0;
  5. left: 0;
  6. height: 1em;
  7. border-style: none none none solid;
  8. border-width: 0.05em;
  9. }

因为我们只需要一条线,因此无需设边框的宽度,且此边取值于边框的左线。

各个li元素的竖线已经站在其左边待命,但不够长。上面的height取固定值1em,显然不能应付各种长度不一致的的场合,如中国连向United States of America的连线就比海口市连向三亚市的连线要长。

如果说height是从top往下计算的数值,则bottom则是从下向上计算的数值。使用bottom代替height,可使这条直线的长度自动延伸到足以覆盖该元素的整个高度,而不管该元素的具体高度是多少。

  1. ul.domtree li:not(:last-child):after {
  2. position: absolute;
  3. content: '';
  4. top: 0;
  5. left: 0;
  6. bottom: 0;
  7. border-style: none none none solid;
  8. border-width: 0.05em;
  9. }

已经胜利在望了,剩下需做的,就是将left值往左调。最后,将上面显示不同颜色的CSS代码去掉,就可得到下面的效果。

Game Over.

因篇幅不长,这里列出上述CSS的全部源码。

  1. ul.domtree, ul.domtree ul {
  2. margin: 0;
  3. padding: 0 0 0 2em;
  4. }
  5. ul.domtree li {
  6. list-style: none;
  7. position: relative;
  8. }
  9. ul.domtree li:before {
  10. position: absolute;
  11. content: '';
  12. top: -0.1em;
  13. left: -0.5em;
  14. width: 0.4em;
  15. height: 0.615em;
  16. border-style: none none solid solid;
  17. border-width: 0.05em;
  18. }
  19. /*
  20. ul.domtree li:last-child {
  21. color: gray;
  22. }
  23. ul.domtree li:not(:last-child) {
  24. color: red;
  25. }
  26. */
  27. ul.domtree li:not(:last-child):after {
  28. position: absolute;
  29. content: '';
  30. top: 0;
  31. left: -0.5em;
  32. bottom: 0;
  33. border-style: none none none solid;
  34. border-width: 0.05em;
  35. }

注::before及:after伪元素始自于CSS2.1,:last-child伪类及:not伪类始于CSS3。因此,本文的实现需要支持CSS3的浏览器支持。

from:http://blog.csdn.net/tanghw/article/details/7102077

[转]使用CSS3实现树形控件的更多相关文章

  1. js树形控件—zTree使用总结

    0 zTree简介 树形控件的使用是应用开发过程中必不可少的.zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. 0.0 ...

  2. 关于 DevExpress.XtraTreeList.TreeList 树形控件 的操作

    作为一个C#程序员,在写程序时一直以来都使用的微软那一套控件,用起来特别爽,可是最近公司的一个项目用到了DevExpress框架,不用不知道,一用吓一跳,不得不承认这个框架确实很强大,效果也很炫,但是 ...

  3. 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>

    上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...

  4. js树形控件

    js树形控件 ztree http://www.treejs.cn/

  5. TreeView树形控件递归绑定数据库里的数据

    TreeView树形控件递归绑定数据库里的数据. 第一种:性能不好 第一步:数据库中查出来的表,字段名分别为UNAME(显示名称),DID(关联数据),UTYPE(类型) 第二步:前台代码 <% ...

  6. Devexpress treelist 树形控件 实现带三种状态的CheckBox

    树形控件是使用频率很高的一种控件.对于属性控件往往需要下面两个功能 1.TreeList带有CheckBox,并且节点要有三种状态(所有的子节点都选中,所有的子节点都没选择,一部分子节点选中).使用 ...

  7. Qt树形控件QTreeView使用1——节点的添加删除操作 复选框的设置

    QtreeView是ui中最常用的控件,Qt中QTreeWidget比QTreeView更简单,但没有QTreeView那么灵活(QTreeWidget封装的和MFC的CTreeCtrl很类似,没有m ...

  8. SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题

    转:http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发--关于TreeView树形控 ...

  9. Android 打造任意层级树形控件 考验你的数据结构和设计

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会 ...

随机推荐

  1. poj3334Connected Gheeves(二分)

    链接 二分高度,算面积的地方有点麻烦,没有用求交点的模板,直接自己按三角形相似手算了一下,写的有点麻烦. 上下界直接取水可放的最高点以及最低点. 自己的长得很挫的代码 #include <ios ...

  2. (四)ubuntu学习前传—uboot中对Flash和DDR的管理

    1.uboot阶段Flash的分区 (1)所谓分区,就是说对Flash进行分块管理.(2)PC机等产品中,因为大家都是在操作系统下使用硬盘的,整个硬盘由操作系统统一管理,操作系统会使用文件系统帮我们管 ...

  3. JavaScript的事件对象_概述/this

    JavaScript 事件的一个重要方面是它们拥有一些相对一致的特点,可以给你的开发提供更多的强大功能. 最方便和强大的就是事件对象,他们可以帮你处理鼠标事件和键盘敲击方面的情况,此外还可以修改一般事 ...

  4. C#_拆箱跟装箱

    Net的类型分为两种,一种是值类型,另一种是引用类型.这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上.那么如果要把一个值类型数据放到堆上,就需要装箱操作:反之,把一个放在堆上的 ...

  5. JavaScript 同名方法的处理

    在JS中,如果存在同名同参的方法,它会先调用哪一个?先看两个例子: 例1: <html> <head> <title></title> <scri ...

  6. zookeeper错误

    ZooKeeper JMX enabled by defaultUsing config: /data4/hadoop/zookeeper-3.4.8/bin/../conf/zoo.cfgError ...

  7. 解决由于一个软件限制策略的阻止,windows无法运行此程序cmd.reg

    解决由于一个软件限制策略的阻止,windows无法运行此程序cmd.reg Windows Registry Editor Version 5.00 [-HKEY_LOCAL_MACHINE\SOFT ...

  8. SAP MM移动平均价和标准价逻辑

    从收货到领用,S一直都是以标准价格计算,V是实时更新 S 时将差异结转到在产品,产品中,最后结转到生产成本,最终到利润.具有计划性,可以控制考核 V 是实时更新,出现差异直接对应材料中调整.价格可以直 ...

  9. 【转】 STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

  10. centos nginx 安装

    1.下载 wget http://nginx.org/download/nginx-1.7.8.tar.gz 2.解压 tar -zxvf nginx-1.7.8.tar.gz 3.切换目录 cd n ...