0

精读《不再需要 JS 做的 5 件事》

 2 years ago
source link: https://segmentfault.com/a/1190000041717742
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

关注 JS 太久,会养成任何功能都用 JS 实现的习惯,而忘记了 HTML 与 CSS 也具备一定的功能特征。其实有些功能用 JS 实现吃力不讨好,我们要综合使用技术工具,而不是只依赖 JS。

5 things you don't need Javascript for 这篇文章就从 5 个例子出发,告诉我们哪些功能不一定非要用 JS 做。

使用 css 控制 svg 动画

原文绘制了一个放烟花的 例子,本质上是用 css 控制 svg 产生动画效果,核心代码:

.trail {
  stroke-width: 2;
  stroke-dasharray: 1 10 5 10 10 5 30 150;
  animation-name: trail;
  animation-timing-function: ease-out;
}

@keyframes trail {
  from,
  20% {
    stroke-width: 3;
    stroke-dashoffset: 80;
  }
  100%,
  to {
    stroke-width: 0.5;
    stroke-dashoffset: -150;
  }
}

可以看到,主要使用 stroke-dasharray 控制线条实虚线的样式,再利用动画效果对 stroke-dashoffset 产生变化,从而实现对线条起始点进行位移,实现线条 “绘图” 的效果,且该 css 样式对 svg 绘制的路径是生效的。

sidebar

可以完全使用 css 实现 hover 时才出现的侧边栏:

nav {
  position: 'absolute';
  right: 100%;
  transition: 0.2s transform;
}

nav:hover,
nav:focus-within {
  transform: translateX(100%);
}

核心在于 hover 时设置 transform 属性可以让元素偏移,且 translateX(100%) 可以位移当前元素宽度的身位。

另一个有意思的是,如果使用 TABS 按键聚焦到 sidebar 内元素也要让 sidebar 出来,可以直接用 :focus-within 实现。如果需要 hover 后延迟展示可以使用 transition-delay 属性。

sticky position

使用 position: sticky 来黏住一个元素:

.square {
  position: sticky;
  top: 2em;
}

这样该元素会始终展示在其父容器内,但一旦其出现在视窗时,当 top 超过 2em 后就会变为 fixed 定位并保持原位。

使用 JS 判断还是挺复杂的,你得设法监听父元素滚动,并且在定位切换时可能产生一些抖动,因为 JS 的执行与 CSS 之间是异步关系。但当我们只用 CSS 描述这个行为时,浏览器就有办法解决转换时的抖动问题。

手风琴菜单

使用 <details> 标签可以实现类似一个简易的折叠手风琴效果:

<details>
  <summary>title</summary>
  <p>1</p>
  <p>2</p>
</details>

<details> 标签内的 <summary> 标签内容总是会展示,且点击后会切换 <details> 内其他元素的显隐藏。虽然这做不了特殊动画效果,但如果只为了做一个普通的展开折叠功能,用 HTML 标签就够了。

虽然直觉上暗色主题好像是一种定制业务逻辑,但其实因为暗色主题太过于普遍,以至于操作系统和浏览器都内置实现了,而 CSS 也实现了对应的方法判断当前系统的主题到底是亮色还是暗色:prefers-color-scheme

所以如果系统要实现暗色系主题,最好可以和操作系统设置保持一致,这样用户体验也会更好:

@media (prefers-color-scheme: light) {
  /** ... */
}
@media (prefers-color-scheme: dark) {
  /** ... */
}
@media (prefers-color-scheme: no-preference) {
  /** ... */
}

如果使用 Checkbox 勾选是否开启暗色主题,也可以仅用 CSS 变量判断,核心代码是:

#checkboxId:checked ~ .container {
  background-color: black;
}

~ 这个符号表示,selector1 ~ selector2 时,为选择器 selector1 之后满足 selector2 条件的兄弟节点设置样式。

除了上面例子外,笔者再追加几个例子。

幻灯片滚动

幻灯片滚动即每次滚动有固定的步长,把子元素完整的展示在可视区域,不可能出现上下或者左右两个子元素各出现一部分的 “割裂” 情况。

该场景除了用浏览器实现幻灯片外,在许多网站首页也被频繁使用,比如将首页切割为 5 个纵向滚动的区块,每个区块展示一个产品特性,此时滚动不再是连续的,而是从一个区块到另一个区块的完整切换。

其实这种效果无需 JS 实现:

html {
  scroll-snap-type: y mandatory;
}
.child {
  scroll-snap-align: start;
}

这样便将页面设置为精准捕捉子元素滚动位置,在滚轮触发、鼠标点击滚动条松手或者键盘上下按键时,scroll-snap-type: y mandatory 可以精准捕捉这一垂直滚动行为,并将子元素完全滚动到可视区域。

颜色选择器

使用 HTML 原生就能实现颜色选择器:

<input type="color" value="#000000">

该选择器的好处是性能、可维护性都非常非常的好,甚至可以捕捉桌面的颜色,不好的地方是无法对拾色器进行定制。

关于 CSS 可以实现哪些原本需要 JS 做的事,有很多很好的文章,比如:

但并不是读了这些文章,我们就要尽量用 CSS 实现所有能做的事,那样也没有必要。CSS 因为是描述性语言,它可以精确控制样式,但却难以精确控制交互过程,对于标准交互行为比如幻灯片滑动、动画可以使用 CSS,对于非标准交互行为,比如自定义位置弹出 Modal、用 svg 绘制完全自定义路径动画尽量还是用 JS。

另外对于交互过程中的状态,如果需要传递给其他元素响应,还是尽量使用 JS 实现。虽然 CSS 伪类可以帮我们实现大部分这种能力,但如果我们要监听状态变化发一个请求什么的,CSS 就无能为力了,或者我们需要非常 trick 的利用 CSS 实现,这也违背了 CSS 技术选型的初衷。

最后,能否在合适的场景选择 CSS 方案,也是技术选型能力的一种,不要忘了 CSS 适用的领域,不要什么功能都用 JS 实现。

讨论地址是:精读《不再需要 JS 做的 5 件事》· Issue #413 · dt-fe/weekly

如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

关注 前端精读微信公众号

<img width=200 src="https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg">

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK