- 原文地址:codrops
- 原文作者:Sara Soueidan
在本文中,我們將探討幾種可用於建立紋理文字或將背景應用於文字的小技巧。
請記住,本文中介紹的一些技術是實驗性的,瀏覽器支援非常低,在構建需要廣泛瀏覽器支援的實際專案時可能不是最好的實現。
我已經為每個演示提供了一個螢幕截圖,每個技術結束時也會有演示的連結。
影象應用於文字背景
-webkit-background-clip: text
我們將從CSS background-clip屬性開始,並使用它來獲得以下效果:
CSS background-clip屬性確定元素的背景繪製區域。 預設情況下,背景被裁切到border-box的邊框位置,它可以設定為其他值,如padding-box和content-box,這些都是不言自明的。
可以使用此屬性建立不同的效果,例如賦予元素透明邊框,在所有現代瀏覽器中都得到了很好的支援。
background-clip屬性在Webkit中使用第四個值text進行了擴充套件,這會使背景影象剪下為前景文字(包括裝飾和陰影)。 然後,通過使用僅Webkit屬性-webkit-text-fill-color為文字提供透明顏色,背景影象將通過文字顯示,從而完成剪下效果。
在撰寫本文時,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上建立了一個非常好的互動式逐步演示,它演示瞭如何製作文字漸變。 您可以檢視它以獲得有關此技術的更直觀的解釋。
mask-image: url()實現紋理文字
我們將要討論的以下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實現的結果是可以跨瀏覽器的,因此您可以使用SVG方法作為上述CSS屬性的非支援瀏覽器的回退。
使用SVG <clippath>剪下文字背景
首先,我們將使用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中使用模式填充文字。
使用SVG <pattern>來填充文字背景
因此,我們可以將背景或圖案應用於文字的另一種方法是使用圖案填充文字,而不是使用背景影象並將其剪下到文字。 對於本演示,我們將使用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剪下背景,就像我們在上一節中所做的那樣。
使用SVG <mask>將紋理應用於文字
就像我們可以使用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>建立紋理文字
我們將要討論的最後一種技術使用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絕對是我們的最佳選擇。
我希望你發現這篇文章很有用。 謝謝你的閱讀!=)
你知道在文字中新增紋理的其他技巧嗎? 如果有,請確保在下面的評論中分享!