为什么使用单个 Div?
2013 年 5 月,我参加了 CSSConf 并观看了Lea Verou 关于 border-radius 的演讲。这是一个令人大开眼界的演讲,我意识到自己对 CSS 行为的理解还不够全面。这让我回想起我在艺术学院学习的时光,当时我不断被鼓励成为自己所选媒介的大师。作为一名网页设计师,CSS 就是我的媒介,因此我挑战自己去学习尽可能多的知识,并探索和实验它的极限。
但是,为什么使用单个 div 呢?
当我学习绘画时,我的课程会进行一些颜色混合练习,我们从三种原色(红、黄、蓝)中创造出各种光谱颜色。练习的目的是学习媒介的行为,而限制则向我们展示了组合的力量。你当然可以购买绿色颜料,但你也可以用蓝色和黄色混合出绿色。限制你的可用选项会迫使你重新评估你现有的工具。
我决定开始一个CSS 绘图项目,每隔几天用 CSS 绘制一些新的东西。为了进一步挑战和探索 CSS 的能力,我给自己设定了一个限制,即在标记中只使用一个 div。与其购买绿色颜料(或添加另一个 div),我需要扩展和组合 CSS 属性来实现我的目标。
工具包
只使用一个 div 和浏览器支持的 CSS 属性,似乎工具过于有限。我发现,重要的不是你有什么工具,而是你如何看待它们。
伪元素
在 HTML 中使用一个 div,由于 CSS 伪类,我实际上可以使用三个元素。因此,使用 div、div:before 和 div:after,我们可以得到如下效果
div { background: red; }
div:before { background: yellow; }
div:after { background: blue; }
将这三个元素视为可以按顺序出现以及三个可叠加的图层会很有帮助。所以在我的脑海中,它通常看起来更像这样
形状
使用 CSS 和一个元素,我们可以得到三种基本形状类型。我们可以使用 width 和 height 属性创建正方形/矩形,使用 border-radius 创建圆形/椭圆形,使用 border 创建三角形/梯形。
我们还可以使用 CSS 创建其他形状,但大多数东西都可以简化为这些形状的某种组合。而且这些是最容易创建和操作的。
相同形状的多个实例
使用多个 box-shadows,我们可以创建许多不同大小、颜色和模糊度的相同形状的版本。在 x 和 y 轴上进行偏移,可以让我们获得几乎无限的多个实例。
div {
box-shadow: 170px 0 10px yellow,
330px 0 0 -20px blue,
330px 5px 5px -20px black;
}
我们甚至可以为我们的 box-shadows 添加 box-shadows。注意它们声明的顺序。同样,将它们视为图层会很有帮助。
渐变
渐变可以通过暗示光源来添加阴影和深度。这使得简单的平面形状看起来更逼真。组合多个 background-images 允许我们使用许多分层的渐变来实现更复杂的阴影,甚至更多形状。
div {
background-image: linear-gradient(to right, gray, white, gray, black);
}
div:after {
background-image: radial-gradient(circle, yellow 50%, transparent 50%),
linear-gradient(to right, blue, red);
}
可视化
最困难的部分是将这些部分可视化地组合成一个可识别的图形。尽管我关注图形的技术方面,但流程的这一部分至关重要。为了帮助解决这个问题,我通常会查看主题的照片并将其可视地分解成碎片。一切都是形状,一切都是颜色。我将整体图片简化为更小的形状或颜色块,我知道(或怀疑可以)用 CSS 实现。
演示
让我们仔细看看两个图形,并分解构成较大图片的一些碎片。首先是绿色蜡笔。
蜡笔由两种主要形状组成:矩形主体和三角形绘图笔尖。
为了捕捉逼真的图像,我必须保证以下几点
- 纸包装的不同颜色
- 包装上的印刷图案和文字
- 显示蜡笔圆润度的阴影
- 显示圆润度和光源的光泽度
所以首先,我使用 div 和背景颜色、从上到下的渐变以及 box-shadow 来创建蜡笔的主体,以显示一些维度
(注意,我在这里使用黑色(a)和白色(a)的混合来代替 rgba)
div {
background: #237449;
background-image: linear-gradient(to bottom,
transparent 62%,
black(.3) 100%);
box-shadow: 2px 2px 3px black(.3);
}
然后我添加了一个从左到右的线性渐变来创建包装。它的 alpha 值为 .6,因此之前的一些渐变会透出来。
div {
background-image: linear-gradient(to right,
transparent 12px,
rgba(41,237,133,.6) 12px,
rgba(41,237,133,.6) 235px,
transparent 235px);
}
接下来,我使用相同的从左到右的渐变技术来创建蜡笔上的印刷条纹。
div {
background-image: linear-gradient(to right,
transparent 25px,
black(.6) 25px,
black(.6) 30px,
transparent 30px,
transparent 35px,
black(.6) 35px,
black(.6) 40px,
transparent 40px,
transparent 210px,
black(.6) 210px,
black(.6) 215px,
transparent 215px,
transparent 220px,
black(.6) 220px,
black(.6) 225px,
transparent 225px);
}
对于印刷的椭圆形,径向渐变非常有效!
div {
background-image: radial-gradient(ellipse at top,
black(.6) 50px,
transparent 54px);
}
我将其分解以演示每个部分,但请记住,background-image 实际上看起来会像这样
div {
// ellipse printed on wrapper
background-image: radial-gradient(ellipse at top,
black(.6) 50px,
transparent 54px),
// printed stripes
linear-gradient(to right,
transparent 25px,
black(.6) 25px,
black(.6) 30px,
transparent 30px,
transparent 35px,
black(.6) 35px,
black(.6) 40px,
transparent 40px,
transparent 210px,
black(.6) 210px,
black(.6) 215px,
transparent 215px,
transparent 220px,
black(.6) 220px,
black(.6) 225px,
transparent 225px),
// wrapper
linear-gradient(to right,
transparent 12px,
rgba(41,237,133,.6) 12px,
rgba(41,237,133,.6) 235px,
transparent 235px),
// crayon body shading
linear-gradient(to bottom,
transparent 62%,
black(.3) 100%)
}
因此,在完成 div 之后,我继续使用 :before 伪元素来创建蜡笔的三角形笔尖。使用实线和透明边框,我创建了一个三角形并将其放置在我刚刚绘制的 div 旁边。
div:before {
height: 10px;
border-right: 48px solid #237449;
border-bottom: 13px solid transparent;
border-top: 13px solid transparent;
}
它与蜡笔的主体相比显得有些平淡,但可以通过 :after 伪元素进行修复。使用它,我添加了一个从上到下的线性渐变来创建一个反射光泽效果,该效果跨越蜡笔的整个宽度。
div:after {
background-image: linear-gradient(to bottom,
white(0) 12px,
white(.2) 17px,
white(.2) 19px,
white(0) 24px);
}
这增加了更多维度和真实感,并有助于解决那个扁平的三角形。作为最后的润色,我在 :after 中添加了一些文本内容,并将其定位为蜡笔包装上的另一个印刷元素。
div:after {
content: 'green';
font-family: Arial, sans-serif;
font-size: 12px;
font-weight: bold;
color: black(.3);
text-align: right;
padding-right: 47px;
padding-top: 17px;
}
就是这样!
让我们看看另一个例子
蜡笔是使用 background-image 和渐变产生逼真效果的一个很好的例子。以下是一个展示多个 box-shadows 强大功能的例子:一个单个 div 相机。
这是相机的主体,使用 background-image 和 border-image 创建。
这是一个 gif,演示了 :before 伪元素(黑色矩形)以及使用其 box-shadows 创建的许多细节。
div:before {
background: #333;
box-shadow: 0 0 0 2px #eee,
-1px -1px 1px 3px #333,
-95px 6px 0 0 #ccc,
30px 3px 0 12px #ccc,
-18px 37px 0 46px #ccc,
-96px -6px 0 -6px #555,
-96px -9px 0 -6px #ddd,
-155px -10px 1px 3px #888,
-165px -10px 1px 3px #999,
-170px -10px 1px 3px #666,
-162px -8px 0 5px #555,
85px -4px 1px -3px #ccc,
79px -4px 1px -3px #888,
82px 1px 0 -4px #555;
}
类似地,这是 :after(灰色圆圈)及其几个 box-shadow 细节。
div:after {
background: linear-gradient(45deg, #ccc 40%, #ddd 100%);
border-radius: 50%;
box-shadow: 0 3px 2px #999,
1px -2px 0 white,
-1px -3px 2px #555,
0 0 0 15px #c2c2c2,
0 -2px 0 15px white,
-2px -5px 1px 17px #666,
0 10px 10px 15px black(.3),
-90px -51px 1px -43px #aaa,
-90px -50px 1px -40px #888,
-90px -51px 0 -34px #ccc,
-90px -50px 0 -30px #aaa,
-90px -48px 1px -28px black(.2),
-124px -73px 1px -48px #eee,
-125px -72px 0 -46px #666,
-85px -73px 1px -48px #eee,
-86px -72px 0 -46px #666,
42px -82px 1px -48px #eee,
41px -81px 0 -46px #777,
67px -73px 1px -48px #eee,
66px -72px 0 -46px #666,
-46px -86px 1px -45px #444,
-44px -87px 0 -38px #333,
-44px -86px 0 -37px #ccc,
-44px -85px 0 -34px #999,
14px -89px 1px -48px #eee,
12px -84px 1px -48px #999,
23px -85px 0 -47px #444,
23px -87px 0 -46px #888;
}
有点疯狂,但如你所见,多个 box-shadows 可以为单个 div 绘图添加很多细节。
最大的挑战
我遇到的两个最大的障碍是三角形形状方面的限制以及渐变的自然行为。
三角形的麻烦
因为三角形是使用边框创建的,所以它限制了我对它们的处理。使用 border-image 添加渐变会应用于所有边框,而不仅仅是一侧。Box-shadows 应用于框的形状,而不是边框创建的三角形形状,因此创建多个三角形形状可能很困难。以下是一个示例,展示了它的外观
div {
border-left: 80px solid transparent;
border-right: 80px solid transparent;
border-bottom: 80px solid red;
}
div:before {
border-left: 80px solid transparent;
border-right: 80px solid transparent;
border-bottom: 80px solid red;
border-image: linear-gradient(to right, red, blue);
}
div:after {
border-left: 80px solid transparent;
border-right: 80px solid transparent;
border-bottom: 80px solid red;
box-shadow: 5px 5px 5px gray;
}
分层渐变
对于渐变,它们的自然行为是填充整个背景。当将多个渐变叠加在一起时,这可能会变得有点棘手。需要花费一些额外的时间来考虑透明度、z-index 以及了解哪些内容可见以及哪些内容不可见。通过有效地使用此技术,我们的图形可以具有惊人的细节。
Tardis 是一个展示和隐藏渐变以创建详细图片的很好的例子。这是一个绘制过程中的图形,显示了一些跨越容器整个宽度的从上到下的渐变。
使用从左到右和从右到左的渐变,我能够覆盖渐变的部分并留下一些部分暴露在外。
生成的图形似乎有许多形状构成 Tardis 的正面,但它是经过策略性分层的线性渐变。有时你必须伪造它。
查看它们在实际中的效果
由于这个项目,出现了一件很棒的事情,那就是一个由Rafael Carício创建的非常酷且有用的 Chrome 浏览器扩展,名为CSS Gradient Inspector。它扩展了开发者工具,可以检查和切换每个元素的渐变,就像它们是图层一样。(在日常项目中也非常有用。)
我非常高兴地看到设计师和开发人员使用动画和 JavaScript 功能对这些图形进行实验和改进。访问该网站并使用您自己的 CSS 进行尝试,网址为a.singlediv.com或在GitHub上!
关于 Lynn Fisher
Lynn Fisher 是一位居住在亚利桑那州钱德勒市的艺术家和设计师。她与&yet的优秀团队合作,设计和开发界面,偶尔也会画画。她喜欢将艺术与技术相结合,并改善设计师和开发人员之间的协作方式。
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 坚定地相信 HTML5 和开放网络,自 1999 年以来一直从事网页前端开发工作 - 在瑞典和纽约市。他还定期在http://robertnyman.com上发表博客文章,并且喜欢旅行和结识新朋友。
17 条评论