大家好,这里是大家的林语冰。坚持阅读,自律打卡,每天一次,进步一点。
春节期间,我有一个朋友在狂追韩剧《Long time no sex》(好久没做),这部剧主要以无性婚姻和婚内出轨等社会现象作为核心创作背景,混入了若干悬疑、犯罪和伦理情节。《好久没做》虽然没有中年老师出轨未成年中二学生那么科幻,也没有老父亲出轨准儿媳全家当街互殴那么激情,但这部人间真实喜剧精准阐释了"艺术源于生活"的永恒真理,目前豆瓣狂砍 8.5
分,总之就是十分推荐。
春天到了,正是欣赏《好久没做》的最佳时机。虽然但是,语冰在沉浸式观看时,被该剧片头的一个"文本电影"特效惊艳到了!
如你所见,在剧名简写"LTNS"的文本中,插入了视频元素,吸睛的创意营造了炫酷的视差效果。
地球人都知道,一切可诉诸 TS 赋能的 App,终将诉诸 ES6 赋能。于是乎,我决定尝试只使用 Web 技术栈,神还原龙年限定版的"生龙活虎"同款文本电影特效,最终成果如下:
考虑到原生 CSS 近几年日新月异,颇有取代 SCSS/LESS 等预处理器的趋势,以及海外样式的多极化方案,我会伪科普新人友好的 CSS 原味版,也会共享语冰最近正在练习的 UnoCSS 重构版。
本期共享的是:
- 如何诉诸原生 CSS 实现"生龙活虎"的文本电影特效
- 如何诉诸 UnoCSS 重构优化
文本电影特效
首先,我们来设计 HTML 的基本骨架结构:
<main>
作为主区域容器<video>
作为电影资源<h1>
作为文本标题
语义化结构如下:
html
<main>
<video autoplay muted loop>
<source src="/dragon.mp4" type="video/mp4" />
</video>
<h1 class="txt-video">生龙活虎</h1>
</main>
这里 <video>
的三个属性都是布尔属性,用于控制视频播放设置:
autoplay
控制视频自动播放muted
控制音频静音或外放loop
控制视频自动播放
我们需要搞一个高清无码的小视频作为静态资源,举个栗子,多人跨年活动"潮汕舞龙",视频如下:
大家可以按需集成自己喜欢的岛国动作片,比如《好久没做》等。
然后我们开始编写样式,我们定义一个绝对定位的全屏容器,样式如下:
css
main {
/* CSS 变量,方便后面复用 */
--main-h: 100vh;
position: absolute;
height: var(--main-h);
width: 100vw;
}
接着,我们需要让视频保持宽高比填充容器,作为标题的"动态内容",样式如下:
css
main {
/* main 样式如上 */
& video {
/* 原生 CSS 嵌套语法 */
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
object-fit: cover;
}
}
这里的 object-fit
属性用于指定 <video>
的内容填充容器的方式,object-fit: cover;
表示内容保持原来的宽高比填充,效果如下:
最后,我们添加 .txt-video
类来设置 <h1>
的文本,样式如下:
css
main {
/* main 和 video 样式如上 */
.txt-video {
font-size: 20rem;
font-weight: bolder;
text-align: center;
color: black;
background: white;
mix-blend-mode: screen;
}
}
我们尽量将标题字体设置得又粗又大,这样文本中的电影视差才更加明显,大家大胆复制、小心粘贴、按需微调即可。
这里的 mix-blend-mode
属性用于指定元素内容和元素的直系父元素内容和背景的混合模式。这样,我们的特效就初具雏形,但是还有 bug......
如你所见,有一部分视频内容露出来了,没有被完全覆盖。这可以使用 flex
布局或绝对定位等方案来修复,但是经过语冰亲自测评,这里使用行高最具性价比,修复如下:
diff
.txt-video {
font-size: 20rem;
font-weight: bolder;
text-align: center;
+ line-height: var(--main-h);
color: black;
background: white;
mix-blend-mode: screen;
}
这里的 line-height
行高和容器等高,主要有两大作用:
- 可以使标题垂直居中;
- 可以让标题垂直铺满容器,覆盖绝对定位露出来的视频背景。
CSS 原味版最终的完整代码如下:
html
<template>
<main>
<video autoplay muted loop>
<source src="/dragon.mp4" type="video/mp4" />
</video>
<h1 class="txt-video">生龙活虎</h1>
</main>
</template>
<style scoped>
main {
--main-h: 100vh;
position: absolute;
height: var(--main-h);
width: 100vw;
& video {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
object-fit: cover;
}
.txt-video {
font-size: 20rem;
font-weight: bolder;
text-align: center;
line-height: var(--main-h);
color: black;
background: white;
mix-blend-mode: screen;
}
}
</style>
UnoCSS 重构优化
前文提及,语冰最近正好在练习 UnoCSS,UnoCSS 是"Vitest 之父" Antfu 的又一力作,一个即时按需的原子 CSS 引擎。简而言之,我们可以通过 UnoCSS DIY 自己的 CSS 架构,实现和 Tailwind CSS 等人气爆棚的 CSS 方案"图灵等价"的功能。
我们通过一个直观的"对照试验"来搭讪一下 UnoCSS,举个栗子,前文 <main>
的样式如下:
css
/* CSS 原味版 */
main {
--main-h: 100vh;
position: absolute;
height: var(--main-h);
width: 100vw;
}
/* UnoCSS 重构版 */
main {
/* 原生 CSS 变量 + Uno 应用指令 */
--uno:absolute h-100vh w-100vh;
}
如你所见,UnoCSS 一行代码就能搞定,而且机智如你会发现 UnoCSS 有原生 CSS 似曾相识的既视感,顾名思义,一目了然。
这其实类似 Tailwind "原子类"方案,而且基本没有入门成本。但 UnoCSS 不像 Tailwind 那么我行我素,而是无拘无束的 CSS 引擎,这意味着,我们可以按需 DIY 自己的原子类,想怎么写就怎么写。
举个栗子,上述例子中绝对定位的 absolute
,我们觉得还是太长了,那我们可以自定义一个"图灵等价"的 ab
原子类,UnoCSS 默认会提供内置的原子类,但不会限制我们的自定义行为,这对于大型项目的样式架构十分友好。
既然是原子"类",那自然是可以作为"类"来使用,UnoCSS 的原子类可以直接写在 HTML 模板里,代码如下:
html
<main class="absolute h-100vh w-100vh"></main>
如你所见,UnoCSS 不仅给力,而且十分灵活。在面向对象编程中,类的作用之一是封装,而在 CSS 的原子类中,保留了单一属性细粒度的样式封装,方便到处复用。
最后,我们精简代码重构"生龙活虎"的文本电影特效,代码如下:
css
main {
--uno: absolute h-screen w-screen;
& video {
--uno: absolute top-0 left-0 h-full w-full object-cover;
}
.txt-video {
--uno: font-size-20rem font-black text-center line-height-100vh color-black
bg-white mix-blend-screen;
}
}
如你所见,核心的样式代码有且仅有 3 行,都是由若干可读且可复用的原子类自由组合而成。
高潮总结
不管是原生 CSS,还是 SCSS/LESS,或者是诸如 UnoCSS 等其他样式方案,能实现功能的方案就是好方案。大家可以根据自己精通的样式方案刻意练习,重构"生龙活虎"文本电影特效。
另外,语冰在重构文本电影特效时,发现视频的性能并不乐观,而且颜色定义十分受限。
所以我们其实可以尝试使用 gif 动图,或者使用静态图片、但是让静态图片"动起来"的方式"曲线救国"。我会在下一篇博客中重点共享更多有趣又好玩的奇技淫巧,我们日后再说。
本期话题是 ------ 你目前最常用的 CSS 样式方案是什么,以及为什么?
欢迎在本文下方群聊自由言论,文明共享。谢谢大家的点赞,掰掰~
《前端 9 点半》每日更新,坚持阅读,自律打卡,每天一次,进步一点。