技术
·
15 min read
·
- Views
创造 CANDY 主题,只为更好的交互
基于 ICARUS 主题重新思考并设计个人博客。
Copied
技术
·
15 min read
·
- Views
创造 CANDY 主题,只为更好的交互
基于 ICARUS 主题重新思考并设计个人博客。
Copied
This post was updated 505 days ago and some of the ideas may be out of date
众所周知,Icarus 是一个非常优秀的 Hexo 主题。它不仅提供清爽、简洁的界面,还与各种主流插件、组件兼容的很好。更令人欣喜的是——它几乎是最活跃的 Hexo 主题之一,有着非常良好的社区氛围。作者时刻保持更新,并提供了非常完善的文档。
种种因素使我最终选择了它,并准备在其基础上修改出自己满意的设计,我将其命名为 Candy,并将在 GitHub 上与 Icarus 保持更新。本文将是这一系列文章的第一节——基础设计修改。
本人前端零基础,如有不妥,请在 评论区 教我做事,谢谢🙏
Icarus 主题很美观,但对我来说它与许多 Hexo 主题一样都存在一个核心问题,即首页的文章如需访问全文,需要点击 Read More 按钮、图片或标题才可以进入,而点击主文字或卡片空白处是没有反应的,恰好很多博主喜欢把摘要写成长篇大论,此时的 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.
貌似如果想这样操作的话,子元素不能再有其他 <a> 元素。我便以为是不可以的,当时就作罢了。
接下来,我尝试在外面先套一层 <object> 标签,再套 <a> 标签链接到正文,这样我们就实现了整张卡片可点击的效果。
这样确实可以了,本来这一段到这里就结束了,但我想起了 文档 里对 <object> 标签的描述:
HTML <object> 元素(或者称作 HTML 嵌入对象元素)表示引入一个外部资源,这个资源可能是一张图片,一个嵌入的浏览上下文,亦或是一个插件所使用的资源。
于是乎,就换来了接下来的方法,也是最终的实现方法。
这种方法的思路其实和第一种是一致的,但是具体实现有区别,这次我们不在 article.jsx 里修改了,直接在 source/js/main.js 最底下添加:
其实就是用了 jQuery 的 warp() 方法,这里我们指定 <a> 元素来包裹 <article> 元素。同时因为我们只需要在首页让这些卡片有链接,所以我们可以通过判断正文末尾的版权信息盒子是否存在,来控制这条语句是否生效。
我们还需要设置一下 card-link 的 color 为 inherit,这样摘要的颜色就会恢复成白色,否则会是你 a 标签的颜色(自定义 CSS 的方法在后文):
这样我们就实现了整个卡片可点击,且卡片里原有的分类链接照样可以点击并不受影响。但我并不知道为何第一种和第三种方法会有这样的差异,如果有大佬清楚请在评论区解答我,谢谢。
所谓「交互」,代表着交流和互动。一个好的交互设计,组件与用户的互动是必不可少的。互联网厂商们早已发现了这一逻辑,并将这些互动悄悄藏在设计里,通过微小的震动、令人愉悦的变换俘获用户的感官。
简单来说,光将整张卡片链接到正文还不够,它得是让用户有感知的,这个感知就由动效来实现。
废话少说,先上效果图👇:
为实现这个效果,我增加了:
我希望能用纯 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 Draft 和 CSS4 Selectors,另附 Can I use 兼容情况。
最后我们添加题图放大的动效,这里的效果模仿自 Apple 官网的 Newsroom 📰,注意 :hover 的写法,我希望鼠标放在卡片上时就激活(而不仅仅是放在题图上):
细心的朋友可能会发现,光这样还不完美——图片在变换的过程中会先取消圆角,再恢复圆角,也就是说中间会有一段时间「四角方方」,这是我们不愿意看到的,解决方法也很简单,再添加一个 0 度的旋转[^6]即可:
在黑暗模式下我还加入了题图变暗的效果。关于黑暗模式我会在之后详解,就不在本文中赘述了:
至此,我们便完成了一个用户友好的卡片设计,它整张卡片可点击,且有合适的动效互动,但这并不是 Candy 主题的全部,还有很多细节性的动效就不在这里赘述了,感兴趣的话可以去查看 style.styl 源码。
最后,我想我需要一个会跟随页面的导航栏,它得是贴心的——当你需要它的时候,比如回首页、切换浅色/深色模式、搜索,它就在那里;它还得是不恼人的——它不应该遮挡太多,影响到正文或视觉平衡,它得是灵巧的,且更好的适配响应式设计。
导航栏不会真的跟着走的,我们只是给它添加一个 position 为 fixed 的样式。这么做的同时还需要调整 width 为 100% 并将下一个元素 section 下移:
当然,也可以采用 sticky 不过兼容性会 差一些,在此案例中效果是一样的。使用 sticky 就不需要设置 section 的下移,不过需要设置 top 属性:
接下来我想让导航栏看起来更轻巧一些,于是缩窄了导航栏的高度并加入了所谓「毛玻璃」效果。
通过修改 navbar-item 的内外边距来缩窄高度:
同时 Icarus 原版对于移动端的处理是将 logo 放在一个自适应的 div 里,当屏幕宽度小于 1088 px 的时候,导航栏会分成上下两行。
但这对于一个一直固定在顶端的导航栏来说太大了,所以这里我做了个修改,将自适应去掉,把 logo 也放在 navbar-menu 里:
效果图:
当然,还有些更好的方案,比如制作下拉菜单栏,以解决导航栏里的标签页太多超出屏幕宽度的问题,可以见这个旧版本的 PR。有空的时候我会改进导航栏,如果真的有人看的话。
所谓「毛玻璃」,更专业一点的说法叫「Backdrop Filter effect」,即背景过滤效果。所以核心就是 backdrop-filter 样式。我这里依旧模仿的 Apple Newsroom,将 navbar 背景色变透明并增加饱和度和模糊:
再将 navbar-menu 背景设为透明,这样小尺寸屏幕下也能正常显示:
效果图:
我们固定了导航栏,紧接着问题就来了。你会发现之前的页内锚元素跳转全都错位了(比如目录、脚注),更准确的来说是正好被现在的导航栏所遮挡,所以我们要来修复这个 bug。
先来修复简单的,修复脚注我们只需要用到 CSS(因为新版目录是用 JavaScript 来控制 href 属性值的,这个方法就不行了),这里我们用到一个小技巧,即用 :target 去定位目标元素,并用 ::before 在前面加一个空的行内元素,然后通过 padding-top 和 margin-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 的,一个非常崭新的评论系统,美观、安全、易用、免登录、免费等等,虽然它还有很长的路要走,但目前配得上这些美好的词汇。希望我能在官方作者写出详细教程之前发布(逃)。
本文完。
6 篇文章
17 个话题
- 次访问