在本文中,咱们将探讨几种可用于建立纹理文本或将背景应用于文本的小技巧。css
请记住,本文中介绍的一些技术是实验性的,浏览器支持很是低,在构建须要普遍浏览器支持的实际项目时可能不是最好的实现。html
我已经为每一个演示提供了一个屏幕截图,每一个技术结束时也会有演示的连接。java
-webkit-background-clip: textgit
咱们将从CSS background-clip属性开始,并使用它来得到如下效果: web
CSS background-clip属性肯定元素的背景绘制区域。 默认状况下,背景被裁切到border-box的边框位置,它能够设置为其余值,如padding-box和content-box,这些都是不言自明的。ajax
可使用此属性建立不一样的效果,例如赋予元素透明边框,在全部现代浏览器中都获得了很好的支持。canvas
background-clip属性在Webkit中使用第四个值text进行了扩展,这会使背景图像剪切为前景文本(包括装饰和阴影)。 而后,经过使用仅Webkit属性-webkit-text-fill-color为文本提供透明颜色,背景图像将经过文本显示,从而完成剪切效果。api
在撰写本文时,background-clip属性的文本值不是任何标准的一部分,所以不幸的是它只能在WebKit浏览器中工做,而且能够为其余浏览器提供简单的CSS回退,或者使用polyfill提供其余后备。浏览器
如今,咱们将使用-webkit-background-clip属性建立一个带背景的文本,并提供一个仅CSS的回退,它将在非WebKit浏览器的文本下显示图像。
对于咱们的演示(如上面的屏幕截图所示),咱们有一个有背景的元素,它内部有一个标题,咱们想要剪切其背景,使其看起来好像背景仅应用于其中的标题文本。
<div class="container">
<!-- the element whose background we're going to clip --> <div class="clipped"> <h1>CO<br/>OK</h1> </div> <!-- arbitrary content --> <p><span>The #1 cooking magazine in the world.</span> New healthy and delicious recipes every week. Subscribe to the weekly issue of COOK magazine and stay up-to-date on the latest kitchen trends and tips anc tricks from the world's #1 chefs. <br/>
Download our app available for Android, iOS and Windows phones.</p>
</div>
复制代码
咱们将使用“宽字体”,以便经过文本更清晰地看到背景。 .clipped元素将得到一个背景图像,咱们将background-clip的属性值设置为text来剪切文本。 咱们要将文本颜色设置为白色,由于非WebKit浏览器会在图像顶部显示文本,咱们须要选择在咱们选择的背景上可读的字体颜色。 而后咱们将文本的填充颜色设置为透明,这将覆盖WebKit浏览器中的白色文本颜色,以便背景图像能够显示。
.clipped {
background: url(../img/kitchen.jpg) no-repeat center center;
background-size: cover;
color: #fff;
text-align: center;
padding: 2em;
/* -webkit-background-clip clips the background of the element to the text */
-webkit-text-fill-color: transparent; /* overrides the white text color in webkit browsers */
-webkit-background-clip: text;
}
复制代码
查看demo1:使用background-clip属性实现文本背景
若是您在非WebKit浏览器中查看演示,您将在背景图像上看到白色文本。
在非WebKit浏览器中显示不透明文本背后的背景图像多是图像在传达可视消息中起重要做用的最佳后备,但若是您在背景中没有图像,也能够回退到常规文本。 Divya Manian撰写了一篇很好的文章,解释了如何实现常规文本后备,Rachel Nabors根据Divya的代码建立了一个Sass mixin,而且已经在Codepen上提供,若是你愿意的话也可使用它。
如今,就像咱们将图像背景应用于文本同样,您也能够应用渐变背景。 由于CSS中的渐变是图像,因此能够对上面的.clipped元素应用渐变,结果将是具备渐变背景的文本。Riza SelçukSaydam在Codepen上建立了一个很是好的交互式逐步演示,它演示了如何制做文本渐变。 您能够查看它以得到有关此技术的更直观的解释。
咱们将要讨论的如下CSS技术目前仅在WebKit浏览器中支持(请参阅此处的支持表),并带有-webkit前缀。
咱们将使用CSS mask来建立漂亮的纹理文本效果。 CSS Masking是一个W3C工做草案,但愿不久以后其余浏览器也会开始实现它。
但就目前而言,咱们将建立一个目前仅适用于WebKit浏览器的演示,而且咱们将为不支持的浏览器提供简单的后备。 咱们将使用CSS的mask-image属性将splatter效果应用于文本以得到以下结果:
当咱们使用CSS masks,时,咱们正在使文本采用其蒙版图像的形状,而不是像上面的背景剪辑技术那样使图像采用文本的形状。
mask-image属性采用如下三个值之一:具备Alpha不透明度的图像,其中透明区域将是不显示内容的区域,CSS渐变或无。 对于咱们的演示,咱们将使用具备alpha不透明度的图像,以下所示:
图像表明了一堆咱们想要应用于文本的油漆泼溅物,使文字看起来像是上面有一些水彩颜料。 不支持的浏览器只会显示文本而不会应用泼溅效果。
将此蒙版应用于文本或任何其余内容时,文本将显示在黑色喷溅的位置,而蒙版图像是透明的部分,文本将不会显示。 您能够将文本(或内容)想象为图层,将蒙版想象为另外一个图层,而后想象将蒙版图像放在文本顶部,而后获取橡皮擦并开始删除未覆盖的文本的全部部分 经过那些黑点,你将最终获得掩盖的文本,如上面的演示截图所示。
为了使效果更逼真,我在包含该文本的元素中添加了水彩背景,该文本将经过文本显示“已删除”,所以很好地将文本与其背景混合。 全部这一切,仅使用CSS。 挺整洁的吧? 目前浏览器支持太糟糕了。 可是咱们将在下一节从新讨论这种效果以跨浏览器工做。
如今,对于咱们的演示,咱们有一个包含两个标题的容器:
<div class="container> <h1>Art</h1> <h2>Digital Magazine</h2> </div> 复制代码
咱们将splatter效果应用于h1元素。 这是相关CSS:
.container h1 {
font: 35em/100% "Oswald", sans-serif;
margin: 0 auto;
padding: 0;
text-align: center;
color: #fff;
/* the property that creates the splatter effect */
-webkit-mask-image: url(../img/splatter-mask_1.png);
mask-image: url(../img/splatter-mask_1.png);
}
复制代码
这就是实现这种效果所需的一切。 如今,固然你会想要添加一些额外的样式,就像我在演示中所作的那样,这取决于你所经历的总体效果,可是当你使用蒙版为文本添加纹理时,一行CSS是很是重要的。
这里要注意的一件重要事情是,当在其余浏览器中实现此属性时,-webkit-前缀多是也可能不是您须要的惟一前缀。 在编写本文时,您须要为此添加-webkit-前缀,若是您在项目中使用此技术,请确保在规范或浏览器支持该属性时更新代码。
查看demo2 mask-image: url()实现纹理文本
该演示将在不支持的浏览器中显示常规的文本。
您能够在W3C规范中阅读有关CSS Masking的更多信息,并在Trent Walton的这篇文章中查看另外一个细微纹理文本示例。
上面的两种效果均可以使用SVG从新实现,使用SVG实现的结果是能够跨浏览器的,所以您可使用SVG方法做为上述CSS属性的非支持浏览器的回退。
首先,咱们将使用SVG的
剪切路径肯定要应用背景的形状或区域。 背景中位于定义形状以外的部分将不会被绘制,而且只有给定形状内的部分才会被绘制。
剪切路径能够采用多个值,其中一个是
一旦定义了剪切路径(咱们将马上获得代码),可使用clip-path引用该路径,做为咱们想要剪辑的图像的属性,或者做为该图像的CSS属性。
让咱们首先定义咱们想要用来剪辑图像的剪辑路径,在咱们的例子中,这只是咱们想要显示背景图像的单个单词。
首先,咱们建立一个包含全部SVG代码的SVG元素。 而后咱们将定义剪辑路径并经过clip-path属性将其应用于图像元素:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1200" height="400" viewBox="0 0 1200 400">
<!-- add title for accessibility -->
<title>Adding Background to Text using SVG clipPath</title>
<defs>
<clippath id="my-path">
<text x="50" y="300" font-size="200" >WATERCOLOR</text>
</clippath>
</defs>
<image xlink:href="img/watercolor_1.jpg" clip-path="url(#test)" width="100%" height="100%" preserveAspectRatio="none" />
</svg>
复制代码
由于SVG元素基本上是图形,因此请确保包含标题,以便屏幕阅读器能够访问它。
在上面的代码中,咱们建立了一个文本元素,给定了字体大小,并定义了x和y坐标,这些坐标肯定了在SVG中绘制文本的位置。 而后,咱们将咱们的文本元素放在clippath元素中,咱们已经给出了一个ID,以便咱们可以引用它。 而后,咱们将clippath元素放在defs元素中。 defs元素可用于存储不直接显示的内容。 而后,这些存储的隐藏内容能够被其余SVG元素引用和显示,这使得它很是适合包含可重用图形的模式。 在咱们的例子中,它很是适合定义咱们想要在图像属性中引用剪辑路径的目的。
接下来,咱们添加了咱们的图像,给它一个宽度和一个高度,并将preserveAspectRatio设置为none,这样它的宽高比就不会被锁定,由于若是不这样,那么它们的高度和宽度都不会应用。
最后,咱们使用图像上的clip-path属性引用了咱们定义的剪切路径。 clip-path属性将clippath元素的ID做为其值,并将剪切路径应用于图像。
您能够经过使用CSS应用它,而不是使用clip-path属性引用剪辑路径,以下所示:
image {
clip-path: url(#my-path);
}
复制代码
这应该在全部现代浏览器中均可以正常展现:Chrome,Safari,Opera,Firefox和IE9 +。 因此,若是你想使用CSS background-clip:text; 例如,你可使用Modernizr检查浏览器对background-clip:text的支持,并提供SVG做为非支持浏览器的后备,这是Tim Pietrusky的polyfill所作的,相比使用背景 图像并使用clippath剪切它,使用SVG模式可以更好的实现剪辑的图像填充文本背景。 在下一节中,咱们将在SVG中使用模式填充文本。
所以,咱们能够将背景或图案应用于文本的另外一种方法是使用图案填充文本,而不是使用背景图像并将其剪切到文本。 对于本演示,咱们将使用SubtlePatterns提供的图案填充文本。
当你使用装饰字体时,使用图像并将其剪切为文本多是一个很好的选择,就像咱们在第一个演示中所作的那样,或者咱们想用一个大的图像做为文本的背景,由于这个背景扮演了一个重要的角色。 但有时候,咱们想要作的只是在文本中添加一个简单而细微的模式,使其具备额外的美妙触感,使其不那么沉闷。 在这种状况下,使用SVG,咱们能够像在上一节中定义剪切路径同样定义模式,而后咱们可使用该模式填充文本。
与以前的演示相似,咱们有一个SVG元素,其中为可访问性添加了标题,咱们想要用模式填充的文本元素,以及咱们将用于定义模式的defs元素。 该模式由一个图像组成,并具备一个ID,当咱们想要引用它并将其应用于咱们的文本时,咱们将使用该ID。 咱们将在文本的fill属性中引用模式,或者经过文本的CSS fill属性引用模式。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="700" height="400" >
<!-- add title for accessibility -->
<title>Applying a patterned background to text in SVG</title> -->
<!-- Source: http://lea.verou.me/2012/05/text-masking-the-standards-way/ -->
<defs>
<pattern id="filler" patternUnits="userSpaceOnUse" width="400" height="400" >
<image xlink:href="img/purty_wood.png" width="1200" height="600" preserveAspectRatio="none" />
</pattern>
</defs>
<text x="100" y="70%" font-size="200" fill="url(#filler)">WOOD</text>
</svg>
复制代码
与以前的演示相似,您能够经过CSS引用模式,以下所示:
text {
fill: url(#filler);
}
复制代码
查看demo4,支持全部现代浏览器:使用SVG填充文本背景。
此时,值得注意的是,您不只能够将图像用做SVG模式,并且正如咱们以前提到的那样,渐变也是图像,您还能够建立SVG渐变并使用它来填充文本,而不是:
在SVG中建立和使用渐变很简单。 渐变被建立为radialGradient或linearGradient元素,并被赋予一个ID,而后在fill属性或CSS属性中引用,就像咱们使用上面的
固然,也能够将渐变设置为容器的背景图像,而后咱们可使用clippath剪切背景,就像咱们在上一节中所作的那样。
就像咱们可使用CSS mask-image属性将图像蒙版应用于元素同样,咱们也能够应用相同的蒙版概念并使用SVG蒙版得到相同的效果。
图像的不透明和透明区域将决定元素的绘制位置,就像咱们在上一节中使用CSS mask-image属性看到的那样。 可是,CSS图像蒙版和SVG图像蒙版之间存在一个重要区别:与CSS蒙版不一样,SVG蒙版使用蒙版中的亮度值来肯定被遮罩的内容,而不是阿尔法值。 所以,由黑色和透明区域组成的图像,例如咱们上面使用的喷溅遮罩,将必须被由白色和透明区域组成的图像替换。 所以,若是咱们要从新建立与上面建立的相同的泼溅文本效果,咱们将不得不使用以下所示的蒙版图像:
能够在Photoshop中轻松将Alpha通道图像蒙板转换为亮度图像蒙版,应用白色覆盖将黑色区域变为白色,这就是我用适合SVG蒙版的CSS图像蒙版替换CSS图像蒙版的方法。 在上面的图像中可见的浅灰色区域其实是透明的,我只是给了图像这个背景,因此你能够看到白色的飞溅,不然在这篇文章的白色背景上看不到。
如今,就像咱们定义SVG剪切路径和模式同样,咱们能够以相似的方式定义咱们的蒙版并将其应用于咱们的文本。
咱们将建立一个包含在SVG mask元素内的图像,该元素将得到一个ID以即可以引用它,而且mask将被包装在defs元素内,该元素用于定义咱们的蒙版而不直接渲染它。
因此它就像是说:咱们定义一个SVG mask,它是一个带有如下URL(上面的亮度mask的URL)的图像,而后咱们将这个mask应用到咱们的text元素上的mask属性,固然也可使用mask属性的CSS。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="380" >
<!-- add title for accessibility -->
<title>Adding Texture to Text using SVG Masks</title>
<defs>
<mask id="mask">
<image width="1200px" height="1200px" xlink:href="img/splatter-mask_luminance.png" preserveAspectRatio="none"/>
</mask>
</defs>
<text x="50" y="70%" font-size="168" fill="white" mask="url(#mask)">WATERCOLOR</text>
</svg>
复制代码
为了完成效果,我将水彩背景添加到主svg元素,使其看起来像文本被混合到该背景中。
咱们将要讨论的最后一种技术使用HTML5 <canvas>元素来建立上述效果。 使用<canvas>,您还能够将元素“剪切”为另外一个元素的形状,使用纹理“填充”文本,并经过更改画布的context的 globalCompositeOperation属性的值,将相似蒙版的效果应用于文本。
在咱们了解它以前,让咱们定义咱们的标记,由于它与咱们将要介绍的3种技术的标记相同。
咱们有一个canvas元素,咱们为其指定高度和宽度,在结束标记以前,咱们将添加一个文本内容,供屏幕阅读器阅读,以及禁用JavaScript的浏览器回退。 但须要注意的是,当JavaScript被禁用时,Firefox不会将文本显示为画布的后备,这多是一个错误。
<canvas id="canvas" width=1000 height=600 >
WATER
</canvas>
复制代码
如今咱们准备好了标记,让咱们开始绘制一些带纹理的文本!
对于咱们的第一个演示,咱们将在画布上建立一个文本,并使用咱们选择的模式填充它以得到如下结果:
咱们将得到canvas元素及其绘图context,而后咱们将建立一个图像,并将该图像用做文本的填充样式。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//create image we're going to use as a fill pattern var img = document.createElement("img"); img.src="img/water.jpg"; //draw the text img.onload= function(){ drawText(); } //function that draws the text and fills it with the texture from the img function drawText() { ctx.font = "bold 200pt Oswald"; ctx.fillStyle = ctx.createPattern(img, 'repeat'); ctx.textAlign = 'center'; var x = canvas.width / 2; ctx.fillText("WATER", x, 400); ctx.fill(); } 复制代码
那么,让咱们回顾一下上面的代码。 全部绘图都发生在drawText函数中。 咱们将在context的font属性中定义字体样式,而后使用context的createPattern方法,咱们将从以前建立的图像中建立一个模式,而后咱们将该模式设置为 fillStyle属性的值,固然,它肯定字体的填充样式。 最后但并不是最不重要的是,咱们实际上将使用fillText方法在画布上绘制文本,该方法接收一个字符串,它是咱们想要绘制的文本的内容,以及一些x和y坐标, 正如您可能已经猜到的那样,肯定将在画布上绘制文本的位置。
这里有一点须要注意:当你在画布中使用自定义字体时,你可能没法看到自定义字体呈现,由于画布绘图可能在字体加载以前发生。要解决这个问题,您可使用字体加载器,如Typekit和Google开发人员开发的 Web Font Loader,并在加载字体后在画布上绘图:
WebFontConfig = {
google: { families: [ 'Oswald' ] },
fontactive: function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.src="img/water.jpg";
img.onload= function(){
drawText();
}
function drawText() {
ctx.font = "bold 200pt Oswald";
ctx.fillStyle = ctx.createPattern(img, 'repeat');
ctx.textAlign = 'center';
var x = canvas.width / 2;
ctx.fillText("WATER", x, 400);
}
}
};
(function() {
var wf = document.createElement('script');
wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
复制代码
演示文件都将使用这种技术,但我会在这里保持简单,只在下面的示例中向您展现该技术的相关功能。
如今,转到下一个技术,咱们将经过更改context的globalcompositeOperation属性的值在画布上建立相似剪辑的效果。 最终结果以下所示:
canvas context的附带属性globalcompositeOperation,它定义了所谓的“源”和“目标”之间的复合操做。也就是说,它定义了您想要绘制的内容将如何与在画布上绘制的内容混合。源是您要绘制的内容,目标是在设置globalCompositeOperation属性以前已经绘制的内容。咱们能够在现有形状后面绘制新元素或形状,并使用此属性清除某些区域,甚至从画布中清除部分。
globalCompositeOperation可使用16个值中的一个,这些值中的每个都在MDN的可视示例中清楚地展现,所以若是您还不熟悉此属性,请检查一下,由于这些示例将帮助您更好的理解。这是每一个值的结果的屏幕截图。在演示的源代码中,目标是首先在画布上绘制蓝色矩形,源是在设置globalCompositeOperation值后绘制的红色圆圈。
此属性的source-in值能够用简单的翻译为“仅绘制它们相交的源和目标的部分/区域”。 所以,若是您有两个元素,一个是已经绘制的,另外一个是您想要继续绘制的元素,那么结果将是只绘制这两个元素相交的区域。
为了更好地理解这一点,让咱们立刻进入代码。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.onload = function () {
drawText();
}
img.src="img/fire.jpg";
function drawText() {
// put text on canvas
ctx.font = "bold 180pt IM Fell Great Primer SC";
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
var x = canvas.width / 2;
ctx.fillText("FIRE", x, 325);
// use compositing to draw the background image only where the text has been drawn
ctx.globalCompositeOperation = "source-in";
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
}
复制代码
在上面的代码中,在drawText函数中,咱们有3个“sections”,用于定义将在画布上绘制的结果。 第一部分是咱们定义文本的地方,包括它的全部样式,而后咱们继续使用fillText方法绘制它。 接下来,咱们将context的globalCompositeOperation设置为source-in。 而后,咱们在画布上绘制图像。
因此你看,在这种状况下,“source”是咱们想要在设置globalCompositeOperation(图像)以后绘制的元素,而“destination”是咱们在设置它以前绘制的文本。 经过将值设置为source-in,咱们告诉浏览器仅在此图像与文本相交的区域中绘制图像,这正是咱们想要得到的效果。
一旦你了解globalCompositeOperation的每一个值,你能够快速轻松地开始使用它们,而且再次确保检查MDN上的可视化示例,由于它们有不少帮助。
当你检查它们时,你会注意到若是咱们将值设置为source-atop,结果对于咱们的演示也是同样的。 source-atop告诉浏览器绘制与目标(文本)相交的源(图像)的部分/区域,并绘制目标的其他区域,即便那些与源不相交的区域,也在咱们的 这种状况,也会产生咱们想要的效果。
注意:在撰写本文时,并不是全部浏览器都支持全局复合操做属性的全部值。
最后,咱们将使用canvas建立另外一个效果,但此次咱们将在文本中添加一些纹理以将其混合到背景中,就像咱们以前使用SVG和CSS的技术同样。 该演示将以下所示:
咱们将使用带有alpha通道的图像做为咱们的“蒙版”,咱们但愿仅在与图像的黑色区域相交的位置绘制文本,并在图像透明的地方“擦除”图像。 所以,咱们但愿咱们的源和目标只能在它们相交的地方绘制。 根据这个逻辑,以及globalCompositeOperation值的上述截图,咱们将要使用source-in值来获取咱们所追求的结果。
下面是咱们用做“蒙版”的图像。 黑色区域是图像与文本相交的位置。 就像咱们在CSS masking部分中所作的那样,您能够想象文本的一个图层和此图像的另外一个图层,将它们放在彼此的顶部,而后擦除图像或文本不相交的部分,相交的部分,就是想要得到的最终效果。
Javascript代码与上面的代码相同,只有globalCompositeOperation的值不一样,因此咱们将直接跳到演示,在那里您能够查看源代码并体验它。
在这里,咱们再次为画布添加了背景,使混合效果更加逼真。 咱们有“划痕”的背景和有划痕的文字很好地融合在一块儿。
我但愿你从这篇文章中学到了一两种新技术。 我认为咱们已经涵盖了使用CSS和HTML建立纹理文本的大多数可能方法。 我最喜欢的技术必须是SVG,由于它具备更普遍的浏览器支持。 当全部浏览器都支持CSS masks和background-clip的文本值时,咱们能够开始使用它们而没必要过度担忧提供回退,而后CSS绝对是咱们的最佳选择。
我但愿你发现这篇文章颇有用。 谢谢你的阅读!=)
你知道在文本中添加纹理的其余技巧吗? 若是有,请确保在下面的评论中分享!