一封来自 Hackathon 的邀请
今年三月,公司内部邮件转发了一封招募:「AI For Good in a Responsible Way 公益黑客松」,由恩派公益与微软共同发起。174 位报名者,40 支参赛队伍,议题从养老支持、残障融合到教育公平与社区治理。
邮件里写:"期待让 AI 在真实土地上长出答案。"
我报了名,选了技术导师的角色 —— 为参赛团队提供技术指导。线下赛 3 月 27-28 日在昆山计家墩理想村,48 小时现场赛,但赛前就可以远程支持。
在 40 个参赛项目里,我选中了一个叫**「看见生命」**的项目。它的背后是一个叫 一境忆(Yijingyi) 的上海艺术工作室,2020 年成立,专注于特殊儿童(自闭症、罕见病等心智障碍孩子)的融合康复 —— 用艺术疗愈、音乐疗愈、马术疗愈等方式,帮助这些孩子表达自己。
他们发起了一场画展:全球首届青少年线上融合画展。
六幅画,每幅标价 ¥1 —— 象征性定价。不是为了卖画,而是为了说一句话:每一幅画都值得被世界看见。
问题:一个好故事藏在了一个坏网站里
画展挂在 HUcares(hucares.com.hk)网站的一个子页面上 —— ASP.NET WebForms,.NET 4.0 时代的产物。打开一看:
- 机构介绍和画作混在一起,层次不清
- 每幅画重复出现 2-3 次同样的缩略图(轮播图没渲染对)
- 其他页面甚至直接抛 NullReferenceException
- 移动端?别想了
这是一个社会价值 >> 技术水平的典型案例。内容和理念远远走在了呈现方式的前面。
作为导师,我的本能反应不是写 PPT 讲方法论,而是 —— 直接动手写一个。
设计理念:每幅画都值得一个舞台
如果你去过 apple.com 的产品页,你会注意到一个模式:每个产品都有自己的「舞台」—— 满屏展示,慷慨的留白,滚动驱动的叙事,一次只讲一件事。
我想让这些孩子的画也得到同样的待遇。
不是缩略图网格,不是轮播图,而是 —— 你滚一屏,就进入一幅画的世界。
叙事结构
页面像走进一个画廊:
入口大厅 → 策展宣言 → 画作1 → 画作2 → ... → 画作6 → 价值观 → 尾厅
12 个全屏 section,从深色的入口大厅开始,明暗交替,最后回到深色的尾厅。像呼吸一样的节奏。
策展宣言
什么是美?谁来定义?
美的背后是什么?
我们相信,美来自人类与生俱来的情感和感受力
我们相信,在孩子的画作中蕴藏着生命的灵思之美
我们相信,这灵思之美将创造不一样的世界
这段文字在滚动时逐行淡入 —— 每一句信念都有自己出场的时刻。

技术:零依赖的 1400 行
整个项目:
| 文件 | 行数 | 作用 |
|---|---|---|
yijingyi.html | 242 | 语义化 HTML,12 个 section |
style.css | 1056 | Apple 风格视觉系统 |
app.js | 112 | 滚动动画 + 进度导航 |
零依赖 —— 没有 React,没有 Tailwind,没有 npm install。打开 HTML 文件就能看。这是 Hackathon 最需要的:任何人拿到代码都能直接跑。
几个值得一提的细节
明暗交替的呼吸感
--dark-bg: #0a0a0a; /* 近乎纯黑 */
--light-bg: #fafaf7; /* 暖白,不是刺眼的纯白 */
六幅画作在深色和浅色背景间交替展示。深色背景上,画作仿佛从黑暗中浮现;浅色背景上,画作沐浴在温暖的光线里。
滚动驱动的渐显系统
整个动画系统只靠一个 IntersectionObserver —— 元素进入视口 12% 时触发 revealed class:
var revealObserver = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add('revealed');
revealObserver.unobserve(entry.target);
}
});
}, { threshold: 0.12 });
CSS 负责定义过渡 —— translateY(40px) 上移淡入,scale(0.9) 放大定格,子元素 stagger 错开 150ms 逐个登场。所有动画都用 cubic-bezier(0.25, 0.46, 0.45, 0.94) 这条曲线,就是 Apple 官网用的那个 ease-out。
胶片质感噪点
Hero 区域叠了一层 SVG 噪点纹理(feTurbulence),opacity: 0.5,mix-blend-mode: overlay —— 给数字画面增添了一丝胶片的颗粒感,和艺术画展的气质很搭。
¥1 象征定价徽章
.price-badge {
border: 1px solid var(--accent);
border-radius: 100px; /* 药丸形态 */
color: var(--accent); /* 琥珀金 */
}
不抢画的风头,安静地待在画作下方,但你不会错过它。
右侧进度导航
九个小圆点固定在右侧,随滚动高亮当前 section。点击可以跳转。经过深色 section 时自动变白,浅色 section 时自动变深。
无障碍:不是附加题,而是主题
这是一个关于融合教育的画展 —— 关于特殊儿童的包容和可见性。如果页面本身不是无障碍的,那就是在打自己的脸。
所以:
- 每幅画都有双语
alt文本(中文画名 + 英文描述) - 语义化的
<article>、<figure>、<figcaption>结构 - 顶部有
skip-link,Tab 键可达 prefers-reduced-motion: reduce时所有动画直接跳过:focus-visible焦点环使用琥珀金色,和品牌色一致- 所有文本用
rem+clamp(),尊重用户的浏览器字号设置 lang="zh-Hans"主语言声明,英文段落加lang="en"
<a href="#gallery" class="skip-link">跳转到画展 / Skip to Gallery</a>
这行代码平时看不见,但屏幕阅读器的用户按 Tab 时,它会跳出来让你直达画廊。
回到初衷
写完代码 build 通过的那一刻,我又从头到尾滚了一遍。
鲸鱼宝宝从黑色背景中浮现,声音的奔跑在暖白里奔腾,飞之眷展开翅膀,星怪露出奇异的笑容,猫咪蜷在角落,最后 —— 爱。
六幅画,六个孩子,六个世界。
标价 ¥1,不是打折,是在说:你愿意花一块钱,看见他们吗?
我不确定这个页面会不会最终上线,Hackathon 项目的命运往往不在导师手里。但至少现在,这六幅画不再藏在 ASP.NET 的 NullReferenceException 后面了。
它们有了自己的舞台。
「看见生命的灵思之美」—— 一境忆艺术工作室,上海,2020 年至今。

