我如何仅使用 CSS 渐变来重建宝丽来相机

2025-05-24

我如何仅使用 CSS 渐变来重建宝丽来相机

最初发表于fossheim.io

之前我用 CSS 重新设计了一个旧计算器。制作过程中我非常开心,所以这次我决定用宝丽来相机来做同样的设计。

使用 CSS 制作的宝丽来相机的最终结果

在本教程中,我将指导您完成我的过程,并解释如何自己在 CSS 中复制实体产品。

由于这是一个相当大的项目,我不会单独介绍每个组件,但完整的代码可以在CodePenGitHubGlitch上找到。

我强烈建议对其进行分叉并进行尝试,以进一步了解每个组件是如何构建的。

您需要:

  • 像 Figma 这样的程序可以从图像中选择颜色
  • HTML/CSS 基础知识
  • 理解 CSS 渐变

我还建议准备一些纸笔,以便勾勒出项目的结构。在创建 HTML 和 CSS 时,我不断地在纸上分解各个组件。

步骤 0:准备

首先,你需要找到一张待重建物体的高质量图像。你需要大量挑选颜色和测量尺寸,所以图像质量好非常重要。

用于创建宝丽来相机的参考

这是我一开始用的那张。正如你所见,我还找了一张已经从相同角度、相同光线下拍摄的照片,与我想要的效果一致。

步骤 1:确定结构

一旦我决定要处理哪个图像,我就会对其进行分析并勾勒出基本结构,然后将其转换为 html。

结构的第一张草图

执行此操作时请记住以下几点:

  • 物理组件。如果是相机上的物理按钮或组件(例如镜头或闪光灯),您也希望将其作为代码中的单独组件。这样可以更轻松地设置样式,并方便您将来添加一些额外功能。例如,您可以让闪光灯在按下快门时亮起。
  • 颜色和尺寸。相机底部(打印机所在位置)为黑色,且比顶部略宽。虽然严格来说,它们可能是同一物理组件(相机机身)的一部分,但将其拆分为顶部和底部组件可以带来更大的灵活性,并使设置颜色和尺寸变得更加容易。
  • 阴影、高光和反光。有些组件如果拆分成几个子组件会更容易重现。例如,镜头在玻璃上有一些反光,但在材质的其他部分是看不到的。所以我把这个部分拆分成了突出相机的实体部分和顶部的玻璃。

结构详细草图

考虑到这一点,结构就变成了这样:

  • 相机
    • 顶部
      • 镜片
      • 取景器
      • 闪光
      • 快门
      • 计时器
      • ...
    • 底部
      • 打印机
      • 标识
      • 切换
      • ...

第 2 步:将结构翻译成 HTML

一旦您将图像分成不同的部分并在纸上布置好结构,您就可以很容易地将其转换为 HTML。

<div class="camera">
  <div class="top">
    <div class="flash"></div>
    <div class="timer"></div>
    <div class="sensor"></div>
    <div class="lens"><div class="glass"></div></div>
        ...
    </div>
    <div class="bottom">...</div>
</div>

现在我们已经准备好了,我们可以开始 CSS 工作并实际创建一些视觉效果。

步骤 3:逐个设置每个组件的样式

从轮廓开始

我建议从较大、较容易的部件开始。比如宝丽来相机,最好从机身顶部或底部开始。这些部件细节最少,也决定了相机的整体结构,所以它们有助于你稍后定位其他部件。

把大件部件安装好后,就可以开始安装其他部件了。之后的安装顺序并不重要。我是从下往上安装的,但具体顺序取决于你。

如果您对 CSS 中的渐变还不熟悉,您可能需要先了解一些细节较少的项目(例如红色快门或白色定时器按钮),然后再了解更复杂的项目,例如镜头或闪光灯。

确定尺寸、位置和颜色

您需要在程序中打开图片(我使用了 Figma),您可以在其中选择颜色并测量每个组件的大小。

Figma 文件,其中包含为所有渐变挑选的颜色

底部的彩虹就是一个很好的例子。我首先在它上面画了一个矩形来测量宽度和高度,然后在CSS中设置。同样的方法也可以用于确定位置:

.rainbow {
    display: block;
    width: 40px;
    height: 46px;
    position: absolute;
    top: 100px;
    left: 80px;
}

最好对所有组件进行绝对定位,除了外部相机机身(可以)position: relative。通过绝对定位,一个组件的宽度和高度不会影响其他组件的定位或大小。

至于颜色,我画了几个形状,并使用颜色选择器为每个部分获取正确的颜色代码。对于大多数物理组件,我使用了渐变色而不是纯色,即使组件看起来或多或少有些扁平。

Figma 文件,其中包含为彩虹挑选的颜色

例如,相机机身顶部有三种不同的白色作为底色。虽然不太显眼,但这样做确实让设计更具立体感。

我通常会从组件顶部选取一种颜色,从底部选取另一种颜色,然后以此为基础创建线性渐变。尽量不要选取阴影后面的颜色,因为它们很容易变得太暗。我们稍后会为每个组件添加阴影。

如果您对外观不满意,可能需要添加第三种或第四种颜色,或者稍微降低颜色之间的对比度。这是一个反复试验的过程,因此您需要同时打开输出和代码。

分层渐变

在这样的项目中,你需要在同一个 div 中叠加渐变。我的意思是,叠加很多渐变。

堆叠渐变时需要记住的一件重要事情是它们的显示顺序。让我们来看以下示例:

    background-image: linear-gradient(green,blue),
        linear-gradient(red,orange),
        linear-gradient(black,white);

绿色渐变显示在顶部,红色渐变显示在下方,黑色渐变显示在底部。我们也可以用类似的方式决定渐变的大小、位置和重复次数:

    background-size: 10px 20px, /* green/blue gradient */
        40px 5px, /* red/orange gradient */
        30px 35px; /* black/white gradient */
    background-position: top left, center, bottom right;
    background-repeat: no-repeat, no-repeat, repeat;

示例 1:上身

对于身体的顶部,我主要想要两个堆叠的渐变:

  • 水平渐变,有四种略有不同的白色色调(从身体的顶部、中部和底部选取)
  • 顶部有一个垂直渐变,从两侧略微透明的白色到中间完全透明的白色
    linear-gradient(
      90deg,
      rgba(243,243,243,0.75),
      rgba(243,243,243,0) 15% 85%,
      rgba(243,243,243,0.75)
    ), 
    linear-gradient(#DDD9DA, #E2DEDF, #EAE8EB, #F3F1F4);

示例 2:闪光灯

现在我们来看看一个更复杂的组件,闪光灯。

这个有很多渐变:背景渐变(白色,浅灰色,黑色,深灰色,浅灰色,白色),水平线(透明,浅灰色,白色,透明),然后是垂直线,然后是顶部和底部的白色方块。

Figma 文件,其中包含为 Flash 挑选的颜色

选择渐变颜色后,我们可以将其转换为 CSS,如下所示:

    background-image: linear-gradient(#EDECEA,#F6F6F8) /*Top white square*/,
        linear-gradient(
            90deg,
            rgba(247,246,244,0) 3%,
            rgba(247,246,244,0.5) 3% 6%,
            ..., /*Repeat*/
            rgba(247,246,244,0) 95%,
            rgba(247,246,244,0.5) 95% 98%,
        ), /*Thin Vertical lines*/
        linear-gradient(
            90deg,
            rgba(186,184,185,0.1),
            rgba(247,246,244,0.65),
            rgba(186,184,185,0.1)
        ), /*Bold vertical line 1*/
        linear-gradient(
            90deg,
            rgba(186,184,185,0.1),
            rgba(247,246,244,0.65),
            rgba(186,184,185,0.1)
        ), /*Bold vertical line 2*/
        linear-gradient(
            #E3DEDA 15%,
            #AFAAA6 25% 35%,
            transparent 45%
        ), /*Horizontal lines*/
        linear-gradient(
            #F0EFED 10%,
            #B0ABA7 20%,
            #403C3B 40%,
            #2F2B2A 43%,
            #292524 45% 55%,
            #696562 65% 75%,
            #C2BFBA 82% 86%,
            #DEDAD7 90% 93%, 
            #C9C6C1 94% 96%,
            #FFFEFA 98%
        ); /*White/gray/black background*/

如果我们只是渲染它,我们只会看到顶部有一个大的白色渐变(linear-gradient(#EDECEA,#F6F6F8)),因为默认情况下每个渐变都设置为 100% 宽度和高度并堆叠在一起。

因此,让我们测量顶部渐变的大小,以及垂直线应该出现的位置。

    background-size: 42px 20px, /*White reflection*/
        42px 100%, /*Thin vertical lines*/
        3px 100%, /*Bold vertical line*/
        3px 100%, /*Bold vertical line*/
        100% 3px, /*Horizontal lines*/
        100%; /*Background*/
    background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat, repeat, no-repeat;
    background-position: 24px top, 25px top, 22px top, 64px top, center, center, center;

添加反射和阴影后(将在下一节中解释),我们的闪光灯最终看起来像这样:

css flash 与实际 flash 的对比

边框、阴影和高光

在使用渐变样式设置组件后,显然还缺少一些东西:深度、阴影和高光。就像堆叠渐变一样,我们也可以将阴影堆叠在一起。

它的工作原理与渐变完全相同,首先提到的是位于顶层的渐变。

在这个例子中,我们最终在蓝色阴影上出现了红色阴影:

    box-shadow: 1px 1px 1px 1px red, 2px 2px 2px 2px blue;

如果我们颠倒顺序,蓝色阴影就会位于顶部,遮住红色阴影:

    box-shadow: 2px 2px 2px 2px blue, 1px 1px 1px 1px red;

示例:白色计时器按钮

最简单的例子就是白色计时器按钮,它能很好地展现阴影的效果。放大图片后,我们可以看到创建深度所需的两样东西:

  • 整个按钮周围有一个非常薄的黑色阴影,底部略厚
  • 按钮内部顶部的细白色高光

让我们从阴影开始:

    box-shadow: 0px /*No left or right offset*/
        0.5px /*Moved 0.5px downwards*/
        1px /*Blur of 1px*/
        0.5px /*Sized up with 0.5px*/
        #605C5B /*Black color*/;

接下来,我们可以添加高亮。我们希望高亮显示在按钮内部,而不是外部,因此我们将使用该inset值。

box-shadow: 0px 0.5px 1px 0.5px #605C5B, /*shadow*/
1px 1px 1px #FFFBFC inset; /*highlight*/
/*1px moved down, 1px to the right, 1px blur, white color, inside the div*/

示例:闪光灯周围的深度

让我们回到更复杂的例子——闪光灯。我们希望组件稍微凸起一些,为此我们需要一个白色阴影,并在其下方添加一个灰色阴影。

之后,我们还想在里面添加一些阴影:

  • 白线网格周围的灰色边框
  • 突出显示在顶部
  • 突出显示底部
  • 顶部有阴影
    box-shadow: -1px -1px 1px #BDB8B5,
        -1.5px -2.1px 0.5px #24201D,
        -4px 4px 3px 3px #F4F0EF,
        -5px 8px 8px #ABA6AA,
        0.25px 1px 1px 5px #3E3A38 inset,
        0 -6px 1px 1px #F6F6F8 inset;

反思

一些组件也需要更多反射,例如镜头内部的玻璃和取景器内部的玻璃。在这种情况下,值得为玻璃创建一个额外的 div。让我们看看我是如何解决这个问题的。

示例:镜头玻璃上的反射

使用 CSS 近距离观察相机镜头内的反射

如果我们看中间,我们会看到我在这里使用了 4 个渐变:

  • 填满整个背景的径向渐变,从近黑色逐渐变为深紫色。这是玻璃的颜色。
  • 顶部的浅绿色反射。这是一个径向渐变,中间是绿色,两侧是透明色,向外延伸并向上移动,因此只有角落可见。
  • 底部深绿色的反射,其作用与顶部反射相同,只是颜色不同。
  • 中间的光反射,这是另一个径向渐变,这次从浅黄色变为透明黄色。
    background-image: radial-gradient(rgba(236, 234, 237, 0.3) 50%, transparent 60%),
        radial-gradient(rgba(193, 189, 186, 0.3) 50%, transparent 60%),
        radial-gradient(#5B5758 45%, #302C2D, #131112);
    background-size: 106% 32%, 106% 25%, 100%;
    background-repeat: no-repeat;
    background-position: -3px -7px, bottom -8px left -3px, center;

概括

  1. 选择一个组件开始
  2. 测量并设置尺寸、边框半径和定位
  3. 选择颜色并创建背景渐变
  4. 堆叠多个背景渐变来创建深度
  5. 添加阴影和高光
  6. 重复直到满意为止

最终结果

完整代码可在CodePenGitHubGlitch上找到。打开、检查并试用一下。修改一些值是了解每个组件功能的最佳方法。

更多阅读材料

向我展示你的结果!

如果您按照本教程创建了自己的图像,我很乐意看到最终结果,您可以在 Twitter ( @liatrisbian )、Dev ( @fossheim )、CodePen ( @fossheim ) 或 GitHub ( @sarahfossheim ) 上标记我。

如果您想要额外的挑战,这里有一些有趣的交互可以添加到我现有的代码中:

  • 单击红色快门使闪光灯亮起
  • 使用其中一个开关创建“夜间模式”,将主体颜色从白色变为黑色
  • 打印图片
  • 通过旋转镜头来移动焦点
文章来源:https://dev.to/fossheim/how-i-recreated-a-poloid-camera-with-css-gradients-only-4la5
PREV
我用 HTML 和 CSS 画了一个合成器
NEXT
终极 Linux 速查表