通常情况之下,Web 开发者都习惯了规则的矩形布局的效果,对于 Web 设计师提供的不规则布局,难免会带有一种恐惧与排斥的心理。事实上,**现代 Web 布局**技术构建这些不规则的布局,例如类似杂志类创意布局,不规则图形的布局等,不再是问题。而且现代 CSS 提供了很多新特性,使这件事情变得更容易。要是你将 SVG 相关的特性以及一些工具结合起来,构建这些不规则的布局你可以手到擒来。比如,接下来我们要构建的水波纹布局效果,就是这样完成的。
如何构建水波纹
我们的目标非常明确,在 Web 上构建带有水波纹的 UI 效果。
到目前为止,我们有两种主流技术可以创建带有水波纹的 UI 效果:CSS 和 SVG 。接下来,我们分别来看看 CSS 和 SVG 是如何构建水波纹的。
CSS 创建水波纹
先从气泡图形着手,这样能更好的帮助大家理解 CSS 创建水波纹的过程。
在 CSS 的世界中,我们会常常利用 CSS 的一些特性,例如圆角、边框、阴影、渐变、变换、裁剪和遮罩 等可以绘制出各种不同的不规则形状。比如,使用 border-radius
就可以快速构建出气泡图形:
直接上代码:
HTML
<section class="bubble"></section>
CSS
.bubble::after {
content: '';
border-top-left-radius: 50% 100%;
border-top-right-radius: 50% 100%;
position: absolute;
bottom: 0;
z-index: -1;
width: 100%;
background-color: #0f0f10;
height: 85%;
}
这里借助 CSS 的伪元素 ::after
和 border-radius
绘制了一个具有响应式的气泡图形,它看上去就类似一个椭圆:
Demo 地址:codepen.io/airen/full/...
现在,我们在这个椭圆上再叠加一个相似的椭圆,使其外观看上去类似一个水波纹:
HTML
<section>
<div class="curve"></div>
</section>
CSS
section {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
min-height: 400px;
padding-top: 100px;
background: #3c31dd;
}
.curve {
position: absolute;
height: 250px;
width: 100%;
bottom: 0;
text-align: center;
&::before,
&::after {
content: "";
display: block;
position: absolute;
width: 55%;
height: 100%;
background-color: #3c31dd;
border-radius: 100% 50%;
}
&::before {
transform: translate(85%, 60%);
background: #fff;
}
&::after {
transform: translate(-4%, 40%);
z-index: -1;
}
}
Demo 地址:codepen.io/airen/full/...
效果只能说是一般般,而且这种方案有两个致命的缺点。首先,两个伪元素要完美地定位,可能有些困难(如果追求不够高,那么大多数情况来说,它也可用);其次,背景调整之后,伪元素的颜色也要随着改变:
如果你碰到相似的场景,那么可以考虑使用 CSS 自定义属性来修复它:
CSS
:root {
--bg: #fff;
}
body {
min-height: 100vh;
background-color: var(--bg);
}
.curve::before {
transform: translate(93%, 48%);
background: var(--bg);
}
Demo 地址:codepen.io/airen/full/...
特别声明,小心伪元素定位造成溢出问题。
SVG 创建水波纹
使用 SVG 创建水波纹要比使用 CSS 简单地多。因为 SVG 最大的特性就是可以无限缩放,而且还不会失真。另外就是,可以使用 <path>
绘制出任何你想要的水波纹效果。即使你不懂 SVG ,你也可以借且诸如 Figma 这样的图形设计软件或在线工具(例如 getwaves.io 、ShapeDriver 和 Haikei app 等)获得绘制水波纹的 SVG 代码。
URL:getwaves.io/
XML
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320" class="wave">
<path fill="#0099ff" fill-opacity="1" d="M0,288L60,288C120,288,240,288,360,261.3C480,235,600,181,720,181.3C840,181,960,235,1080,245.3C1200,256,1320,224,1380,208L1440,192L1440,0L1380,0C1320,0,1200,0,1080,0C960,0,840,0,720,0C600,0,480,0,360,0C240,0,120,0,60,0L0,0Z"></path>
</svg>
SVG 的另一个优势是,可以直接嵌套到 HTML 文档中:
HTML
<div class="wave--container">
<h1>Hello, world!</h1>
<p>Check out my awesome waves!</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320" class="wave">
<path fill="#0099ff" fill-opacity="1" d="M0,288L60,288C120,288,240,288,360,261.3C480,235,600,181,720,181.3C840,181,960,235,1080,245.3C1200,256,1320,224,1380,208L1440,192L1440,0L1380,0C1320,0,1200,0,1080,0C960,0,840,0,720,0C600,0,480,0,360,0C240,0,120,0,60,0L0,0Z"></path>
</svg>
</div>
根据布局需要,添加少些 CSS ,就可以构建出页头带有水波纹的布局效果:
Demo 地址:codepen.io/airen/full/...
案例:水波纹卡片
Demo 地址:codepen.io/airen/full/...
不难发现,上面这个案例中,好多地方都有水波纹的身影。前面说了,水波纹的效果,不需要担心,即使你不懂任何 SVG 也无妨,使用 getwaves.io 工具,可以获得案例中所需的水波纹的效果以及对应的 SVG 代码。
只不过,在这里我将利用 SVG 的雪碧图技术,即使用 SVG 的 <symbol>
将每个水波纹实例化,然后在需要使用的地方使用 <use>
来调用。
XML
<svg style="display:none;">
<symbol id="one" viewBox="0 0 1440 320" preserveAspectRatio="none">
<path fill="white" d="M0,96L1440,320L1440,320L0,320Z"></path>
</symbol>
<symbol id="two" viewBox="0 0 1440 320" preserveAspectRatio="none">
<path fill="white" d="M0,32L48,37.3C96,43,192,53,288,90.7C384,128,480,192,576,197.3C672,203,768,149,864,138.7C960,128,1056,160,1152,160C1248,160,1344,128,1392,112L1440,96L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path>
</symbol>
<symbol id="three" viewBox="0 0 1440 320" preserveAspectRatio="none">
<path fill="white" d="M0,128L30,144C60,160,120,192,180,197.3C240,203,300,181,360,192C420,203,480,245,540,245.3C600,245,660,203,720,192C780,181,840,203,900,181.3C960,160,1020,96,1080,80C1140,64,1200,96,1260,122.7C1320,149,1380,171,1410,181.3L1440,192L1440,320L1410,320C1380,320,1320,320,1260,320C1200,320,1140,320,1080,320C1020,320,960,320,900,320C840,320,780,320,720,320C660,320,600,320,540,320C480,320,420,320,360,320C300,320,240,320,180,320C120,320,60,320,30,320L0,320Z"></path>
</symbol>
<symbol id="four" viewBox="0 0 1440 320" preserveAspectRatio="none">
<path fill="white" d="M0,192L120,192C240,192,480,192,720,165.3C960,139,1200,85,1320,58.7L1440,32L1440,320L1320,320C1200,320,960,320,720,320C480,320,240,320,120,320L0,320Z"></path>
</symbol>
<symbol id="five" viewBox="0 0 1440 320" preserveAspectRatio="none">
<path fill="white" d="M0,32L120,69.3C240,107,480,181,720,192C960,203,1200,149,1320,122.7L1440,96L1440,320L1320,320C1200,320,960,320,720,320C480,320,240,320,120,320L0,320Z"></path>
</symbol>
<symbol id="six" viewBox="0 0 1440 320" preserveAspectRatio="none">
<path fill="rgba(255, 255, 255, .8)" d="M0,32L120,64C240,96,480,160,720,160C960,160,1200,96,1320,64L1440,32L1440,320L1320,320C1200,320,960,320,720,320C480,320,240,320,120,320L0,320Z"></path>
</symbol>
</svg>
如果你希望能更好的控制每个水波纹的颜色,那么建议你将 fill
设置为 currentColor
或 CSS 自定义属性的值。这样利用 CSS 穿透 <use>
元素,覆盖引用的 SVG 的样式。有关于这方面的详细介绍,请移步 《CSS Tips:CSS 如何穿透 SVG 的 use》。
我们以示例中的卡片为例,你可能需要像下面这样的一个 HTML:
HTML
<div class="cards">
<div class="card">
<figure>
<img src="https://picsum.photos/id/188/800/600" alt="">
<svg>
<use href="#two"></use>
</svg>
</figure>
<figcaption>
<p>现代 Web 布局</p>
</figcaption>
</div>
<!-- 其他 Card -->
</div>
<figure>
中的 <use>
就是引用 <symbol>
已实例化的水波纹。接下来,你需要使用一点 CSS 来样式化卡片:
CSS
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100% - 18px, 300px), 1fr));
gap: 2rem;
.card {
display: grid;
gap: 2rem;
position: relative;
box-shadow: 0 5px 20px 2px rgb(0 0 0 / 0.15);
min-width: 0;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, .125);
border-radius: .25rem;
overflow: hidden;
figure {
position: relative;
}
img {
display: block;
max-width: 100%;
aspect-ratio: 4 / 3;
border-radius: .25rem .25rem 0 0;
object-fit: cover;
object-position: center;
}
svg {
position: absolute;
bottom: 0;
left: 0;
height: 55px;
width: 100%;
}
figcaption {
padding: 0 20px 20px;
font-weight: bold;
}
}
}
整个布局,使用了 CSS Grid 中的 RAM 布局技术,另外还应用了些新的 CSS 特性,例如 aspect-ratio 设置图片的宽高比
,object-fit 和 object-position 防止图片拉伸和挤压
等。其他的 CSS 应该对于大家来说,很普通,就不在这里重复阐述!
写在最后
利用相似的技术,你不仅仅局限于水波纹的布局,你可以实任何不规则的效果。最后希望这篇文章所阐述的小技巧对你今后的工作有所帮助。
如果你对 CSS 方面的技巧感兴趣,请移步阅读:
如果你觉得该教程对你有所帮助,请给我点个赞。要是你喜欢 CSS ,或者想进一步了解和掌握 CSS 相关的知识,请关注我的专栏,或者移步阅读下面这些系列教程: