首发于前端微志
前端微周刊(第8期):使用CSS hsl函数和CSS 变量,自动生成暗黑模式

前端微周刊(第8期):使用CSS hsl函数和CSS 变量,自动生成暗黑模式

“前端微周刊”,为前端开发者提供技术相关资讯及文章。
微信关注“前端微志”公众号,及时获取最新周刊。
因公众号规则,文内链接,只能在“查看原文”​页面中打开。

资讯

Tailwind CSS v2.1发布

Tailwind CSS 发布了v2.0之后的第一个含多个特性更新的版本。其中,三月份发布的Just-In-Time引擎已经合并到主包中,可以在tailwind.config.js中通过配置mode: 'jit启用该特性,另外还有CSS filtersmix-blend-modeisolationbox-decoration-break等功能的支持。

这里简单提一下这次比较受关注的新特性Just-In-Time,它到底能带来哪些好处?

受益于这种实时地class分析能力,不管是在development还是production模式下,都可以实现样式的按需打包,保证了开发环境和线上环境的一致。之前,Tailwind只能在生产环境进行这种按需的样式打包,开发环境因计算量较大,体验不太好。

这个能力,还可以支持用户通过类似串行的方式定义样式,如sm:focus:hover:active:font-bold可以实现在鼠标悬停和选中状态下的字体加粗。还支持自定义样式,如bg-[#a0cdae]可以自定义背景颜色。

目前来看,Tailwind已经越来越成熟了,可以考虑在你的项目中实践一下了。

Chrome DevTools架构调整:整合到TypeScript

DevTools 迁移 TypeScript

DevTools在2013年决定使用一个类型检查器,当时选择的是Closure Compiler,之后就经常被问到一个问题:你们有没有考虑迁移到一个新的类型检查器?

迁移到JavaScript modules之后,Closure Compiler已经不能发现一些JavaScript中的异常。

由于TypeScript团队自身也使用DevTools来做用例的测试,所以两者自身的兼容适配上有一定的优势。在对比了一些性能指标之后,决定使用TypeScript

文章

Notion 编辑器原理分析

Notion 表现层与数据层的数据流
所以整个 notion 可以分两层,数据层专门负责存储数据;渲染层负责把数据渲染成界面,接收用户的事件并转化成 op 操作交给数据层执行。

100 underline/overlay animations

underline动画效果

文中提供了百种通过underlineoverlay的动画方式,实现多变的鼠标悬停动效, 建议读后收藏。

这些动画,都是使用CSS中的基本属性,如backgroundtransition等,没有SVGJavaScript,且只有一个HTML标签,只需要定义一个样式class使用即可。

How to Learn Complex Things Quickly: A Guide

这是一篇方法论的表述:如何学习复杂事物?

通常面对复杂事物时,第一反应都会想到很多阻碍和困难,然后就立即劝退了。文中通过循序渐进的方式,讲述如何拆解目标并一步一步地实现目标。大概分为以下几步:

  • 确定目标
  • 阅读完整目录,先不要搞那么细
  • 试着研究深入一点点
  • 不要害怕寻求帮助
  • 总结经验,复盘问题

道理我们都懂,等于没说?戳原文细度以下,你会有些收获的。

Dark mode in 5 minutes, with inverted lightness variables

自动生成的暗黑模式效果对比

要实现网站的暗黑模式,没有一个标准答案,每种方式都有各自的优缺点,除了要考虑老项目的改造成本,还要考虑后期的持续维护成本。所以,我们需要一个规则简单,易维护的方案。

本文介绍了一种通过使用CSS中的hsl函数和CSS 变量相结合,实现自动生成暗黑模式的功能的技术方案。

示例代码:

:root {
    --primary-hs: 250 30%;
}

h1 {
    color: hsl(var(--primary-hs) 30%);
}

article {
    background: hsl(var(--primary-hs) 90%);
}

article h2 {
    background: hsl(var(--primary-hs) 40%);
    color: white;
}

@media (prefers-color-scheme: dark) {
  :root {
    --primary-hs: 320 30%;
  }
}

如果你对hsl函数不熟悉,这里提一下它的关键知识点。它接收三个参数,分别是色相饱和度亮度饱和度亮度好理解,那色相指什么?

色相是一个从0到360范围内的数值,表示颜色从红色到绿色再到蓝色间的渐变色,其中0和360表示红色,120表示绿色,240表示蓝色。

Discovering Observer Web APIs

浏览器环境下,有一些API可以用来监听页面变化,如:

  • MutationObserver(监视DOM树中节点的增删改查变化)
  • ResizeObserver(监听标签HTML元素和SVG标签的边界改变)
  • IntersectionObserver(异步监视目标标签元素与根节点间的交叉状态变化)

文中深入地研究如何使用它们,实现某些需要监视页面变化场景下的功能。

工具、插件

Figma to React

示例:左侧为设计稿,右侧为生成的React代码

Figma to React可以将一个Figma绘制的一页内容,转换为React语法的代码,支持React NativeNext.js框架的代码导出。

Deno standard library

Deno核心团队支持的一个所有Deno项目都可以放心使用的高质量代码集合的标准,这些模块没有额外的依赖,如果你想要创建Deno生态下的项目,可以参考这些模块的代码。

Web Developer Checklist(Chrome插件)

使用该插件分析 https://tinyshare.cn

这是一个开发者工具,针对网站的SEO可用性移动端适配AccessibilityPerformance等指标的检查项进行分析,给出可供开发者参考的数据。

Tagify

Tagify是一个强大的input插件,可以将input中的内容展示成可交互的tag,支持各种自定义配置。

代码片段

使用JS复制内容添加到剪切板

在浏览器中复制内容,很简单,用户只需要选中内容,然后ctrl+c即可完成复制。但是这需要用户主动选中内容,如果你的需求是只能一次点击来完成复制操作,那就需要使用浏览器中的一些API来实现了。

下面介绍两种方法:

方法一:使用`execCommand('copy')

根据MDN的文档,document.execCommand这个API已经不被建议使用了,但它还是可以在textarea标签中正常运行。如果你的页面没有textarea标签,可以创建一个隐藏的textarea,将内容填充到这个标签内,再执行复制的操作。复制操作的示例代码如下:

function copyTextFromTextArea() {
  const area = document.querySelector('#text-area')
  area.select();
  document.execCommand('copy')
}

方法二:Clipboard API

Clipboard API是一个更现代化,且基于Promise实现。实现一个简单的复制操作,示例代码:

function copyTextFromParagraph() {
  const cb = navigator.clipboard;
  const paragraph = document.querySelector('p');
  cb.writeText(paragraph.innerText).then(() => alert('Text copied'));
}

使用IntersectionObserver监听页面元素变化

IntersectionObserver对象用于异步监听页面元素及其根元素交叉状态的方法。我们可以利用这一特性API,实现一个“页面滚动时触发CSS动画”的功能:

const observer = new IntersectionObserver(entries => {
  // 循环所有入口
  entries.forEach(entry => {
    // 如果元素是可见的
    if (entry.isIntersecting) {
      // 添加动画class
      entry.target.classList.add('square-animation')
    }
  })
});
observer.observe(document.querySelector('.square));

在JavaScript中使用媒体查询(Media Query)

通常,我们都是在CSS中使用媒体查询做网页的自适应开发,如对min-widthmax-widthdpr等设备条件进行自定义的样式配置。

其实,我们也可以通过JavaScript实现媒体查询的功能。这里要提到window.matchMedia这个方法,它接收一个媒体查询条件作为参数,并返回一个MediaQueryList对象,MediaQueryList.matches即表示当前文档页面是否符合要查询的媒体查询条件

下面给出一个简单的示例(来自MDN):

var para = document.querySelector('p');
var mql = window.matchMedia('(max-width: 600px)');

function screenTest(e) {
  if (e.matches) {
    /* 该 viewport 宽度小于等于600px */
    para.textContent = 'This is a narrow screen — less than 600px wide.';
    document.body.style.backgroundColor = 'red';
  } else {
    /* 该 viewport 宽度大于600px */
    para.textContent = 'This is a wide screen — more than 600px wide.';
    document.body.style.backgroundColor = 'blue';
  }
}

// 监听 mql 的变化
mql.addEventListener('change', screenTest);
文章首发于微信公众号:前端微志。
想要第一时间收到文章推送,更有前端前瞻性技术分享,请微信搜索关注“前端微志”,
发布于 2021-04-10 00:59