【CSS in Depth 2 精译_039】6.3 CSS 定位技术之:相对定位(上)

news2024/9/30 3:56:48

当前内容所在位置(可进入专栏查看其他译好的章节内容)

  • 第一章 层叠、优先级与继承(已完结)
  • 第二章 相对单位(已完结)
  • 第三章 文档流与盒模型(已完结)
  • 第四章 Flexbox 布局(已完结)
  • 第五章 网格布局(已完结)
  • 【第六章 定位与堆叠上下文】 ✔️
    • 6.1 固定定位
      • 6.1.1 创建一个固定定位的模态对话框
      • 6.1.2 在模态对话框打开时防止屏幕滚动
      • 6.1.3 控制定位元素的大小
    • 6.2 绝对定位
      • 6.2.1 关闭按钮的绝对定位
      • 6.2.2 伪元素的定位问题
    • 6.3 相对定位 ✔️
      • 6.3.1 创建下拉菜单(上) ✔️
      • 6.3.2 创建 CSS 三角形(下)(精译中 ⏳)

文章目录

    • 6.3 相对定位 Relative positioning
      • 6.3.1 创建下拉菜单 Creating a dropdown menu

《CSS in Depth》新版封面

《CSS in Depth》新版封面

6.3 相对定位 Relative positioning

相对定位可能是最不被理解的定位类型。元素首次设置 position: relative 后,通常页面上看不到任何变化。被相对定位的元素及其周围的所有元素,都还保持着原来的位置(尽管某些元素可能会跑到另一些元素前面,这个问题稍后讨论)。

如果再加上与 inset 相关的属性,元素就会从原位置移走,但周围元素的位置却保持不变。如图 6.4 所示的四个行内块级(inline-block)元素,若给第二个元素指定三个额外属性:position: relative; top: 1em; left: 2em,该元素将从初始位置移走,而其余元素则不受影响。它们依旧遵循着常规文档流的行为模式,围绕在被移走元素的初始位置周围。

图 6.4 第二个元素在相对定位的作用下发生移动

图 6.4 第二个元素在相对定位的作用下发生移动

声明 top: 1em 将元素从原来的顶部边缘下移了 1em;而 left: 2em 则将元素从最初的左边缘右移了 2em。这可能导致该元素与其下方或旁边的其他元素发生重叠。元素定位时,属性值也可以取负值,如 bottom: -1em 可以令元素下移 1em,效果上与 top: 1em 相同。

注意

与固定定位和绝对定位不同,设置了相对定位的元素,无法使用 inset 相关的属性来控制其大小。这些值只能让元素上下左右移动。可以用 top 或者 bottom,但它们不能一起使用(否则 bottom 将被忽略);同理,可以用 left 或者 right,但它们也不能一起使用(否则 right 将被忽略)。

使用这些属性来调整相对元素(relative element)的位置偶尔也很管用,比如对摆放位置进行微调。但这并非相对定位最主要的用法;更常见的使用场景,是通过设置 position: relative 来为其内部的绝对定位元素(absolutely positioned element)创建一个包含块(containing block)。

6.3.1 创建下拉菜单 Creating a dropdown menu

接下来将用相对定位与绝对定位来创建一个下拉菜单。初始状态下,该菜单是一个普通的矩形按钮;当用户点击它时,则会弹出一个链接列表,如图 6.5 所示。

图 6.5 下拉菜单

图 6.5 下拉菜单效果图

该菜单的 HTML 标记如代码清单 6.5 所示。将属于菜单的部分添加到示例页 <main class="container"> 元素的开头。该代码包含了一个容器元素,用来设置里面的内容居中对齐,并与页面顶部横幅中的内容左对齐。而菜单下面的 <h1> 元素则是为了演示下拉菜单的弹框(popup)将出现在页面其他内容前方的效果。

代码清单 6.7 添加下拉菜单的 HTML 标记

<main class="container">
  <nav>
    <div class="dropdown" id="dropdown"><!-- 下拉菜单的容器 -->
      <!-- 切换按钮始终保持可见 -->
      <button type="button" class="dropdown-toggle" 
        id="dropdown-toggle">Main Menu</button>
      <!-- 随菜单的打开/关闭而显示/隐藏的 div 元素 -->
      <div class="dropdown-menu">
        <ul class="submenu">                           
          <li><a href="/">Home</a></li>                
          <li><a href="/coffees">Coffees</a></li>      
          <li><a href="/brewers">Brewers</a></li>      
          <li><a href="/specials">Specials</a></li>    
          <li><a href="/about">About us</a></li>       
        </ul>                                          
      </div>                                           
    </div>
  </nav>

  <h1>Wombat Coffee Roasters</h1>
</main>

下拉菜单的容器包含两个子元素:一个始终显示的切换按钮,以及一个会随下拉框的开合而显示与隐藏的下拉菜单。由于下拉菜单会设置绝对定位,因此它的出现并不会影响最初的页面布局。换言之,下拉菜单将出现在其他内容的前方。

而通过按下按钮来切换菜单的展开与关闭的逻辑,则需要一些 JavaScript 脚本的配合,如代码清单 6.8 所示。将它们更新到页面,实现这一功能。

代码清单 6.8 控制下拉菜单打开与关闭的 JavaScript 代码

<script type="text/javascript">
  const dropdownToggle = document.getElementById("dropdown-toggle");
  const dropdown = document.getElementById("dropdown");
 
  dropdownToggle.addEventListener("click", function (event) {
    dropdown.classList.toggle("is-open");
  });
</script>

这段代码与前面构建的模态对话框有些类似,通过按钮的点击实现在下拉菜单中添加或删除一个 is-open 类;基于该类的 CSS 代码则会同步切换对应的效果。

接着再给下拉菜单的容器设置相对定位,为内部绝对定位的菜单建立包含块。根据代码清单 6.9 更新页面样式。

代码清单 6.9 展示呈打开状态的下拉菜单样式

.dropdown {
  display: inline-block;
  position: relative;  /* 创建包含块 */
}
 
.dropdown-toggle {
  padding: 0.5em 1.5em;
  border: 1px solid #ccc;
  background-color: #eee;
  border-radius: 0;
}
 
.dropdown-menu {
  display: none;  /* 设置菜单初始隐藏 */
  position: absolute;
  left: 0;
  top: 2.1em;  /* 将菜单放到下拉菜单按钮的下方 */
  inline-size: max-content;
  min-inline-size: 100%;
  background-color: #eee;
}
 
.dropdown.is-open .dropdown-menu {
  display: block;  /* 菜单可用时予以显示 */
}
 
.submenu {
  padding-inline-start: 0;
  margin: 0;
  list-style-type: none;
  border: 1px solid #999;
}
 
.submenu > li + li {
  border-top: 1px solid #999;
}
 
.submenu > li > a {
  display: block;
  padding: 0.5em 1.5em;
  background-color: #eee;
  color: #369;
  text-decoration: none;
}
 
.submenu > li > a:hover {
  background-color: #fff;
}

这样,当点击主菜单的切换按钮时,其下方就会弹出下拉菜单;再次点击切换按钮,下拉菜单就关闭了。值得一提的是,类似功能也可以通过伪类 :hover 来实现,但该方案对键盘导航及触屏设备不太友好(如果此时打开模态对话框,您可能会看到模态框莫名其妙地跑到下拉菜单后面去了。不要紧,这个问题很快就会解决。)。

给绝对定位的 dropdown-menu 设置 left: 0,实现了其左边与整个容器左边对齐;而 top: 2.1em 则将其上边缘放置到按钮的下方(算上内边距与边框,切换按钮大约高 2.1em)。将 min-inline-size 的值设为 100% ,确保了其宽度至少与下拉菜单的容器宽度相当(该容器宽度则由其内部元素宽度、即切换按钮的实际宽度决定)。最后通过 submenu 类指定下拉菜单的具体样式。

注意

当下拉菜单位于屏幕右边缘时,通常会使用 right: 0 而非 left: 0 来进行定位。因为这样一来,宽度超过容器的菜单项则会紧贴按钮右边缘,同时向左延展至切换按钮的左侧,而不是溢出视口的右边缘。

构建页面时,可访问性是一个重要的考量因素,对于下拉菜单这样的交互元素(interactive elements)而言更是至关重要。即使再不济,至少也要确保用户能完全通过键盘实现页面交互。本例中的下拉菜单可以使用 Tab 健定位到切换按钮,并通过 Space 空格键切换菜单的打开与关闭。当菜单打开时,您还可以继续使用 Tab 健循环浏览菜单项。(而在苹果操作系统 Mac OS 上,可能还需要再系统偏好设置中打开键盘导航(enable keyboard navigation))。关于构建考虑页面可访问性的下拉菜单的更多信息,详见:https://www.webaxe.org/accessible-custom-select-dropdowns/

DIY 发散

最后讨论页面可访问性的问题时,作者顺便提到了一个小功能:下拉菜单打开时,可以通过 Tab 健循环浏览菜单项。然而该功能并没有在新版示例页中有所体现。根据提供的示例页 listing-6.09.html,用 Tab 下翻到最后一个菜单项或用 Shift + Tab 上翻到首个菜单项时,页面并不会自动循环浏览。要实现上述功能,还应该监听页面当前被激活的元素在菜单项中的位置:顺序浏览到最后一个时,下一次 Tab 让第一个菜单项得焦点;逆序浏览至首个菜单项时,则下一次 Tab 让最后一个子项得焦点。根据这个思路,其中一个经实测的 JS 版本如下:

// ... keep the same for handling the toggle of 'is-open' class
// use Tab to cycle through the menu items
const firstItem = dropdown.querySelector('li:first-of-type > a');
const lastItem =  dropdown.querySelector('li:last-of-type > a');
document.addEventListener("keydown", function (event) {
  const {key, shiftKey} = event;
  if (dropdown.classList.contains('is-open')) {
    if(key === 'Tab'){ 
      const {activeElement: active} = document;     
      if (shiftKey) {  // Shift + Tab
        if (active === firstItem) {
          event.preventDefault();
          lastItem.focus();  // Focus the last item
        }
      } else {  // Tab
        if (active === lastItem) {
          event.preventDefault();
          firstItem.focus();  // Focus the first item
        }
      }
    }
  }
});

上述代码的 firstItemlastItem 放到 keydown 事件逻辑的外面,是基于下拉菜单项数量和内容均固定的情况,即静态页面下的处理。如果下拉菜单是动态构建的(如从后端查询数据并在前端动态渲染),则最好放到第 7 行到第 9 行之间。作为必要的妥协,改到里面后,页面每次触发 keydown 事件都会执行 DOM 查询,性能上估计会差一点点,尤其是在频繁触发的情况下。适合放到哪里,得根据具体情况而定。



关于《CSS in Depth》(中译本书名《深入解析 CSS》)

第 1 版第 2 版
读者评分原版:4.7(亚马逊);中文版:9.3(豆瓣)原版:5.0(亚马逊);中文版:暂无,待出版
出版时间原版:2018 年 3 月;中文版:2020 年 4 月原版:2024 年 7 月;中文版:暂无,待出版
原价原版:$44.99;中文版:¥139.00原版:$59.99;中文版:暂无,待出版
现价原版:$36.49;中文版:¥52.54 起步原版:$52.09;中文版:暂无,待出版
原版国内预订起步价 ¥461.00起步价 ¥750.00

本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA插件:Maven Helper插件强势优化【某个依赖包被哪些maven项目模块引用,快速定位】体验真好!

背景&#xff1a; 开发的项目是maven多模块&#xff0c;子模块数量多&#xff0c;已经超过10个。 而且经常会被扫描漏洞&#xff0c;并进行依赖包升级。 在使用过程中&#xff0c;发现MavenHelper插件和IDEA自带的Analyze Dependencies都有个缺点&#xff1a;只能是单个模块…

【C++笔试强训】如何成为算法糕手Day3

​ 学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 目录 循环渐进Forward-CSDN博客 第一题&#xff1a;除2&#xff01; 第二题&#xff1a;dd爱框框 第三题&#xff1a;简写单词 第一题&#xff1a;除2&#xff01; 牛客网…

前端独立实现页面是否有发布

1、自动更新js (AutoUpdate.js) import { Modal } from "antd"let lastSrcs; const scriptReg /\<script.*src["](?<src>[^"])/gm; async function extractNewScripts() {const html await fetch(/?_timnestamp Date.now()).then(res > …

追随 HarmonyOS NEXT,Solon v3.0 将在10月8日发布

Solon &#xff08;开放原子开源基金会&#xff0c;孵化项目&#xff09;原计划10月1日发布 v3.0 正式版。看到 HarmonyOS NEXT 将在 10月8日启用公测&#xff0c;现改为10月8日发布以示庆贺。另外&#xff0c;Solon 将在2025年启动“仓颉”版开发&#xff08;届时&#xff0c;…

(11)(2.1.2) DShot ESCs(四)

文章目录 前言 6 混合ESC协议 7 IOMCU DShot限制 8 参数说明 前言 DShot 是一种数字 ESC 协议&#xff0c;它允许快速、高分辨率的数字通信&#xff0c;可以改善飞行器控制&#xff0c;这在多旋翼和 quadplane 应用中特别有用。 6 混合ESC协议 虽然 ArduPilot 自动驾驶仪…

Redis 为什么用跳表实现有序集合

近几年针对 Redis 面试时会涉及常见数据结构的底层设计&#xff0c;其中就有这么一道比较有意思的面试题&#xff1a;“Redis 的有序集合底层为什么要用跳表&#xff0c;而不用平衡树、红黑树或者 B树&#xff1f;”。 本文就以这道大厂常问的面试题为切入点&#xff0c;带大家…

Python 将数据写入 excel(新手入门)

一、场景分析 假设有如下一组列表数据&#xff1a; 写一段 python脚本 将这组数据写入一个新建的 excel&#xff0c;表头是 【序号】、【姓名】、【性别】、【年龄】 student_list [{name:小林, gender:男, age:10}, {name:小红, gender:女, age:11}, {name:小王, gender:男…

mysql数据库:超键、候选键、主键与外键

mysql数据库&#xff1a;超键、候选键、主键与外键 1、超键&#xff08;Superkey&#xff09;2、候选键&#xff08;Candidate Key&#xff09;3、主键&#xff08;Primary Key&#xff09;4、外键&#xff08;Foreign Key&#xff09; &#x1f496;The Begin&#x1f496;点点…

【Golang】Go语言接口与多态

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

106.WEB渗透测试-信息收集-FOFA语法(6)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;105.WEB渗透测试-信息收集-FOFA语法&#xff08;5&#xff09; FOFA语法案例&#xff1a…

金融领域的人工智能——Palmyra-Fin 如何重新定义市场分析

引言 DigiOps与人工智能 正在改变全球各行各业&#xff0c;并带来新的创新和效率水平。人工智能已成为金融领域的强大工具&#xff0c;为市场分析、风险管理和决策带来了新方法。金融市场以复杂性和快速变化而闻名&#xff0c;人工智能处理大量数据并提供清晰、可操作的见解的…

影刀---实现我的第一个抓取数据的机器人

你们要的csdn自动回复机器人在这里文末哦&#xff01; 这个上传的资源要vip下载&#xff0c;如果想了解影刀这个软件的话可以私聊我&#xff0c;我发你 目录 1.网页对象2.网页元素3.相似元素组4.元素操作设置下拉框复选框滚动条获取元素的信息 5.变量6.数据的表达字符串变量列…

企业身份安全管理面临的问题和解决方案

企业在向数字化、移动化、智能化加速发展的过程中&#xff0c;需加大信息化建设与数字化转型的投入已成为共识。企业建设的系统数量逐渐增多&#xff0c;部分企业甚至存在上千套信息化系统&#xff0c;且类型繁多&#xff1a; 办公系统&#xff1a;HR、OA、邮件、考勤等系统核心…

【Linux】通过内核以太层可查看应用程序运行时访问外网情况

比如&#xff0c;SourceInsight3.exe从外网接收信息&#xff1a; 下边是运行firefox时内核打印的日志&#xff0c;可以看到浏览器运行时调用了很多的操作系统内核系统调用&#xff0c;比如&#xff1a;文件读写、网络数据包的收发等等&#xff0c;其实这些日志还并不全&#x…

Qt-QListWidget多元素控件(36)

目录 多元素控件介绍 xxWidget和xxView的区别 描述 属性 方法 增加 删除 信号 使用 图形化界面操作 代码操作 多元素控件介绍 首先我们要先了解一下多元素控件是什么意思&#xff0c;一般而言是以以下这六个控件来进行区别的 xxWidget和xxView的区别 举个例子 描述…

寻找情感MV视频素材:热门素材网站推荐

在MV创作中&#xff0c;情感表达至关重要&#xff0c;唯美而深情的画面能迅速引发观众的共鸣&#xff0c;从而增强作品的感染力。不论你是制作爱情、失恋、亲情还是友情主题的MV&#xff0c;找到合适的情感视频素材都是成功的关键。如果你想为作品增添温暖和深情的氛围&#xf…

PowerPoint技巧:将幻灯片里的图片背景设置为透明

在PPT中添加了图片&#xff0c;想要将图片中的背景设置为透明或者想要抠图&#xff0c;有什么方法吗&#xff1f;今天分享两个方法。 方法一&#xff1a; 添加图片&#xff0c;选中图片之后&#xff0c;点击【图片格式】功能&#xff0c;点击最左边的【删除背景】 PPT会自动帮…

如何在 macOS 上恢复未保存的 Excel 文件 – 文件恢复的最佳方法

Microsoft Excel 主要用于学生、员工和组织创建电子表格、报告和许多其他内容。我们是人&#xff0c;我们也容易忘记事情。因此&#xff0c;您想要在 macOS 上恢复未保存的 Excel 文件并不罕见。 虽然在 Excel 上恢复未保存的电子表格很容易&#xff0c;但在 macOS 上就有些棘…

【C++掌中宝】类和对象(一):类的定义和实例化

文章目录 引言1. 什么是类&#xff1f;1.1 类的定义1.1.1 类定义格式1.1.2 访问限定符1.1.3 类域 1.2 类在编程中的作用——抽象与封装 2. 类的基本组成2.1 成员变量&#xff1a;类的属性&#xff08;变量&#xff09;2.2 成员函数&#xff1a;类的行为&#xff08;函数&#x…

ai教我校验“顺序”四则运算expression(re“非捕获组”应用)

与ai学伴聊天对掐&#xff0c;学到了re非捕获组匹配。 (笔记模板由python脚本于2024年09月25日 23:21:14创建&#xff0c;本篇笔记适合初通Python&#xff0c;熟悉六大基本数据(str字符串、int整型、float浮点型、list列表、tuple元组、set集合、dict字典)的coder翻阅) 【学习的…