技术

·

15 min read

·

- Views

创造 CANDY 主题,只为更好的交互

基于 ICARUS 主题重新思考并设计个人博客。

Copied

创造 CANDY 主题,只为更好的交互

This post is from the old blog, so may not be presented at the best

This post was updated 1214 days ago and some of the ideas may be out of date

众所周知,Icarus 是一个非常优秀的 Hexo 主题。它不仅提供清爽、简洁的界面,还与各种主流插件、组件兼容的很好。更令人欣喜的是——它几乎是最活跃的 Hexo 主题之一,有着非常良好的社区氛围。作者时刻保持更新,并提供了非常完善的文档。

种种因素使我最终选择了它,并准备在其基础上修改出自己满意的设计,我将其命名为 Candy,并将在 GitHub 上与 Icarus 保持更新。本文将是这一系列文章的第一节——基础设计修改。

本人前端零基础,如有不妥,请在 评论区 教我做事,谢谢🙏

真正的卡片式设计——让最频繁的交互更人性化

分析

Icarus 主题很美观,但对我来说它与许多 Hexo 主题一样都存在一个核心问题,即首页的文章如需访问全文,需要点击 Read More 按钮、图片或标题才可以进入,而点击主文字或卡片空白处是没有反应的,恰好很多博主喜欢把摘要写成长篇大论,此时的 Read More 按钮看起来更小,很容易被忽视,点击大段文字也许是很多读者的第一反应,虽然这并不会得到任何回应。

[object Object]
大佬们的博客,长长的「摘要」使 Read More 按钮显得特别小

点击、进入全文,这应该是每个博客最频繁的交互。尴尬的小按钮难免给读者造成一些细微的障碍,当然如果对自己的内容足够自信,或者没那么讲究的话,你就可以跳过这一节了。

尝试

为了达成真正的卡片效果,我探索过一些方法。

我的第一反应是在 <article> 标签外套一层 <a> 标签然后设置 href 属性,同时 <article> 要设置成块级元素。于是我便在 layout/common/article.jsx 中这样修改:

感觉非常合理,但其实并不行,如果这样操作,在实际页面中,<a> 标签并不会正确包裹,反而会被添加到 <article> 元素下每个子元素的首位。我并不确定是什么原因,但是根据 Stack Overflow 上的一篇 回答 中的评论:

You should really point out (by suggesting this way) that: using this solution you cannot have other Anchor elements inside the article.
Roko C. Buljan

貌似如果想这样操作的话,子元素不能再有其他 <a> 元素。我便以为是不可以的,当时就作罢了。

接下来,我尝试在外面先套一层 <object> 标签,再套 <a> 标签链接到正文,这样我们就实现了整张卡片可点击的效果。

这样确实可以了,本来这一段到这里就结束了,但我想起了 文档 里对 <object> 标签的描述:

HTML <object> 元素(或者称作 HTML 嵌入对象元素)表示引入一个外部资源,这个资源可能是一张图片,一个嵌入的浏览上下文,亦或是一个插件所使用的资源。
MDN

于是乎,就换来了接下来的方法,也是最终的实现方法。

解法

这种方法的思路其实和第一种是一致的,但是具体实现有区别,这次我们不在 article.jsx 里修改了,直接在 source/js/main.js 最底下添加:

其实就是用了 jQuery 的 warp() 方法,这里我们指定 <a> 元素来包裹 <article> 元素。同时因为我们只需要在首页让这些卡片有链接,所以我们可以通过判断正文末尾的版权信息盒子是否存在,来控制这条语句是否生效。

我们还需要设置一下 card-linkcolorinherit,这样摘要的颜色就会恢复成白色,否则会是你 a 标签的颜色(自定义 CSS 的方法在后文):

这样我们就实现了整个卡片可点击,且卡片里原有的分类链接照样可以点击并不受影响。但我并不知道为何第一种和第三种方法会有这样的差异,如果有大佬清楚请在评论区解答我,谢谢。

加入一点动效会让体验更好吗?答案是肯定的

所谓「交互」,代表着交流和互动。一个好的交互设计,组件与用户的互动是必不可少的。互联网厂商们早已发现了这一逻辑,并将这些互动悄悄藏在设计里,通过微小的震动、令人愉悦的变换俘获用户的感官。

简单来说,光将整张卡片链接到正文还不够,它得是让用户有感知的,这个感知就由动效来实现。

废话少说,先上效果图👇:

[object Object]
动图可能看不太清楚,可自行在本博客体验效果,深色模式和浅色模式下会有细微的差别

为实现这个效果,我增加了:

  • 向上的位移
  • 阴影的变换
  • 题图的变大(深色模式下,还增加了题图的变暗)

我希望能用纯 CSS 解决的,尽量只用 CSS。为了后期与 Icarus 同步更方便,我们修改 source/css 目录下的 style.styl 来自定义样式。Icarus 使用 Stylus[^3] 作为 CSS 预处理器。它的定义生效规则是:

一个变量不能影响在定义它以前的输出样式。

所以为了方便,我们可以把所有自定义样式放在最前面,把 @import 放在最后。

位移与阴影

首先,我们将位移与阴影一起添加,效果模仿自 Gridsome Blog Starter 🙏。

因为我不希望在正文处也出现动效,同时希望尽可能用纯 CSS 解决,所以我在 article.jsx 最前面添加一个只在正文生效的空的 div 元素,并通过 class 名「controller」来控制:

这样一来,正文的最前面就会多一个空的、class 名为「controller」的 div 元素。接下来我们写伪类:

如果有大佬们有更好的解决方案,请在评论区赐教。

点击展开查看:一个现在不兼容,但未来可能可以的做法。

简单来说就是 :not 里嵌套兄弟选192择器 ~

很好理解,这个选择器会选择兄弟不为 .controller.card,这样只需要这一个语句即可。

关于这一特性的详细可以看 W3C Editor's DraftCSS4 Selectors,另附 Can I use 兼容情况

题图

最后我们添加题图放大的动效,这里的效果模仿自 Apple 官网的 Newsroom 📰,注意 :hover 的写法,我希望鼠标放在卡片上时就激活(而不仅仅是放在题图上):

细心的朋友可能会发现,光这样还不完美——图片在变换的过程中会先取消圆角,再恢复圆角,也就是说中间会有一段时间「四角方方」,这是我们不愿意看到的,解决方法也很简单,再添加一个 0 度的旋转[^6]即可:

在黑暗模式下我还加入了题图变暗的效果。关于黑暗模式我会在之后详解,就不在本文中赘述了:

至此,我们便完成了一个用户友好的卡片设计,它整张卡片可点击,且有合适的动效互动,但这并不是 Candy 主题的全部,还有很多细节性的动效就不在这里赘述了,感兴趣的话可以去查看 style.styl 源码

「跟着走」的导航栏,贴心而不恼人

最后,我想我需要一个会跟随页面的导航栏,它得是贴心的——当你需要它的时候,比如回首页、切换浅色/深色模式、搜索,它就在那里;它还得是不恼人的——它不应该遮挡太多,影响到正文或视觉平衡,它得是灵巧的,且更好的适配响应式设计。

跟着走?No!它只是固定在那里

导航栏不会真的跟着走的,我们只是给它添加一个 positionfixed 的样式。这么做的同时还需要调整 width100% 并将下一个元素 section 下移:

当然,也可以采用 sticky 不过兼容性会 差一些,在此案例中效果是一样的。使用 sticky 就不需要设置 section 的下移,不过需要设置 top 属性:

「瘦身」+「毛玻璃」,让导航栏灵巧一些

接下来我想让导航栏看起来更轻巧一些,于是缩窄了导航栏的高度并加入了所谓「毛玻璃」效果。

「瘦身」

通过修改 navbar-item 的内外边距来缩窄高度:

同时 Icarus 原版对于移动端的处理是将 logo 放在一个自适应的 div 里,当屏幕宽度小于 1088 px 的时候,导航栏会分成上下两行。

但这对于一个一直固定在顶端的导航栏来说太大了,所以这里我做了个修改,将自适应去掉,把 logo 也放在 navbar-menu 里:

效果图:

[object Object]
改动后的导航栏更窄更清爽了(右)

当然,还有些更好的方案,比如制作下拉菜单栏,以解决导航栏里的标签页太多超出屏幕宽度的问题,可以见这个旧版本的 PR。有空的时候我会改进导航栏,如果真的有人看的话。

「毛玻璃」

所谓「毛玻璃」,更专业一点的说法叫「Backdrop Filter effect」,即背景过滤效果。所以核心就是 backdrop-filter 样式。我这里依旧模仿的 Apple Newsroom,将 navbar 背景色变透明并增加饱和度和模糊:

再将 navbar-menu 背景设为透明,这样小尺寸屏幕下也能正常显示:

效果图:

最后,修复锚元素定位

我们固定了导航栏,紧接着问题就来了。你会发现之前的页内锚元素跳转全都错位了(比如目录、脚注),更准确的来说是正好被现在的导航栏所遮挡,所以我们要来修复这个 bug。

脚注修复

先来修复简单的,修复脚注我们只需要用到 CSS(因为新版目录是用 JavaScript 来控制 href 属性值的,这个方法就不行了),这里我们用到一个小技巧,即用 :target 去定位目标元素,并用 ::before 在前面加一个空的行内元素,然后通过 padding-topmargin-top 配合来控制位置这样就修复了正文到脚注的跳转错位:

稍微解释一下,这里就是先用 padding-top 将这个空的 inline-block 移动到距离其容器上方 N px 的位置,然后通过 margin-top 将这个容器整体上移 N px 的位置,这样我们就可以通过调整 N 的值来控制元素的位置。

同理,我们还需要修复下脚注到正文的跳转:

这里有一些细微的差别,因为脚注是一个列表,列表的元素应该按一整条一整条来看,所以我们把 display 改为 block,再按照之前的方法适当调整一下距离,最后我们还需要通过 margin-bottom 来对齐文本和序号。

目录修复

如果你不需要一个「随着滚动到不同位置,动态折叠展开」的目录,你可以使用这个旧版本的 toc.js,并且采用上面修复脚注的方式来修复错位,这里我就不赘述了。

如果你需要这样一个「智能」的目录,请采用最新版本toc.js 并把它放在 source/js 里,这里我只说下对于错位的修复。

首先在 source/js/toc.js 中创建一个 scrollTo 方法来代替不支持偏移量的 scrollIntoView 方法:

没有什么可说的,非常好理解,然后在下面替换即可:

就是这么简单,我们完成了所有错位修复。

写在最后的、其他的一些玩意儿

感谢你看到这里,零基础的我可能比较啰嗦,这当然不是我在视觉和交互上做出的全部修改,尽量挑了些对我来说比较有代表性的「坑」,大佬们见笑了。一些细枝末节的修改,网络上可能已经有无数篇相同的文章教你如何去操作了,我就不费口舌了。当然如果你有任何疑问、评价或想教我做事儿,也请不要吝啬,请在文末的评论区给我留言,我会第一时间回复。

这是 Candy 主题修改系列的第一篇,应该也是最零碎的一篇,我非常迫不及待地想分享关于黑暗模式的实现,但是先忍住,下一篇将会是关于 Twikoo 的,一个非常崭新的评论系统,美观、安全、易用、免登录、免费等等,虽然它还有很长的路要走,但目前配得上这些美好的词汇。希望我能在官方作者写出详细教程之前发布(逃)。

本文完。

脚注

https://github.com/ppoffice/hexo-theme-icarus
  • Stylus 是富于表现力、健壮、功能丰富的 CSS 预处理器,详见官网