HTMLCSS中的树形结构图

我们可以只使用 html 和 css 创建树视图(可折叠列表) ,而不需要 JavaScript。可访问性软件将看到树形视图作为列表嵌套在披露窗口小部件中,并且自动支持标准键盘交互。

 1、HTML

我们就从简单嵌套列表的 html 开始:

<ul>
  <li>
    Giant planets
    <ul>
      <li>
        Gas giants
        <ul>
          <li>Jupiter</li>
          <li>Saturn</li>
        </ul>
      </li>
      <li>
        Ice giants
        <ul>
          <li>Uranus</li>
          <li>Neptune</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

       然后,我们向最外层的 < ul > 元素添加一个类,对于每个包含嵌套列表的列表项,我们将列表项的内容放在 < Details > 和 < Summary > 元素中,使用 open 属性来控制最初展开哪些嵌套列表:

<ul class="tree">
  <li>
    <details open>
      <summary>Giant planets</summary>
      <ul>
        <li>
          <details>
            <summary>Gas giants</summary>
            <ul>
              <li>Jupiter</li>
              <li>Saturn</li>
            </ul>
          </details>
        </li>
        <li>
          <details>
            <summary>Ice giants</summary>
            <ul>
              <li>Uranus</li>
              <li>Neptune</li>
            </ul>
          </details>
        </li>
      </ul>
    </details>
  </li>
</ul>

没有任何样式,这个 html 生成:

浏览器将 < Details > 元素实现为一个披露窗口小部件,使其能够展开和折叠嵌套列表,但是项目符号和披露箭头的组合会产生一个令人困惑的用户界面。 

2、自定义属性:

       有两个维度影响树视图的布局: 行间距(等于文本的行高)和标记的半径。我们首先为这些维度创建 CSS 自定义属性:

.tree{
  --spacing : 1.5rem;
  --radius  : 10px;
}

       虽然我们通常使用相对单位来缩放基于文本大小的用户界面控件,但对于标记,这可能导致控件过小或过大,所以我们使用一个合理的固定大小。

3、padding

       然后我们设计列表项和嵌套列表的样式,为行和标记腾出空间:

.tree li{
  display      : block;
  position     : relative;
  padding-left : calc(2 * var(--spacing) - var(--radius) - 2px);
}

.tree ul{
  margin-left  : calc(var(--radius) - var(--spacing));
  padding-left : 0;
}

        第7行从列表项中删除项目符号点。第8行建立了一个新的堆叠上下文和包含块,我们将使用它来定位行和标记。

       第9行缩进列表项。缩进等于两倍的间距,减去标记半径,减去两个像素的行宽。其结果是,列表项中的文本将与其下方的标记的左侧对齐。

       第13行使用负边距来补偿第9行引入的缩进,确保嵌套列表只按所需的间距缩进。第14行删除浏览器应用于列表的默认填充。

在最初展开所有嵌套列表的树视图中,应用此样式生成:

4、垂直线属性 

接下来,我们添加构成连接每个列表项标记的线的一部分的垂直线到其嵌套列表的标记:

.tree ul li{
  border-left : 2px solid #ddd;
}

.tree ul li:last-child{
  border-color : transparent;
}

       我们使用一个边框来创建这条线,并将其隐藏在每个列表中的最后一个项目中,因为这条线不应该继续超过这个项目的标记。使边框透明,而不是完全删除它,避免了增加填充以进行补偿的需要。

应用这种风格生成:

5、水平线

 我们使用生成的内容来添加将垂直线连接到每个列表项的标记的水平线:

.tree ul li::before {
            content: '';
            display: block;
            position: absolute;
            top: calc(var(--spacing) / -2);
            left: -2px;
            width: calc(var(--spacing) + 2px);
            height: calc(var(--spacing) + 1px);
            border: solid #ddd;
            border-width: 0 0 2px 2px;
        }

       这段代码还创建了短的垂直线,因为之前创建的垂直线不会一直延伸到顶部和底部的标记。

       第26行和第27行生成一个块,第28行到第30行将其定位为从前一行文本的中点开始,与左侧的垂直线重叠。

       第31和32行设置块的大小。它需要比间距宽两个像素,因为它与左侧的垂直线重叠,并且比间距高一个像素,因为水平线宽度的一半位于文本行的中点以下。注意,我们假设使用边框大小,因此这些尺寸包括边框。

      第33和34行在块的左边和底边创建一个边框。

应用这种风格生成:

总结:

接下来,我们从摘要中删除默认样式:

.tree summary {
            display: block;
            cursor: pointer;
        }

        .tree summary::marker,
        .tree summary::-webkit-details-marker {
            display: none;
        }

        .tree summary:focus {
            outline: none;
        }

        .tree summary:focus-visible {
            outline: 1px dotted #000;
        }

        第38行和第44行删除了公开箭头。Safari 需要第44行,第42行和第43行的两个选择器覆盖了不同版本的浏览器。第39行更改光标以指示可以单击摘要以与其交互。

       Safari 在摘要周围显示了一个焦点指示器,即使是在使用指针而不是键盘导航的情况下,所以我们移除了第48行的焦点样式,然后使用 :focus-visible 伪类将其添加回来,供访问者使用第52行的键盘导航。

应用这种风格生成:

6、标识

 我们再次使用生成的内容来创建标记:

        .tree li::after,
        .tree summary::before {
            content: '';
            display: block;
            position: absolute;
            top: calc(var(--spacing) / 2 - var(--radius));
            left: calc(var(--spacing) - var(--radius) - 1px);
            width: calc(2 * var(--radius));
            height: calc(2 * var(--radius));
            border-radius: 50%;
            background: #ddd;
        }

       注意,我们同时为 < li > 元素(不包含嵌套列表的列表项)和 < 摘要元素生成标记,允许包含嵌套列表的列表项具有不同的标记样式,具体取决于嵌套列表是展开的还是折叠的。

       第57行和第58行生成一个块,第59行到第61行将其置于水平线和垂直线交汇处的中心。顶部位于文本行的中点,减去半径。左边定位在垂直线的边缘,减去半径,减去对应于线宽一半的一个像素。

第62和63行设置块的大小,第64和65行将其设置为圆形。

应用这种风格生成:

 7、展开和折叠按钮

最后,我们添加了展开和折叠按钮:

       .tree summary::before {
            content: '+';
            z-index: 1;
            background: #696;
            color: #fff;
            line-height: calc(2 * var(--radius) - 2px);
            text-align: center;
        }

        .tree details[open]>summary::before {
            content: '−';
        }

       第69行和第78行显示了按钮中的加号与减号。请注意,我们使用真正的减号(-)而不是连字符(-) ,因为这与加号的外观相匹配,而在大多数字体中,连字符越窄越小。

       第70行使按钮显示在前面创建的标记之上。因为标记是使用: : 创建的,否则它将显示在按钮的顶部。

应用此样式生成完成的树视图:

8、这是完成的代码 

将以上所有内容结合起来,就得到了最终的代码:

CSS

    <style>
        .tree {
            --spacing: 1.5rem;
            --radius: 10px;
        }

        .tree li {
            display: block;
            position: relative;
            padding-left: calc(2 * var(--spacing) - var(--radius) - 2px);
        }

        .tree ul {
            margin-left: calc(var(--radius) - var(--spacing));
            padding-left: 0;
        }

        .tree ul li {
            border-left: 2px solid #ddd;
        }

        .tree ul li:last-child {
            border-color: transparent;
        }

        .tree ul li::before {
            content: '';
            display: block;
            position: absolute;
            top: calc(var(--spacing) / -2);
            left: -2px;
            width: calc(var(--spacing) + 2px);
            height: calc(var(--spacing) + 1px);
            border: solid #ddd;
            border-width: 0 0 2px 2px;
        }

        .tree summary {
            display: block;
            cursor: pointer;
        }

        .tree summary::marker,
        .tree summary::-webkit-details-marker {
            display: none;
        }

        .tree summary:focus {
            outline: none;
        }

        .tree summary:focus-visible {
            outline: 1px dotted #000;
        }

        .tree li::after,
        .tree summary::before {
            content: '';
            display: block;
            position: absolute;
            top: calc(var(--spacing) / 2 - var(--radius));
            left: calc(var(--spacing) - var(--radius) - 1px);
            width: calc(2 * var(--radius));
            height: calc(2 * var(--radius));
            border-radius: 50%;
            background: #ddd;
        }

        .tree summary::before {
            content: '+';
            z-index: 1;
            background: #696;
            color: #fff;
            line-height: calc(2 * var(--radius) - 2px);
            text-align: center;
        }

        .tree details[open]>summary::before {
            content: '−';
        }
    </style>

HTML

<body>
    <ul class="tree">
        <li>
            <details open>
                <summary>Giant planets</summary>
                <ul>
                    <li>
                        <details>
                            <summary>Gas giants</summary>
                            <ul>
                                <li>Jupiter</li>
                                <li>Saturn</li>
                            </ul>
                        </details>
                    </li>
                    <li>
                        <details>
                            <summary>Ice giants</summary>
                            <ul>
                                <li>Uranus</li>
                                <li>Neptune</li>
                            </ul>
                        </details>
                    </li>
                </ul>
            </details>
        </li>
    </ul>
</body>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/23871.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hbase操作

(1) 启动 启动顺序&#xff1a;Hadoop--zookeeper—hbase 主进程&#xff1a;HMaster 从进程&#xff1a;HRegionServer 确认进程是否正常 (2) 进入终端 [rootmaster ~]# hbase shell (3) 查看状态 命令&#xff1a;status 表示有3台机器&#xff0c;0台down掉&…

位操作集锦

位操作集锦 异或运算两两交换数据签名检测两个数是否拥有不同的符号&#xff0c;即一个正数&#xff0c;一个负数寻找只出现一次的一个数字1寻找只出现两次的一个数字寻找只出现一次的一个数字2寻找只出现一次的两个数字 与和位移运算判断奇偶数二进制数中1的个数二进制数中最右…

MFC 给对话框添加图片背景

在windows开发当中做界面的主要技术之一就是使用MFC&#xff0c;通常我们看到的QQ,360,暴风影音这些漂亮的界面都可以用MFC来实现。今天我们来说一下如何用MFC美化对话框&#xff0c;默认情况下&#xff0c;对话框的背景如下&#xff1a; 那么&#xff0c;我们如何将它的背景变…

C++服务器框架开发3——协程与线程的简单理解/并发与并行

该专栏记录了在学习一个开发项目的过程中遇到的疑惑和问题。 其教学视频见&#xff1a;[C高级教程]从零开始开发服务器框架(sylar) 上一篇&#xff1a;C服务器框架开发2——头文件memory/typedef C服务器框架开发3——协程与线程的简单理解/并发与并行 目前进度协程与线程的简…

json-server的基本使用

1、mock是什么&#xff1f; mockjs 作用&#xff1a;生成随机数据&#xff0c;拦截 Ajax 请求 目的&#xff1a;很多时候前端开发页面的过程中&#xff0c;后端的接口并没有写好&#xff0c;这个时候需要前端自己定义接口及接口的返回数据的结构体&#xff0c;这个时候就需要…

ReactRouterDom-v5v6用法与异同

本文作者系360奇舞团前端开发工程师 简介&#xff1a; React Router Dom是React.js中用于实现路由功能的常用库。在React应用中&#xff0c;路由可以帮助我们管理页面之间的导航和状态&#xff0c;并实现动态加载组件。本文将深入探讨React Router Dom的两个主要版本&#xff1…

【微电网】含风、光、储联合发电的微电网优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Jupyter程序安装和使用指南【操作示例】

Jupyter Notebook(简称Jupyter)是一个交互式编辑器&#xff0c;它支持运行40多种编程语言&#xff0c;便于创建和共享文档。Jupyter本质上是一个Web应用程序&#xff0c;与其他编辑器相比&#xff0c;它具有小巧、灵活、支持实时代码、方便图表展示等优点。下面分别为大家演示如…

辅助生成: 低延迟文本生成的新方向

大型语言模型如今风靡一时&#xff0c;许多公司投入大量资源来扩展它们规模并解锁新功能。然而&#xff0c;作为注意力持续时间不断缩短的人类&#xff0c;我们并不喜欢大模型缓慢的响应时间。由于延迟对于良好的用户体验至关重要&#xff0c;人们通常使用较小的模型来完成任务…

EnjoyVIID部署

1、下载 git clone https://gitee.com/tsingeye/EnjoyVIID.git 2、导入数据库 创建表enjoyviid 导入数据库(修改数据库文件里的编码) EnjoyVIID/sql/tsingeye-viid.sql 3、修改配置 vim EnjoyVIID/tsingeye-admin/src/main/resources/application-dev.yml 修改数据库连接、re…

接口测试--apipost接口断言详解

在做接口测试的时候&#xff0c;会对接口进行断言&#xff0c;一个完整的接口测试&#xff0c;包括&#xff1a;请求->获取响应正文->断言。 一、apipost如何进行断言 apipost的断言设置实在后执行脚本中进行编写的。apipost本身提供了11中断言&#xff1a; apt.asser…

Linux-0.11 kernel目录进程管理asm.s详解

Linux-0.11 kernel目录进程管理asm.s详解 模块简介 该模块和CPU异常处理相关&#xff0c;在代码结构上asm.s和traps.c强相关。 CPU探测到异常时&#xff0c;主要分为两种处理方式&#xff0c;一种是有错误码&#xff0c;另一种是没有错误码&#xff0c;对应的方法就是error_c…

URP自定义屏幕后处理

回到目录 大家好&#xff0c;我是阿赵。这次来说一下URP渲染管线里面怎样使用后处理效果&#xff0c;还有怎样去自定义后处理效果。 一、使用URP自带的后处理效果 要使用URP自带的后处理效果&#xff0c;方法很简单&#xff0c;和Unity内置渲染管线的PostProcessing后处理很…

任务7 课程信息管理系统

系列文章 任务7 课程信息管理系统 已知课程的信息包括&#xff1a;课程编号&#xff0c;课程名称&#xff0c;课程性质&#xff08;必修、选修&#xff09;&#xff0c;课时&#xff0c;学分&#xff0c;考核方式&#xff08;考试、考查课&#xff09;&#xff0c;开课学期&a…

Ubuntu22.04安装MySQL8

在 Ubuntu 22.04 上安装 MySQL 8&#xff0c;可以按照以下步骤进行&#xff1a; 安装MySQL需要在root用户下 sudo su -更新软件包列表&#xff1a; sudo apt update安装 MySQL 8&#xff1a; sudo apt install mysql-server安装过程中会提示设置 MySQL root 用户的密码。 确认…

(学习日记)AD学习 #4

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

波奇学C++:模板和STL

什么是模板&#xff1f;为什么我们需要模板&#xff1f; 先假设一个场景&#xff0c;我们要编写一个函数交换a,b两个数的值 void swap(int& a,int& b) {int cmpa;ab;ba; } swap函数可以帮我们交换两个int型的值&#xff0c;那如果要交换的类型是float&#xff0c;do…

【linux解压和打包文件】

TOC 打包成zip文件 指令 zip zip -r -q -o html.zip html/ -r 参数表示递归打包包含子目录的全部内容&#xff0c;-q 参数表示为安静模式&#xff0c;即不向屏幕输出信息&#xff0c;-o 表示输出文件&#xff0c;需在其后紧跟打包输出文件名。解压zip文件 1.unzip -q …

【HMS Core】【ML Kit】活体检测FAQ合集

【问题描述1】 使用示例代码集成活体检测SDK时&#xff0c;报错state code -7001 【解决方案】 使用示例代码前请详细阅读示例工程中的“README”文件。您需要完成以下操作后才可以运行示例代码。 在AppGallery Connect网站下载自己应用的“agconnect-services.json”文件&a…

服务(第三十二篇)nginx做缓存服务器

nginx作为缓存服务配置语法 1、proxy_cache_path 配置语法&#xff08;即缓存路径配置语法&#xff09; Syntax&#xff1a;proxy_cache_path path [levelslevels] [use_temp_pathon|off] keys_zonename:size [inactivetime] [max_sizesize] [manager_filesnumber] [manager_s…