你知道Web版本的 Photoshop 都用了哪些CSS技术吗?

目录
文章目录隐藏
  1. 前言
  2. Photoshop 旧版 Logo
  3. body 元素
  4. 几乎都是 Flexbox 布局
  5. 关于 CSS Grid 布局
  6. 大量使用 CSS 变量
  7. 当菜单处于活动状态时锁定页面
  8. 混合模式菜单
  9. 注释组件
  10. 对图层缩略图使用 Object-Fit: Contain
  11. 最后

前言

几周前,Adobe 发布了一个 Web 版的 Photoshop,它是用 WebAssembly、Web 组件、P3 颜色等网络技术构建的。

Photoshop 是我 14 岁时学会的第一个专业设计应用程序。这是我成为设计师并最终成为前端开发人员的原因之一。正因为如此,我认为看看 CSS 是如何助力像 Photoshop 这样的大型应用开发会很有趣。

你知道 Web 版本的 Photoshop 都用了哪些 CSS 技术吗?

在这篇文章中,我将分享在 Web 版的 Photoshop 中我觉得有趣的 CSS 发现。

Photoshop 旧版 Logo

我注意到的第一件事是在浏览器控制台中使用 Photoshop(1990-1991)的旧 Logo。

Photoshop 旧版 Logo你会对这样的东西是如何制作的感到好奇吗?以下是代码:

console.info(
  "%c %cAdobe %cPhotoshop Web%c  %c2023.22.0.0%c  %c56043548b47",
  "padding-left: 36px; line-height: 36px; background-image: url('data:image/gif;base64,R0lGODlhIAAgAPEBAAAAAP///wAAAAAAACH5BAEAAAIALAAAAAAgACAAAAKkhC+py3zfopxGvIsztsCGD4La2FVAGBoBuZnox45WcqLsum5KDWdvf1nwTo+fLbgDqo7LFCJJbOY0oidt6ozVKrtib0qaCnlYcJh7rf5iK6HZaM64VeS6L+pWf89WT+6vRAUBBVQ1gpOTJ4IYdxCnOBSJ8ZhkZNekk5ZSxpTpt6Y1eEVm00j3VALDmBXVyPEJB2r2ShoLh2ASqvU60dsr5yuBUQAAOw=='); background-size: 32px; background-repeat: no-repeat; background-position: 2px 2px", "background: #666; border-radius:0.5em 0 0 0.5em; padding:0.2em 0em 0.1em 0.5em; color: white; font-weight: bold", "background: #666; border-radius:0 0.5em 0.5em 0; padding:0.2em 0.5em 0.1em 0em; color: white;", "", "background: #c3a650; border-radius:0.5em; padding:0.2em 0.5em 0.1em 0.5em; color: white;", "", "background: #15889f; border-radius:0.5em; padding:0.2em 0.5em 0.1em 0.5em; color: white;");

body 元素

要让 Photoshop 这样的应用在 Web 网页上有真实应用的感觉,首先需要防止滚动。为了实现这一点,<body>元素设置了position: fixedoverflow: hidden

body,
html {
  height: 100%;
}

body {
  font-family: adobe-clean, sans-serif;
  margin: 0;
  overflow: hidden;
  position: fixed;
  width: 100%;
}

<body>元素内部,也有多个根元素。

<psw-app>
  <psw-app-context>
    <ue-video-surface>
      <ue-drawer>
        <div id="appView">
          <psw-app-navbar></psw-app-navbar>
          <psw-document-page></psw-document-page>
        </div>
      </ue-drawer>
    </ue-video-surface>
  </psw-app-context>
</psw-app>

最里面是包含导航和文档页面的元素 #appView

#appView {
  background-color: var(--editor-background-color);
  color: var(--spectrum-global-color-gray-800);
  display: flex;
  flex-direction: column;
}

包含导航和文档页面的元素 

几乎都是 Flexbox 布局

当构建一个 web 应用程序时,使用flexbox有很多好处。当我想到Flexbox和 Photoshop 一起出现时,我的感觉是很复杂。

Flexbox 布局

Photoshop 是一个著名的设计软件,是许多人进入设计领域的第一款软件。另一方面使用 Flexbox 构建组件变得更容易,对 CSS 对新手来说更容易。

无需使用clearfix清除浮动,只需添加display: flex,然后根据需要设置子项的样式。让我们探索 Photoshop 中的相关Flexbox使用情况。

导航栏

我喜欢这里的命名。他们使用“start”,“center”和“end”,而不是使用“leftcenterright”,。

导航栏

对于可以从左到右(LTR)或从右到左(RTL)工作的应用程序来说,这种逻辑命名是正确的。

Context Bar

在构建像 Photoshop 这样的复杂应用程序时,嵌套的flexbox容器是必要的。在下图中,我在上下文栏中突出显示了两个容器。

Context Bar

第一个容器用于抓取动作。第二个容器包含所有操作和按钮。

.container {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--spectrum-global-dimension-size-50);
}
  • gap的使用对定义间距有很大帮助。相比使用 margin 或 padding 就好多了。
  • 名称.container太通用了,但它在这里恰到好处,因为这是一个 Web 组件,所有的样式都被封装在内部。

图层

由于图层功能是 Photoshop 的重要组成部分,因此它可能是新手将要学习的前几件事之一。我好奇地检查了它们背后的 CSS 实现。

这里是层组件的 HTML 代码:

<psw-tree-view-item indent="0" layer-visible can-open dir="ltr" open>
  <div id="link">
    <span id="first-column"></span>
    <span id="second-column"></span>
    <span id="label"></span>
  </div>
</psw-tree-view-item>

你认为这里使用 ID 是完全可以的吗?由于这是一个 Web 组件,所以#first-column ID在页面上出现多少次并不重要。

Web 组件

#link元素是主要的flexbox包装器,#label中的元素也是flexbox包装器。

<div class="layer-content layer-wrapper selected">
  <psw-layer-thumbnail></psw-layer-thumbnail>
  <div class="name" title="Layer name">Layer name</div>
  <div class="actions"></div>
  <overlay-trigger></overlay-trigger>
</div>

让我们看看子层的缩进是如何完成的。

子层的缩进是如何完成的

  • :host()表示层组件
  • 如果有 HTML 属性存在indent=1,则更改第一列的padding-right

CSS :host 是一个伪类选择器,它用于选择当前组件的宿主元素。:host 选择器只能在 Shadow DOM 中使用,因为它选择的是组件的根元素,而不是组件内部的子元素。

:host([dir="ltr"][indent="1"]) #first-column {
  padding-right: var(--spectrum-global-dimension-size-200);
}

如果是indent=2,则通过 CSS calc()函数将padding-right的值乘以 2。

:host([dir="ltr"][indent="2"]) #first-column {
  padding-right: calc(2 * var(--spectrum-global-dimension-size-200));
}

子层的缩进是如何完成的

在浏览器中,我尝试嵌套到第 6 级。下面是一张真实的截图:

尝试嵌套到第 6 级

当看到这个的时候,我检查Figma背后的 CSS 实现。他们使用了一个间隔组件来增加嵌套层的间距。

间隔组件

有趣的是,两个主要的设计应用程序使用了不同的技术来实现相同的目标。

关于 CSS Grid 布局

新建文件弹窗

创建新的 Photoshop 文件时,您可以选择预定义的大小列表。为了实现这一点,有一个包含多个选项卡和一个活动面板的布局。

新建文件弹窗

HTML 代码如下:

<sp-tabs
  id="tabs"
  quiet=""
  selected="2"
  size="m"
  direction="horizontal"
  dir="ltr"
  focusable=""
>
  <div id="list"></div>
  <slot name="tab-panel"></slot>
</sp-tabs>

在 CSS 中,有一个 1 列 2 行的主网格。第一行是 auto,第二行跨越可用空间。

:host {
  display: grid;
  grid-template-columns: 100%;
}

:host(:not([direction^="vertical"])) {
  grid-template-rows: auto 1fr;
}

这里有几件事:

  • 使用 CSS:not()选择器
  • 使用[attr^=value]选择器排除属性direction的值以vertical开头的 HTML 元素。

我认为这是一种条件 CSS 技术。

我尝试将 direction 属性更改为 vertical。

CSS 技术

下面是基于属性更改的 CSS:

:host([direction^="vertical"]) {
  grid-template-columns: auto 1fr;
}

:host([direction^="vertical-right"]) #list #selection-indicator,
:host([direction^="vertical"]) #list #selection-indicator {
  inline-size: var(
    --mod-tabs-divider-size,
    var(--spectrum-tabs-divider-size)
  );
  inset-block-start: 0px;
  inset-inline-start: 0px;
  position: absolute;
}

要突出显示哪个选项卡项处于活动状态,有一个相对于选项卡列表定位的#selection-indicator元素。

图层属性

我很喜欢这里的 CSS 网格。它适用于在网格中对齐多个元素的问题。

图层属性

在 CSS 中,我注意到以下代码:

.content {
  position: relative;
  display: grid;
  grid-template-rows: [horizontal] min-content [vertical] min-content [transforms] min-content [end];
  grid-template-columns: [size-labels] min-content [size-inputs] auto [size-locks] min-content [space] min-content [position-labels] min-content [position-inputs] auto [end];
  row-gap: var(--spectrum-global-dimension-size-150);
}

这里使用的技术称为命名网格线。这个想法是你命名每个列或网格,然后定义其宽度。列和行的宽度为automin-content。这是制作动态网格的好方法。

制作动态网格

这样每个网格项都应该定位在网格中。以下是一些例子:

.horizontal-size-label {
  grid-area: horizontal / size-labels / horizontal / size-labels;
}

.vertical-position-input {
  grid-area: vertical / position-inputs / vertical / position-inputs;
}

.horizontal-position-input {
  grid-area: horizontal / position-inputs / horizontal /
    position-inputs;
}

另一个引起我注意的细节是在网格项中使用position: absolute。锁定按钮被放置在网格的中心,但它需要在lefttop位置稍微偏移一些。

.lock-button {
  grid-area: horizontal / size-locks / horizontal / size-locks;
  position: absolute;
  left: 8px;
  top: 22px;
}

Drop-Shadow 输入框

这是许多 CSS 网格用于输入字段布局的示例。

:host([editable]) {
  display: grid;
  grid-template-areas:
    "label ."
    "slider number";
  grid-template-columns: 1fr auto;
}

:host([editable]) #label-container {
  grid-area: label / label / label / label;
}

:host([editable]) #label-container + div {
  grid-area: slider / slider / slider / slider;
}

:host([editable]) sp-number-field {
  grid-area: number / number / number / number;
}

在浏览器中检查时,可以看到轴网线名称或轴网区域名称。

轴网线名称或轴网区域名称

对应网格线名称:

对应网格线名称

你可以用两种不同的方式查看布局,对于调试或理解您试图构建/修复的布局非常有用。
CSS 网格应该在我们的 Web 应用程序中更多地使用,但绝对不像下面的例子。

菜单网格

菜单网格

我认为在这里使用 CSS 网格布局有点过头了,下面说明一下我的理解。

sp-menu-item {
  display: grid;
  grid-template-areas:
    ". chevronAreaCollapsible . iconArea sectionHeadingArea . . ."
    "selectedArea chevronAreaCollapsible checkmarkArea iconArea labelArea valueArea actionsArea chevronAreaDrillIn"
    ". . . . descriptionArea . . ."
    ". . . . submenuArea . . .";
  grid-template-columns: auto auto auto auto 1fr auto auto auto;
  grid-template-rows: 1fr auto auto auto;
}

这是一个包含 8 列 * 4 行的网格。从我花费的时间来理解他们为什么这样做,似乎一次只有一行网格是活跃的,其他行会因为内容为空或者缺少 HTML 元素而折叠。

有趣的是,上面的 CSS 是我简化后的。原始版本看起来像这样,团队使用了grid-template速记。

grid-template 速记

以下是我可以在应用程序中找到的相关菜单项。

相关菜单项

这个 CSS 网格是为了这个小组件而设计的,我认为在这里使用 CSS 网格是一种过度设计。

下面是一个使用网格的例子。

.checkmark {
  align-self: start;
  grid-area: checkmarkArea / checkmarkArea / checkmarkArea /
    checkmarkArea;
}

#label {
  grid-area: labelArea / labelArea / labelArea / labelArea;
}

::slotted([slot="value"]) {
  grid-area: valueArea / valueArea / valueArea / valueArea;
}

CSS 网格

请注意 CSS 网格中的灰色部分是不活动的。它们因为没有内容而被折叠了。对于这个具体的例子,作者也可以这样做:

.checkmark {
  align-self: start;
  grid-area: checkmarkArea;
}

#label {
  grid-area: labelArea;
}

::slotted([slot="value"]) {
  grid-area: valueArea;
}

当它们是相同的值时,不需要定义每个列和行的开始和结束。

大量使用 CSS 变量

我真的很喜欢 CSS 变量如何用来改变 UI。我将着重指出这方面的多个例子。

更改图层缩略图的大小

如果您熟悉 Photoshop,则可以控制缩略图大小并使其更小。当您有很多层,并希望在更少的空间中查看更多层时,这很有用。

更改图层缩略图的大小

首先层面板的主容器上有一个 HTML 属性large-thumbs

<psw-layers-panel large-thumbs></psw-layers-panel>

在 CSS 中,有:host([large-thumbs])分配特定的 CSS 变量。

:host([large-thumbs]) {
  --psw-custom-layer-thumbnail-size: var(
    --spectrum-global-dimension-size-800
  );
  --psw-custom-layer-thumbnail-border-size: var(
    --spectrum-global-dimension-size-50
  );
}

对于每个层,都有一个名为psw-layer-thumbnail的元素。这是 CSS 变量将被应用的地方。它将从主容器继承它。

<psw-layers-panel-item>
  <psw-tree-view-item>
    <psw-layer-thumbnail class="thumb"></psw-layer-thumbnail>
  </psw-tree-view-item>
</psw-layers-panel-item>

这里 CSS 变量被分配给缩略图。

:host {
  --layer-thumbnail-size: var(
    --psw-custom-layer-thumbnail-size,
    var(--spectrum-global-dimension-size-400)
  );
  --layer-badge-size: var(--spectrum-global-dimension-size-200);
  position: relative;
  width: var(--layer-thumbnail-size);
  min-width: var(--layer-thumbnail-size);
  height: var(--layer-thumbnail-size);
}

Loading 进度条

管理组件的大小是通过使用属性size来完成的,CSS 变量根据大小而变化。

Loading 进度条

:host([size="m"]) {
  --spectrum-progressbar-size-default: var(
    --spectrum-progressbar-size-2400
  );
  --spectrum-progressbar-font-size: var(--spectrum-font-size-75);
  --spectrum-progressbar-thickness: var(
    --spectrum-progress-bar-thickness-large
  );
  --spectrum-progressbar-spacing-top-to-text: var(
    --spectrum-component-top-to-text-75
  );
}

图像控件

如果 HTML 属性quite存在,则 UI 更简单。

图像控件

这也可以通过 CSS 变量来实现。

:host([quiet]) {
  --spectrum-actionbutton-background-color-default: var(
    --system-spectrum-actionbutton-quiet-background-color-default
  );
  --spectrum-actionbutton-background-color-hover: var(
    --system-spectrum-actionbutton-quiet-background-color-hover
  );
  /* And a lot more styles that I removed for the purpose of keeping the article clean. */
}

单选按钮

在这个例子中,团队使用 CSS 变量根据size HTML 属性更改单选按钮的大小。

单选按钮

<sp-radio size="m" checked="" role="radio"></sp-radio>
:host([size="m"]) {
  --spectrum-radio-height: var(--spectrum-component-height-100);
  --spectrum-radio-button-control-size: var(
    --spectrum-radio-button-control-size-medium
  );
  /* And a lot more styles that I removed for the purpose of keeping the article clean. */
}

当菜单处于活动状态时锁定页面

当主菜单处于活动状态时,有一个“保持器”元素填充整个屏幕,位于菜单下方。

当菜单处于活动状态时锁定页面

#actual[aria-hidden] + #holder {
  display: flex;
}

#holder {
  display: none;
  align-items: center;
  justify-content: center;
  flex-flow: column;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

此元素用于防止用户点击或悬停在页面的其他部分,看起来像在模仿桌面应用程序。

混合模式菜单

我在这里发现了 CSS viewport单元的用途。混合模式菜单的最大高度为55vh

混合模式菜单

sp-menu {
  max-height: 55vh;
  --mod-menu-item-min-height: auto;
}

::slotted(*) {
  overscroll-behavior: contain;
}

overscroll-behavior: contain也有用到。这是一个很好的功能,可以避免滚动正文内容。

注释组件

用户可以在画布上的任何地方钉上注释或绘图。我检查了组件,以了解它是如何构建的。

我喜欢动态定位和颜色的 CSS 变量

注释组件

为了将每个评论放置在用户选择的位置,团队使用了通过 JS 提供的 CSS 变量来处理。

<div
  data-html2canvas-ignore="true"
  class="Pin__component ccx-annotation"
  style="
    --offset-x: 570.359375px;
    --offset-y: 74.23046875px;
    --ccx-comments-pin-color: #16878C;
  "
></div>
.Pin__component {
  --pin-diameter: 24px;
  left: calc(var(--offset-x) - var(--pin-diameter) / 2);
  top: calc(var(--offset-y) - var(--pin-diameter) / 2);
  position: absolute;
  height: var(--pin-diameter);
  width: var(--pin-diameter);
  border-radius: var(--pin-diameter);
  border: 1px solid white;
  background: var(--ccx-comments-pin-color);
}

使用 SVG 进行工程图标注

当你将图片缩小时,SVG 笔划不会调整大小,而且看起来很粗。

使用 SVG 进行工程图标注

据我所知,这可以通过添加vector-effect: non-scaling-stroke来解决。但我没试过。

对图层缩略图使用 Object-Fit: Contain

在图层面板中,缩略图使用object-fit: contain以避免失真。

对图层缩略图使用 Object-Fit: Contain

对图层缩略图使用 Object-Fit: Contain

最后

文章到此就结束了,介绍了 Photoshop Web 版本使用的一些 CSS 技术。与国内常见的 CSS 技术相比,有许多不同之处,其中很多部分值得学习和借鉴。当然这只是其中的一部分,如果你感兴趣,可以查看他们的源代码来深入研究。

本文为译文,原文链接,点击这里查看

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 你知道Web版本的 Photoshop 都用了哪些CSS技术吗?

发表回复