大多数浏览器和
Developer App 均支持流媒体播放。
-
Safari 浏览器和 WebKit 的新功能
探索 Safari 浏览器和 WebKit 的最新功能,并学习如何制作更完善、功能更强大的网站。我们将带您了解 HTML 的最新更新、CSS 增强功能、Web 检查器工具、以及 Web API,等等。
资源
- Learn more about bug reporting
- MDN Web Docs - Web Extensions API
- Safari Release Notes
- Safari Technology Preview
- WebKit Open Source Project
相关视频
WWDC23
WWDC22
-
下载
♪ 柔和乐器演奏的嘻哈音乐 ♪ ♪ 您好!我是 Kendall Bagley Safari 浏览器 团队的软件工程师 自从上次我们 在 WWDC 相遇已经过去一年了 今天 我们会来聊聊 Safari 浏览器 和 WebKit 上的所有绝妙的 新功能和改进 包括今年 WWDC 的最新更新 以及过去一整年间的积累 说实话 这一年可真够忙的! 从去年秋天起 每次 Safari 的版本更新 都带来了各位网页开发者一直想要的 令人激动的全新功能 一年来 我们做出的所有改进 都是在响应开发者分享给我们的 反馈中的重点 比如用 :has() 伪类添加了父选择器 新的 flexbox inspector 还有容器查询功能 我们想要在优化和简化 您的日常工作的同时 构建出最强大的 Web 开发软件 实际上 画面上的 就是我们今天要介绍的 一部分新内容 但我们不可能在短短的一个讲座里 面面俱到的讲清楚一切 过去一年间 Safari 浏览器 经历了七次版本更新 带来了总计 162 个 新网页平台功能 我们很荣幸能为您提供那么多新工具 来帮助您建设网站和网页 App 对 macOS 来说 尽快查看更新内容的最佳方法 就是使用 Safari Technology Preview 在那里 您可以试用最新最棒的 Safari 和 WebKit 功能 并帮助我们了解还需改进之处 但如您所见 新功能可真是有一大堆 让我们来看看 接下来要讲解的内容吧 今天我们要了解一下 新的 HTML 功能 CSS 改进 有一大堆改进 帮您改善代码架构 新的 Web Inspector 工具 多种新 web API 出色的 JavaScript 和 WebAssembly 功能 以及安全和隐私方面的改进 首先 让我们来看看 HTML 有哪些更新 我创建了一个网页供我和同事使用 让我们拿它当作示例 我这个人比较节俭 喜欢再利用衣服 好让我的衣橱更加持久 所以我觉得一个衣物交换网站 应该是一个好主意 可以让我们的团队也参与进来 我设计的网站有一个请求物品按键 能让您在发现一件中意的衣服时 展示一个供您填写的表单 我想在整个 网页的上方 一个覆盖层上 展示这个表单 新的对话框元素 提供了一个非常简单的方法 可以稳定而方便的创建覆盖层 好创建我们的申请表 CSS 中新的背景伪元素 让我们可以设置模态后面 背景的样式 让我们请求一个物品 调出对话框 看到这阴影和动画了吗? 看起来真棒! 有人在网站上申请了物品之后 发布它的人 要能够接受这个请求 在页面底部 有一个轮播 可以让您翻阅所有收到的请求 但我不希望有人因为 鼠标或键盘的误点按 与这些不是在最前面的 按钮或文本框互动 我可以使用 inert 属性来解决这个问题 在 JavaScript 的这里 动态应用 inert 属性 我就可以在用户切换轮播时 禁用与非当前轮播卡片上 元素的互动 Inert 还能关闭 辅助技术的互动 防止屏幕阅读器 读出那些禁用的项目 这能更清晰的引导系统 知道应该与哪些元素交互 最后 对 HTML 来说 还有新的图像延迟加载功能 在我的网站上 那些头部的图标 需要立刻加载 但那些初次加载时 处在屏幕外的衣物图片 可以对它们使用延迟加载 这样 只有在用户 滚动到它们时 图片才会加载 这会使网页的 加载和响应看起来都变得更快 我很喜欢这个网站现在的样子 对于那些使用 辅助技术的人来说 它也会十分好用 这些 HTML 特性只是一个开始 因为今年 CSS 也有许多 值得关注之处 我们对 CSS 的关注重点 主要是通过更强大的架构 让您可以 更轻松的复用您的 CSS 鉴于此 我们知道 对于新 web 技术 开发者的头号需求就是容器查询 我们很高兴地宣布 容器查询会在 Safari 16 中实装! 您将可以同时使用尺寸查询 和容器查询单元 在这里 我在尝试为这个衣物交换网站 设计另一种布局 我要把这个代表一件衣服的卡片 变成一个可复用的组件 并把这个组件 放到页面布局的几个不同位置 在侧边栏中 这里的空间有点狭窄 所以我希望组件中的内容 垂直堆叠 在物品的主网格中 我想把第一个变成主页横幅 让它占满所有横向空间 并把其中的内容调整成适合 宽布局的样式 主内容区域中的其他物品 应被分成较小的列 所以我又创建了一种布局 适用于中等横向空间的情况 用容器查询 而不是媒体查询的方式 处理这种布局的变化 我只需为这个组件写一次布局代码 就可以在网站的任何地方 任何大小的容器中 使用这个组件 且始终会应用正确的布局 我指定了容器应该使用哪些元素 以及它应该只衡量行内大小 还是要同时衡量行内和块级大小 这是通过 container-type 属性实现的 为容器命名是一个可选项 用 container-name 属性即可 它能让我更加灵活的构建 HTML 然后我使用 @container 规则 基于容器的尺寸 规定了应用样式的条件 这里 如果一个衣物卡片组件 处于一个宽度超过 250 像素的组件中 网格就会有两列 而不是一列 CSS 架构的另一个更新:级联层 这是 CSS 级联的一个重大升级 自 CSS 诞生之日起 级联就一直是由这些不同的层组成的 但无论各层中给定选择器的 优先级如何 作者样式 也就是您作为 web 开发者所写的样式 总是会覆盖浏览器默认样式 而行内样式则总是高于作者样式 以此类推 剩下的层级也如此 级联层采用了这种概念 还允许您创建自己的自定义层 每层中的优先级都是独立计算得出的 一整层的优先级会高于另一整层 无论使用中的选择器优先级如何 而哪些层高于哪些层是由您 通过在 CSS 中 定义层顺序决定的 在为大型项目构建 CSS 以及长期维护其代码时 级联层会成为一种好用的工具 也许您的团队会用它 防止一个设计系统被覆盖 或者把它与您为项目中的 自定义样式使用的框架分开 一切都取决于您! 对您的 CSS 架构来说 所有这些精彩的 新改进之上的 画龙点睛一笔就是 :has() 这是一个伪类 用作大家期待已久的父选择器 它还有许多其他功能 与 CSS 中的 任何其他选择器结合 :has() 可以用于 寻找兄弟元素 属性 表单文本框状态等等 它真的很强大 在这里 我想在 每当有人为一条消息 选中了“Urgent?”(紧急?) 复选框时 就高亮显示整个消息框 我可以用 :has 伪类来规定 只要表单元素有一个复选框被选中的 复选框类型输入 就应用这个 CSS 我甚至都不需要 用 JavaScript 我们希望这些为处理 CSS 架构所进行的改进 包括 :has() 级联层 以及容器查询 能大大改善 您作为一名 web 开发者的 工作效率 但让我们如此兴奋的 CSS 改进 可不止这些 开发者一直想要一个 类似现有的视口单元的工具 但要更好的适配那些在滚动时 视口尺寸会变化的设备 为此我们给大家 带来了新的视口单元 如果您想知道视口在最小状态时 它的高度 用 svh 即可 要是想知道视口 在最大状态时的高度 请用 lvh 只要记住:s 代表小 l 代表大 对于那些始终匹配视口 当前实际高度的动态数字 用 dvh 即可 不只是高度 我们还为您准备了更多视口单元 有宽度单元 与常用的高度单元配合 可以改善完整性 还有块和行内元素 它们在多语言情况下 不同语言的文本 溢出情况不同时 会很有用 当然我们也没忘了最小和最大值 但要是您想在网页上创造一些运动 而不只是做出被动反应呢? 以前 动画一直都是高度声明性的 您要指定一个 开始 结束 和持续时间 让物体动起来 但让网页元素动起来 一直都是一个挑战 无论是在您试图 让它沿着弧形轨迹移动时 还是只是让它根据一个偏移量移动 而我想在您点按头部横幅时 添加一个秘密动画效果 因为这样会很有趣 有了新的 offset-path 您可以定义对象运动的轨迹 用 offset-path 来设置运动轨迹 用 offset-distance 来设置关键帧效果 然后用 animation 属性 来应用关键帧效果 这样您就可以全权控制 CSS 中的动画 我们还想把更多的网页控制权交给您 即使是那些通常都是被 浏览器引擎定义的那一部分 而 over scroll-behavior 就是这类实践的第一个例子 自网络诞生以来 如果您点按了一个 把您转至网页某处的链接 它会在视觉上表现为一次跳跃 有时候这会使用户迷失方向 CSS 中的 scroll-behavior 属性 允许您指定是否想要这种行为 它的默认值是自动 也就是显示为那种跳跃 如果把 scroll-behavior 指定为平滑 浏览器就会平滑的滚动到 页面上的指定位置 您还可以用 JavaScript 方法来实现这个效果 用 Window.scroll() scrollTo() 或 scrollBy() 即可 最了解您的客户的人就是您自己 您应该能定义自己的网页体验 而不必拘束于浏览器引擎默认值 在这方面 :focus-visible 和 accent-color 同样可以大放异彩 如果您曾经想要对焦点选择器 应用某种样式 以使其更符合 您的整体设计 那您可能已经很熟悉焦点选择器了 但这么做可能会导致 损失一些 基于浏览器的无障碍辅助功能 而在我的网站上 我喜欢用自定义表单颜色 而不是内置的颜色 让我们把头部横幅的蓝绿色 用在这里的焦点高亮和复选框上吧 用 :focus-visible 伪类 您可以自定义焦点选择器的样式 同时使其只在浏览器原生支持时 才显示出来 而且 要为您的表单增加另一层自定义 您还可以用 accent-color 来改变 表单控件 UI 不同部分的颜色 它可以用来调整复选框 以及单选按钮 等等 另外 对于 CSS 我们一直在越来越多的 替换掉 WebKit 前缀 它们曾经是进行 特性实验的完美方法 但现在 我们可以逐步接近 它们的标准定义属性了 这样可以使您的 CSS 更易于编写 提高互操作性 但别担心 您已有的带有 WebKit 前缀的 CSS 将在您把它们过渡至 相应的 web 标准期间正常工作 Backface-visibility print-color-adjust 以及 text-align: match-parent 都与它们的对应前缀版本 完全相同 Mask 和 text-combine-upright 都从前缀版本更新了语法 以符合标准 而且不带前缀的 appearance 属性还增加了 对新的 auto 值的支持 但 Safari 16 中移除了 WebKit 特定的值 比如 caret 和 listitem 以符合标准规范 我们新增的排版选项 也颇值得关注 特别是 font-palette 属性的加入 使为彩色字体选择调色板 变得更加简单 尝试为我的网站添加 logo 想必会很酷 我们可以用内置的深色 或浅色调色板来试试看怎么样 甚至还可以用色彩覆盖 自定义加入一点明亮的黄色 使其完全符合我想要的样子 在排版方面 还增加了 text-decoration-skip-ink 它允许您控制 一条下划线或上划线 与字母或字符相交时会发生什么 还有 ic 单元 可以让您在块方向 精确排列 CJK 字符 对于中文 日文和韩文等语言 它可以助您创建一个整洁的排版网格 最后在这些 优秀的 CSS 特性中 我们当然还得说说 subgrid 多年来 网页布局一直都是一个难题 CSS Grid 是革命性的功能 但它只对网格容器的直接子级有用 在这里我使用了 CSS Grid 来布局这些卡片 使其根据视口宽度 通过增加或移除列来调整布局 这里没有进行任何媒体查询 但每张卡片的内容的尺寸都是不同的 有些标题会更长 照片的宽高比也不同 这使一切看起来很乱 我想要让页面上所有的 请求物品按键和消息框都对齐 我想要在出现标题很长的卡片时 其他卡片能随其调整 使它们维持相同的间距 现在 我们可以用 subgrid 来实现此功能 我在每张卡片上都放了一个网格 并把这些网格 都绑定到了它们的父网格 只需写入 “grid-template-rows: subgrid”即可 您可以在 Web Inspector 的 Grid Inspector 中看到 所有衣物卡片的内容都完美对齐了 在这里我还可以 启用所有我需要的网格 使用 Web Inspector 能让许多 CSS 作业都变得轻松 事实上 Web Inspector 获得了许多 很棒的新功能 我觉得您一定会跃跃欲试的 首先 布局变的更容易写了 因为您可以实时看到它们的情况 这正是 Web Inspector 如此重要的原因 另外 有了新的 Flexbox Inspector 您可以直接看到各元素之间的间距 在我的网站上 我在为头部横幅添加图标时 遇到了一些麻烦 我只需点按检查元素 选择布局选项卡 因为我现在要看的不是网格 我可以折叠这一部分 直接进入新的 Flexbox Inspector 甚至只需点按一下 我就能打开所有的视图 而且并不影响流畅性 打开所有视图后 我可以清楚的看到那些井号 和容器框标识着 这些元素是如何排列的的 以及空白空间为什么占据了视图 现在我可以使用新的对齐编辑器 来好好对齐这些内容了 转到样式选项卡 找到 align-items 旁的一个新按钮 在这里 我可以切换不同的选项 来找到哪种样式最适合我的头部横幅 justify-content 也可以应用同样的方法 同样的 只需在不同选项间切换 找到适合您的那一款 我还觉得这些黄色图标有点太小了 我想让它们变得与红色图标一样大 这些红色图标应该在名称中 使用了“medium”这个变量 但我实在想不起来它们的全名了 我可以检查这些黄色图标 在 inspector 中更改它们的高度 这样就可以调整它们的尺寸 而且 有了新的 CSS 模糊自动补全功能 我可以直接输入“medium” 我想要的变量就直接出现了 尽管“medium” 是在其名称的末尾 这样一来那些黄色图标 终于不会显得太小了 而且 对于我要检查的元素中 不需要的各图标中的其他变量 新的 CSS 工具 会将它们隐藏起来 但别担心 如果您需要 也有一个按键 可以显示它们 接下来的这个 可能是今年 Web Inspector 最为激动人心的更新 我们很高兴的宣布 Safari Web Inspector 支持开发者工具扩展了 创作了您最喜欢的 开发者工具扩展的人 现在可以把它们 移植到 Safari 浏览器上了 可以使用它们在其他浏览器中 使用的相同底层 API 来完成移植 如果您想学习如何为 Web Inspector 开发扩展 探索新 API 并开始自己 设置与使用它们 请务必查看 今年 WWDC 的“创建 Safari Web Inspector 扩展”讲座 现在我们已经了解了相当多的 我们的前端技术 是时候换个方向 了解一下我们的 web API 有什么新内容了 我们很高兴的宣布 对 web push 的支持 该功能会在 Safari 16 和 macOS Ventura 中更新 它将在明年登陆 iOS 和 iPadOS Web push 让您可以从 网站或 web App 向用户 远程发送通知 这是一个完全可互操作的 基于标准的功能 如果您已经在其他浏览器中 部署实现了 web push 那您应该无需任何修改 就可使其在 Safari 浏览器上工作 而且您也不需要 Apple Developer 账户 要了解所有详情 请查看 WWDC 22 的“了解 Safari 浏览器的 Web Push”讲座 如果您为 web push 感到兴奋 那想必新的 web App 清单改进 也会令您兴奋 现在 您可以在 manifest 文件中 自定义用户保存在主屏幕上的图标 要优先显示清单中的图标 您要确保在 HTML head 中 没有定义 apple-touch-icon 如果您想在 iOS 和 iPadOS 中显示一种图标 而在其他移动平台上显示另一种 您仍然可以使用 HTML head 中的 apple-touch-icon 来定义 Apple 设备的图标 如果您没有在这两个地方设置图标 用户把您的网站保存到主屏幕时 就只会看到您的网站的屏幕截图 激动人心的是 我们在 载入 manifest 文件时 不再等待用户在共享菜单中选择 “添加到主屏幕”了 也就是说 您可以 在您的整个网站上 用 manifest 文件来定义网页特征 进一步降低 使用 meta 标签的需求 此外 我们的 API 还改进了 相同来源情况下 多种浏览上下文的 网页使用情况 广播频道允许您在那些 不同浏览上下文间发送通知 假设有人正在使用这个衣物交换网站 并同时在两个窗口中打开了它 然后用户 在其中一个窗口请求了一件衣服 我们能够发布一条消息 在其他打开的 选项卡或窗口中同步这个不可用状态 但也许您不只需要更新后台选项卡 还需要更新网站保存的文件 为此 我们还更新了 文件系统访问 API 我们在这一年间的几个版本中 对这个 API 进行了增量更新 从访问域私有文件系统开始 它是基于访问域的私有存储 比如 我的衣物交换网站上的文件 不会被其他网站 比如 apple.com 读取 然后我们给 API 添加了 FileSystemFileHandle 的 getFile() 方法 它会从您的网站的 根目录读取检索得出的已存在的文件 就像我们对这个 我们刚刚创建的草稿文件所做的一样 现在让我们看看我们今年 最有活力的 API 新内容 色彩 Display P3 色域使我们可以 呈现 RGB 色域中不存在的颜色 这是色彩选择器的一些示例 弯曲的白线的左侧 是 RGB 色域中存在的颜色 而线的右侧则 是只在 P3 色域中才有的颜色 2016 年 我们为 视频和照片添加了 P3 色域支持 去年 我们很高兴成为了第一个 实装了 CSS Color Level 4 定义的新色值语法的浏览器 今年 我们为画布元素内的内容 添加了 P3 色域的支持 我们终于不必再受限于 90 年代设备的色域了 您可以开始利用 今天的优秀设备所支持的全部 色彩再现能力 过去一年间 我们的 Web API 的新功能 甚至还不止这些 包括 shadow realms web locks 以及更新了对 ResizeObserver API 的支持 用于 ResizeObserverSize 界面 它能助您监控 元素的 box-sizing 属性变化 在我们 API 更新中 有太多值得一试的部分 当然了 那些新功能也是 事实上 我们还有更多内容 接下来 让我们来看看 JavaScript 和 WebAssembly 的新特性 如果您的网站使用 worker 而您想让这些 worker 的 实例在选项卡和窗口间共享 那么新的共享 worker 界面 一定会有所帮助 它还可能减少内存使用量 不需要为每项您希望发生在后台的 任务产生新的 worker 每个同访问域的浏览上下文 只需要一个 worker 每个脚本都会用同样方式 创建一个共享 worker 然后它们就可以用相同的端口 来接收和发送消息 共享 worker 将可以 接收和回复来自所有 不同脚本的消息 这会降低您的服务器的载荷 同时使客户的 网页浏览体验顺滑快速 我们还有一系列的 数组功能要展示给您 当您想要从末尾搜索时 不必使用 reverse() 来改变数组 现在您只需要使用 findLast() 和 findLastIndex() 方法 就像我现在这样 查询最后一个项目 包含“鞋带”的项目和索引 新的 at() 方法还能使 从末尾搜索数组更加简单 当索引为正时 使用大括号效果很好 但 at() 给了我们额外的功能 可以用负值索引 使您的代码更简洁易读 但即使有这么多的新数组功能 也没有什么能比得上 我们新增的国际化功能的数量 在过去一年间 WebKit 持续不断的 得到了我们的 Intl 功能方面的更新 我们增加了支持不同数字系统的 新方法:NumberFormat 更新了 Locale 和 DisplayNames 以支持更多日历 还有通过 Intl Enumeration API 支持了更多货币种类 正如我所说 这一年来我们 新增了许多 Intl 功能 可供您尝试和探索 以满足您的 世界各地用户的功能 绝不会少对于那些已经有 各种不同编程语言的项目 比如 C Objective C 或 Swift 要把它们带到 web 上来 只需使用 WebAssembly 无需重写 即可运行 有了今年的这些改进 您的使用 WebAssembly 的 web App 只会变得更强大 其可寻址内存扩展到了 4GB 新的零成本异常处理 也会进一步提升性能 总的来说 JavaScript 和 WebAssembly 毫无疑问都得到了一些 激动人心的特性供您尝试 说到 WebAssembly 我们还有一些安全 和隐私增强 它们不仅 保护我们开发的网页所面向的用户 还会为您 作为开发者带来许多新的潜能 有了新的 Cross Origin Opener Policy 和 Cross Origin Embedder Policy HTTP 响应标头 您的网站可以选择加入进程隔离 使您的网站运行在 它自己的专用 webContent 进程中 我们知道 使用 WebAssembly 多线程 许多 App 可以受益于 在多个线程上平行运行 有了这些新的标头 您可以安全的使用这一功能 我们的第二个安全性增强 同样涉及 HTTP 标头 我们支持了 内容安全策略 level 3 CSP 增强了对您的加载内容的 安全控制 还降低了 跨站点脚本以及其他漏洞的风险 Level 3 更新 带来的最令人激动的新功能 就是新的 strict-dynamic 源表达式 Strict-dynamic 的设计者 意识到您可以用随机数 来允许某些脚本 然后把这种信任 扩展到已受信任脚本加载的脚本中 而不再需要明确的允许列表 看看这能让标头变的多简洁 原来的那种一长串域名的形式 可能会导致允许值过多 这就是我们的安全和隐私特性更新 今天我们的讲座 也就到此为止了 但还有许多东西 等待您自己去探索 比如 我们还带来了一些媒体更新 包括使用 getUserDisplay() API 支持截屏特定 Safari 窗口 WebRTC 完美协商 带内章节轨道 和 requestVideoFrameCallback() 以及许多 web 扩展的酷炫新特性 支持了 manifest version 3 以及一堆新的 web 扩展 API 要更深入了解今天介绍的这些特性 探索 Safari 和 WebKit 在过去一年间的 所有 162 项特性和改进 请务必下载 Safari Technology Preview 来跟上未来的更新 为探索 web 技术 请查看我们的版本更新日志 博客文章以及 webkit.org 上所有的精彩内容 包括关于 Web Inspector 的详细文档 和往常一样 通过提交错误报告 告诉我们您的想法 和您接下来想要的东西 如果您在 WebKit 中遇到了错误 无论是 HTML CSS JavaScript DOM API 还是 Web Inspector 都请务必提交您的反馈 使用 bugs.webkit.org 上的 WebKit 的错误跟踪系统即可 有关 Safari 浏览器界面 的建议或错误报告 请通过 Apple 反馈助理提交问题 在接下来的一年 我们期待着 带来更多优秀的特性 持续更新 Safari 浏览器 和 Safari Technology Preview 来改善 web 开发者的工作效率 感谢参加我的讲座 祝您在 WWDC 过的愉快 再见! ♪
-
-
2:59 - Dialog element
<!-- <dialog> element --> <dialog method="dialog"> <form id="dialogForm"> <label for="givenName">Given name:</label> <input class="focus" type="text" name="givenName"> <label for="familyName">Family name:</label> <input class="focus" type="text" name="familyName"> <label> <input type="checkbox"> Can trade in person </label> <button>Send</button> </form> </dialog>
-
3:09 - Backdrop pseudo-class
/* ::backdrop pseudo-element */ dialog::backdrop { background: linear-gradient(rgba(233, 182, 76, 0.7), rgba(103, 12, 0, 0.6)); animation: fade-in 0.5s; } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
-
3:53 - inert attribute
// inert attribute function switchToIndex(index) { this.items.forEach(item => item.inert = true); this.items[index].inert = false; this.currentIndex = index; }
-
4:22 - Lazy image loading
<img src="images/shirt.jpg" loading="lazy" alt="a brown polo shirt" width="500" height="600">
-
6:46 - Container Queries
/* Container queries */ .container { container-type: inline-size; container-name: clothing-card; } .content { display: grid; grid-template-rows: 1fr; gap: 1rem; } @container clothing-card (width > 250px) { .content { grid-template-columns: 1fr 1fr; } /* additional layout code */ }
-
8:05 - Cascade layers
/* Author Styles - Layer A */ @layer utilities { div { background-color: red; } } /* Author Styles - Layer B */ @layer customizations { div { background-color: teal; } } /* Author Styles - Layer C */ @layer userDefaults { div { background-color: yellow; } }
-
8:54 - :has() pseudo-class
<!-- :has() pseudo-class --> <style> form:has(input[type="checkbox"]:checked) { background: #ff927a; } </style> <form class="message"> <textarea rows="5" cols="60" name="text" placeholder="Enter text"></textarea> <div class="checkbox"> <input type="checkbox" value="urgent"> <label>Urgent?</label> </div> <button>Send Message</button> </form>
-
11:08 - Offset Path
/* offset-path */ :is(.blue, .teal, .yellow, .red) { offset-path: circle(9vw at 5vw 50%); } @keyframes move { 100% { offset-distance: 100%; } } /* Animation */ .clothing-header.clicked :is(.blue, .teal, .red, .yellow) { animation: move 1100ms ease-in-out; }
-
11:43 - scroll-behavior: auto
html { scroll-behavior: auto; }
-
12:09 - scroll-behavior: smooth
html { scroll-behavior: smooth; }
-
13:10 - :focus-visible & accent-color
/* :focus-visible & accent-color */ :focus-visible { outline: 4px solid var(--green); box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3); } :root { accent-color: var(--green); }
-
14:50 - Font palette dark mode & light mode
/* Dark mode */ font-palette: dark; /* Light mode */ font-palette: light;
-
15:01 - Font palette custom colors
/* Dark mode */ font-palette: dark; /* Light mode */ font-palette: light; /* Custom colors */ @font-palette-values --MyPalette { override-colors: 1 yellow; } #logo { font-palette: --MyPalette; }
-
15:55 - CSS Grid
/* Grid to layout cards */ main { display: grid; grid-template-columns: repeat(auto-fit, minmax(225px, 1fr)); gap: 1rem; } /* Grid to layout each card’s content */ article { display: grid; grid-row: span 5; }
-
16:35 - Adding sub grid
/* Grid to layout cards */ main { display: grid; grid-template-columns: repeat(auto-fit, minmax(225px, 1fr)); gap: 1rem; } /* Grid to layout each card’s content */ article { display: grid; grid-row: span 5; /* Adding subgrid, tying them together */ grid-template-rows: subgrid; }
-
21:15 - Web App Manifest file icons
// Manifest file "icons": [ { "src": "orange-icon.png", "sizes": "120x120", "type": "image/png" } ]
-
21:29 - apple-touch-icon
<!-- HTML head --> <link rel="apple-touch-icon" href="blue-icon.png" />
-
22:36 - Broadcast Channel
// State change broadcastChannel.postMessage("Item is unavailable");
-
23:14 - Origin private file system
// Accessing the origin private file system const root = await navigator.storage.getDirectory(); // Create a file named Draft.txt under root directory const draftHandle = await root.getFileHandle("Draft.txt", { "create": true }); // Access and read an existing file const existingHandle = await root.getFileHandle("Draft.txt"); const existingFile = await existingHandle.getFile();
-
25:32 - Shared Worker
// Create Shared Worker let worker = new SharedWorker("SharedWorker.js"); // Listen for messages from Shared Worker worker.port.addEventListener("message", function(event) { console.log("Message received from worker: " + event); }); // Send messages to Shared Worker worker.port.postMessage("Send message to worker");
-
25:56 - findLast() and findLastIndex()
const list = ["shirt","pants","shoes","hat","shoestring","dress"]; const hasShoeString = (string) => string.includes("shoe"); console.log(list.findLast(hasAppString)); // shoestring console.log(list.findLastIndex(hasAppString)); // 4
-
26:17 - at()
const list = ["shirt","pants","shoes","hat","shoestring","dress"]; // Instead of this: console.log(list[list.length - 2]); // It's as easy as: console.log(list.at(-2));
-
29:12 - strict-dynamic source expression
// strict-dynamic source expression // Without strict-dynamic Content-Security-Policy: script-src desired-script.com dependent-script-1.com dependent-script-2.com dependent-script-3.com; default-src "self"; // With strict-dynamic Content-Security-Policy: default-src "self"; script-src "nonce-desired" "strict-dynamic";
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。