现代 CSS

CSS秘密花园:图片边框

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

CSS Secrets》是@Lea Verou最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

CSS Secrets

问题

有时候,我们想将一些图案或图片添加为边框,而不是背景。比如,在下图中所示的元素就拥有一个装饰性的边框,边框内是一个被限制在边框区域的图片。此外,我们还希望图片可以覆盖整个边框区域。那么我们怎样使用 CSS 达到这一目的呢?

图片边框

图注:图片被用来装饰各种高度的边框

此时,也许在你的内心会响起一个响亮的声音:“border-image,border-image,我们可以使用 border-image,它可以完美的解决这个问题!”年轻人,做事不要太急躁。让我们重新回忆一下 border-image 的解析机制:它实际上将背景分成了九块,然后分别将各个块作用到了元素的边角上。下图就是一个视觉原理图。

图片边框

图注:border-image 的快速入门。上面:分割后的图片;虚线框内的就是分割后的碎片;中间:border-image: 33.34% url(...) stretch; 下面: border-image: 33.34% url(...) round;,在线示例链接

那我们是否可以将图片切分成块,然后使用 border-image 模拟出下图这样的效果呢?

图片边框

实际上,即使我们精确计算出了元素的尺寸和边框宽度,仍然无法达到自动适配多种尺寸的目的。问题的核心就是,我们并不是让边角具有某种特定的图形,而且即使添加上了图形,当元素尺寸变化时,图形也会发生形变。如果你稍微尝试一下,就会理解使用 border-image 是无法实现效果的,那么我们应该怎么办呢?

解决这个问题最简单的方法就是使用两个 HTML 标签:一个标签使用目标图片作为北京,两一个使用白色作为背景并覆盖在前一个标签上面:

<div class="something-meaningful">
    <div>
        I have a nice stone art border,
        don’t I look pretty?
    </div>
</div>

.something-meaningful {
    background: url(stone-art.jpg);
    background-size: cover;
    padding: 1em;
}
.something-meaningful > div {
    background: white;
    padding: 1em;
}

这种方法确实实现了下图的效果:

图片边框

但是它却需要添加额外的 HTML 标签。这只能算是一种折中的办法:它不仅仅混合了表现和样式,而是在某些情况下必须修改 HTML 结构。那么我们是否可以只用一层标签就实现这个效果呢?

解决方案

值得庆幸的是,CSS 的渐变以及在 Backgrounds & Borders Level 3 中扩展后的 background 属性可以帮助我们实现这一个效果,而且是只用一个标签。这种方法的核心就是使用纯色覆盖背景图片。不过,为了让第二章图片装饰到边框上,我们需要为 backgroud-clip 属性配置不同的属性值。最后一件事就是让最底下的图层只有一种颜色,所以我们需要通过 CSS 渐变模拟一个纯白色背景。

我们最初实现这个方法的代码就像下面一样:

padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
            url(stone-art.jpg);
background-size: cover;
background-clip: padding-box, border-box;

图片边框

图注:第一次的尝试非常接近理想效果。

正如上图所示,效果非常接近我们的目标了,唯一的不足是多了一些重复的部分。其中的原因就是 backgroud-origin 属性的默认值为 padding-box,因此,图片会定位到内边距盒模型的左上角,剩余的部分就会不断平铺这一图片。为了矫正这一效果,我们需要将 background-origin 的属性值修改为 border-box

padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
            url(stone-art.jpg);
background-size: cover;
background-clip: padding-box, border-box;
background-origin: border-box;

这些新属性也可以统一使用 background 简写语法来声明,从而让我们的代码更加简洁优雅:

padding: 1em;
border: 1em solid transparent;
background:
    linear-gradient(white, white) padding-box,
    url(stone-art.jpg) border-box 0 / cover;

当然,我们也可以将这一技巧应用到和渐变相关的背景图案上。比如,看一看下面的这些代码,我们可以用它来生成信封风格的边框:

padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white) padding-box,
            repeating-linear-gradient(-45deg,
              red 0, red 12.5%,
              transparent 0, transparent 25%,
              #58a 0, #58a 37.5%,
              transparent 0, transparent 50%)
0 / 5em 5em;

最终结果如图所示:

图片边框

图注:我们实现的怀旧信封边框

现在,你可以使用 background-size 随意修改条纹的宽度,也可以使用 border 随意修改边框的宽度。不同于前一个示例,这种效果是可以使用 border-image 来实现的:

padding: 1em;
border: 16px solid transparent;
border-image: 16 repeating-linear-gradient(-45deg,
                   red 0, red 1em,
                   transparent 0, transparent 2em,
                   #58a 0, #58a 3em,
                   transparent 0, transparent 4em);

不过,使用 border-image 会遇到几个问题:

  • 每次修改 border-width 的时候,同时需要修改 border-image-slice
  • 因为不能在 border-image-slice 中使用类似 em 的单位,所以我们只能对边框宽度使用像素单位
  • 条纹的宽度需要硬编码到颜色过渡点上,那么当需求变化时就需要修改四个地方的代码

这种技巧的另一种有趣应用就是创建一个类似选区的边框(marching ants borders)。选区型边框(译者:之所以称之为选区型,是因为效果非常类似 ps 中选区边框的效果,更容易理解)是虚线边框,而且虚线是实时滚动的,非常类似行进中的蚂蚁(当然,这需要一定的想象力将虚线想象为蚂蚁)。这在 GUI 中几乎是不可想象的效果。图像编辑软件通常使用这种边框来表示这是一块被选中的区域,简称选区。

图片边框

图注:选区型边框在 Adobe Photoshop 中被用来标志被选中的地方

为了创建这种边框,我们将要使用前面创建信封边框的技巧。首先是将条纹更改为黑白两色,并且将边框调整为 1px 的宽度(你注意到现在条纹是怎样变化为虚线边框的了吧?),然后适当修改一个 background-size,最后为 background-size 添加动画效果(从初始值增加到 100%):

@keyframes ants { to { background-position: 100% } }
.marching-ants {
    padding: 1em;
    border: 1px solid transparent;
    background:
        linear-gradient(white, white) padding-box,
        repeating-linear-gradient(-45deg,
          black 0, black 25%, white 0, white 50%
        ) 0 / .6em .6em;
    animation: ants 12s linear infinite;
}    

现在,你可以从下图中看到一个静态的效果。

图片边框

图注:在纸上显示选区型边框是不可能的,可以访问在线示例进行查看——非常有意思!

显然,这种技巧不仅仅对选区型边框有用,只需修改一下边框颜色和虚线之间的间距,就可以用来创建各种自定义的虚线边框。

目前,如果想要使用 border-image 属性实现类似的效果,那么就只能使用 border-image-source 添加 GIF 来模拟了,详情见 Marching ants animated selection rectangle in CSS。当浏览器广泛支持渐变效果之后,我们就可以用渐变来创建这种效果了,而且代码会更加简练优雅。

图片边框

图注:顶部剪切过得边框,用来模拟传统书籍中的脚注

不过,border-image 也是非常强大的属性,甚至有时比渐变更强大。比如,假设我们需要一个裁剪过的顶部边框,就像常见的脚注样式。那么只需要使用 border-image和垂直渐变就可以实现,其中裁剪的长度可以硬编码实现。边框的宽度则有 border-width 来控制。代码就像是这样:

border-top: .2em solid transparent;
border-image: 100% 0 0 linear-gradient( 90deg, 
            padding-top: 1em;
            currentColor 4em,
transparent 0);

最终结果如上图所示。此外,因为我们在这里使用 em 单位,所以整体效果就能随字体大小而变化;因为使用了 currentColor,所以它也可以随字体颜色而改变颜色。

总结

在CSS2.1的时代要实现图片边框效果是一种奢侈的想法,但在CSS3中虽然增加了border-image属性实现图片边框,但依旧受到诸多的限制性,其中最大的限制就是浏览器对其支持度。在这一节中,我们介绍了使用多背景,以及配合background-clipbackground-origin属性模拟出图片边框效果。

如需转载,烦请注明出处:http://www.w3cplus.com/css3/css-secrets/continuous-image-borders.htmljordans for sale footlocker

返回顶部