两周前,Adobe 发布了Web版 Photoshop🔗,它是使用 WebAssembly、web components、P3 颜色等 Web 技术构建的。本文就来研究一下网页版 Photoshop 上有趣又有用的 CSS 知识!
Photoshop 旧 Logo
首先,在浏览器控制台中使用了 Photoshop 的 Logo(1990-1991)。
这是如何实现的呢?这里是代码:
Body 元素
要让像Photoshop这样的应用在Web上感觉像一个真正的应用,第一件事是防止滚动。为了实现这一点,<body>元素具有position: fixed和overflow: hidden。
在<body>元素内部,也有多个根元素。
最内部有一个包含导航和文档页面的元素。
Flexbox 布局
在构建现代的 Web 应用时,使用 Flex 布局具有很多好处。网页版 Photoshop 就用到了很多 Flex 布局。
使用 Flexbox 使构建组件变得更容易。下面来看几个使用 Flexbox 的例子。
导航栏
我很喜欢这部分的元素类命名,它没有使用 left、center、right,而是使用了start、center、end。
在应用可以从左到右(LTR)或从右到左(RTL)工作时,这种逻辑命名是正确的做法。
操作
在构建像 Photoshop 这样的复杂应用时,嵌套的 Flexbox 容器是很常见的。下图显示了操作栏中的两个容器。
第一个容器用于缩放。第二个容器包含所有的操作和按钮。
- 使用gap属性非常有助于定义间距,使用margin或padding来实现这个效果可能会变得混乱。
- .container这个类名太过通用了,但在这里非常适用,因为这是一个Web组件,所以所有的样式都被封装起来了。
图层
图层功能是Photoshop的重要组成部分,仔细观察CSS,发现它们全部都是 Flexbox 布局。
下面是图层组件的 HTML 结构:
这里使用 ID 是完全没问题的,因为这是一个 Web 组件,因此 #first-column ID 在页面上出现多少次并不重要。
#link元素是一个 Flexbox 容器,#label元素也是一个 Flexbox 容器。
下面来举一个例子说明如何完成子层的缩进。
- :host()表示图层组件。
- 这感觉像是条件式 CSS。如果HTML属性indent=1存在,那么就更改第一列的padding-right。
如果缩进是两个级别,那么可以通过CSS的calc()函数,将padding-right的值乘以 2。
在浏览器中,尝试嵌套到第 6 层:
而知名的设计软件 Figma 是使用间隔组件来增加嵌套层的间距的。
Grid 布局
新文件模式
在创建新的 Photoshop 文件时,可以选择预定义的尺寸列表。为了实现这一点,有一个包含多个选项卡和一个活动面板的布局。
HTML 如下所示:
在 CSS 中,有一个 1 列 2 行的主网格。其中,第一行的高度根据内容自适应调整行高,而第二行则占据了所有剩余可用空间。
这里有几个要点:
- 使用CSS的:not()选择器。
- 使用[attr^=value]选择器来排除具有以vertical开头的值的direction属性的HTML元素。
这些都是条件式 CSS 技术。
尝试将direction属性更改为vertical,结果符合预期。
下面是基于属性变化的CSS:
为了突出显示哪个选项卡是活动状态,有一个相对于选项卡列表定位的#selection-indicator元素。
图层属性
这部分的 CSS 网格用法很有趣,它适合解决对齐网格中许多元素的问题。
深入研究 CSS:
使用 Firfox 开发者工具来调试这个网格,它会生成模拟的网格布局。当突出显示矩形时,它将显示放置在实际的网格中。
这里使用的技术就是命名网格线,其思想是给每个列或行指定一个名称,然后定义其宽度。列和行的宽度可以是auto
或min-content
,这是创建动态网格的一种很好的方法。
这样,每个网格项都可以在网格内部进行定位:
还有一个细节是对网格项使用了position: absolute。锁定按钮位于网格的中心,但它需要略微从左边和顶部位置进行插入。
输入
下面来看看使用 CSS 网格来布局输入字段的用例。
在浏览器中检查时,可以看到网格线名称或网格区域名称。
- 网格区域名称
- 网格线名称
菜单项
在我看来,在这里使用 CSS 网格有点大材小用了。
这是一个包含 8列 4行的网格。这里似乎一次只能激活一个网格行,其他行将由于内容为空或HTML元素的缺失而折叠。
有趣的是,上面的 CSS 是简化过的版本。原始版本看起来像这样,使用了grid-template缩写。
下面是在应用中找到的一些菜单项:
CSS 网格是针对这个小组件的,感觉是有点多此一举了。
注意,CSS 网格的暗部分处于非活动状态。它们折叠了,因为没有内容。对于这个例子,也可以这样来实现:
当每列和行的值相同时,无需定义它们的开始和结束位置。
CSS变量的广泛使用
更改图层缩略图的大小
Photoshop 可以控制缩略图大小。当有很多图层并且想要在更小的空间中查看更多图层时,这非常有用。
Adobe 团队的构建方式很有趣。首先,图层面板的主容器上有一个 HTML 属性large-thumbs。
在CSS中,有一个:host([large-thumbs])选择器,它分配了特定的CSS变量。
对于每个图层,都有一个名为 psw-layer-thumbnail 的元素,这是将应用CSS变量的地方。
这里,CSS 变量被分配给缩略图。
加载进度
通过使用size属性来管理组件的大小。CSS 变量会根据不同的 size 而变化。
图像控制
如果 HTML 存在属性quiet,则 UI 会更简单(没有边框)。
这也是通过 CSS 变量完成的。
单选按钮
在这个例子中,使用 CSS 变量来根据 HTML 的 size 属性值来改变单选按钮的大小。
菜单处于活动状态时锁定页面
当主菜单处于活动状态时,会有一个名为 holder 的元素填充整个屏幕(遮罩层),并位于菜单下方。
此元素是为了防止用户单击或将鼠标悬停在页面的其他部分,以确保用户只能对菜单进行操作,这可能是为了模仿桌面应用而设置的。
混合模式菜单
这里使用了 CSS 视口单位。混合模式菜单的最大高度为 55vh(视口高度的55%)。
这里还使用了 overscroll-behavior: contains,这是避免滚动正文内容的一个很棒的功能。
图层缩略图
在图层面板中,缩略图使用了object-fit: contain来避免变形。