如何在某些区域制作单个 运行-of-text 并在其他区域制作实体填充?
How can I make a single run-of-text outlined in some areas and a solid-fill in other areas?
我最近遇到了这个 dribbble/landing page concept with hollow/filled text。
首先,我不完全确定这个概念是否可以在 CSS 中重新创建。
Google 确实让我找到了 CSS 文本掩码,但我找不到任何 post 可以真正重现这种效果。
我如何重建 hollow/filled 文本,具体取决于文本背后的背景是否有图像?
可以在pure-HTML+CSS中完成(没有任何SVG)。
- 它也可以在纯 SVG 中完成。
- SVG-only 选项会更简单,因为 SVG 具有更强大的混合和遮罩功能,HTML 元素(CSS 框)(CSS 框)目前还不能使用这些功能.
我决定为 HTML+CSS 做这件事,因为我觉得这是一个挑战。
- 这个 HTML 版本是动画的,文本是完全可选的。
- 这个HTML+CSS版本可以进一步简化by using
mask-image: element(#target)
which意味着我们不需要mask-only文本,不幸的是 Chrome 似乎还不支持 element()
(但是 Firefox 支持)。
一个小 wart 是 text-stroke
轮廓不完全 line-up 纯白色文本(至少在 Chrome 在 Windows 10 上,我的计算机版本 Helvetica
为 96dpi,但在同一浏览器和计算机中为 192dpi(2x,又名 Retina))看起来很完美。
以下是它在我的机器上以 96dpi 分辨率查看动画中不同点的方式:
下面的示例实现适用于以下浏览器(在撰写本文时):
- Chrome 98
- 边 98
- 火狐 97
- macOS Safari 技术预览(第 137 版)
- 它有点 在 macOS Safari 15.2 中工作,但由于某些原因你必须先点击它。
- 它在 iOS Safari 15.1 中不起作用(只有轮廓文本可见,实心文本根本不呈现)。
- 因为它 确实 在 Safari 预览浏览器中工作,所以它应该在 iOS Safari 和 macOS Safari 的下一次更新中工作,但是。
body {
background-color: #dbdac2;
--solid-white: linear-gradient(white,white);
}
#container,
#container > #div1 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-size:
153px 302px,
148px 302px,
154px 302px;
background-position:
131px 94px,
309px 28px,
480px 94px;
background-repeat:
no-repeat,
no-repeat,
no-repeat;
animation: moveImages 2s infinite;
animation-direction: alternate;
}
#container {
border: 1px solid white;
position: relative;
width: 711px;
height: 440px;
/* These are the 3 photo images, rendered as separate background-image layers: */
background-image:
url( "https://i.stack.imgur.com/hmwyh.png" ),
url( "https://i.stack.imgur.com/JeHEg.png" ),
url( "https://i.stack.imgur.com/pVgz6.png" );
}
#container p {
margin: 0;
position: static;
padding-top: 192px;
padding-left: 62px;
overflow: hidden;
font-family: Helvetica;
font-size: 99px;
letter-spacing: -2px;
font-weight: 600;
}
#container > #pStroke {
text-stroke: 1px white;
-webkit-text-stroke: 1px white;
color: transparent;
}
#container > #div1 {
/* #div1's background-image layers must match #container's: */
background-image:
var(--solid-white),
var(--solid-white),
var(--solid-white);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
@keyframes moveImages {
/* The `@keyframes from {}` rule is optional, btw. */
to {
background-size:
53px 302px,
58px 302px,
154px 302px;
background-position:
431px 94px,
209px 28px,
280px 194px;
}
}
<div id="container">
<div id="div1">
<p id="pWhite">Fashion Give<br />Impression.</p>
</div>
<p id="pStroke">Fashion Give<br />Impression.</p>
</div>
解释:
div#container
元素有一个 background-image
属性 设置为 3 个不同的来源图像(使用模因图像代替您发布的示例中的时尚照片) .
- 这些图像可以通过
background-size
和 background-position
属性独立定位和缩放。
另一个元素(#div1
)通过absolute
定位覆盖div#container
并且具有相同的background-size
和background-position
属性,但是使用单个纯白色背景图像(来自 linear-gradient(white,white)
)而不是照片,然后这 3 个白色背景图像层被 #div1
的内部 <p>
文本使用 background-clip: text;
.
- 这个例子必须使用
background-image: linear-gradient
(或background-image: url("1x1px-white.png");
)而不是background-color: white;
,因为它需要在3个不同的层中重复,而 background-color: white;
不能用于定义背景内的矩形区域,也不能有 多个 background-color
层(即使 semi-transparent)。
- 该示例还必须使用DOM文本来遮盖白色矩形——而不是使用白色矩形来遮盖DOM文本——因为CSS-in-HTML 不支持任何类型的 reversed 文本掩码,否则这会容易得多。不过,我相信这在 SVG 中很容易实现。
#div1
的 <p>
元素用于通过仅使用其内部 padding
而不是 position: absolute;
来正确定位文本,因为定位的文本不能与 background-clip: text;
,不幸的是。
带有文本副本的另一个 <p>
元素用于描边文本(text-stroke: 1px white;)
虽然文本内容在 HTML 源中被复制,但 3 个图像(及其各自的白色蒙版)的更繁琐的大小和位置信息不需要被复制到CSS,还好;感谢 CSS 的选择器如何工作(因为 #container
和 #div1
的 background-size
和 background-position
属性由单个 CSS 规则设置).
可能的替代方法:
不是为纯白色部分使用重复的相同大小的 background-image
层,而是单个(但非常复杂)clip-path
跟踪 3 个框(就像一条线画得像 etch-a-sketch) 可以用在 #pWhite
上,但这不可能是可动画的。
我认为最好的方法是这样的:
- 为 3 张照片使用 3 个单独的
<img />
元素(而不是 background-image
)并在新的 <div id="images">
. 中使用 absolute
定位
- 然后纯白色文本
<p>
(在 div#images
的兄弟元素中)将 absolute
-ly 定位在 div#images
之上 z-index
并用 mask-image: element(#images);
掩盖
- 但是Chrome似乎不支持在HTML+CSS中使用
element()
,据我所知只有Firefox支持。
- 描边文本将作为重复的
<p>
元素保留在 div#images
后面。
- 这种方法的另一个优点是
<img/>
元素s 可以使用 transform: translate
定位,而不必通过 background-position
或 position: absolute
来定位,这会产生更好的性能和帧率。
不过,我想不出任何不需要复制文本内容的方法 - 至少直到 CSS 的 content:
属性允许元素从其他元素复制文本。
我最近遇到了这个 dribbble/landing page concept with hollow/filled text。
首先,我不完全确定这个概念是否可以在 CSS 中重新创建。 Google 确实让我找到了 CSS 文本掩码,但我找不到任何 post 可以真正重现这种效果。
我如何重建 hollow/filled 文本,具体取决于文本背后的背景是否有图像?
可以在pure-HTML+CSS中完成(没有任何SVG)。
- 它也可以在纯 SVG 中完成。
- SVG-only 选项会更简单,因为 SVG 具有更强大的混合和遮罩功能,HTML 元素(CSS 框)(CSS 框)目前还不能使用这些功能.
- 它也可以在纯 SVG 中完成。
我决定为 HTML+CSS 做这件事,因为我觉得这是一个挑战。
- 这个 HTML 版本是动画的,文本是完全可选的。
- 这个HTML+CSS版本可以进一步简化by using
mask-image: element(#target)
which意味着我们不需要mask-only文本,不幸的是 Chrome 似乎还不支持element()
(但是 Firefox 支持)。
一个小 wart 是
text-stroke
轮廓不完全 line-up 纯白色文本(至少在 Chrome 在 Windows 10 上,我的计算机版本Helvetica
为 96dpi,但在同一浏览器和计算机中为 192dpi(2x,又名 Retina))看起来很完美。以下是它在我的机器上以 96dpi 分辨率查看动画中不同点的方式:
下面的示例实现适用于以下浏览器(在撰写本文时):
- Chrome 98
- 边 98
- 火狐 97
- macOS Safari 技术预览(第 137 版)
- 它有点 在 macOS Safari 15.2 中工作,但由于某些原因你必须先点击它。
- 它在 iOS Safari 15.1 中不起作用(只有轮廓文本可见,实心文本根本不呈现)。
- 因为它 确实 在 Safari 预览浏览器中工作,所以它应该在 iOS Safari 和 macOS Safari 的下一次更新中工作,但是。
body {
background-color: #dbdac2;
--solid-white: linear-gradient(white,white);
}
#container,
#container > #div1 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-size:
153px 302px,
148px 302px,
154px 302px;
background-position:
131px 94px,
309px 28px,
480px 94px;
background-repeat:
no-repeat,
no-repeat,
no-repeat;
animation: moveImages 2s infinite;
animation-direction: alternate;
}
#container {
border: 1px solid white;
position: relative;
width: 711px;
height: 440px;
/* These are the 3 photo images, rendered as separate background-image layers: */
background-image:
url( "https://i.stack.imgur.com/hmwyh.png" ),
url( "https://i.stack.imgur.com/JeHEg.png" ),
url( "https://i.stack.imgur.com/pVgz6.png" );
}
#container p {
margin: 0;
position: static;
padding-top: 192px;
padding-left: 62px;
overflow: hidden;
font-family: Helvetica;
font-size: 99px;
letter-spacing: -2px;
font-weight: 600;
}
#container > #pStroke {
text-stroke: 1px white;
-webkit-text-stroke: 1px white;
color: transparent;
}
#container > #div1 {
/* #div1's background-image layers must match #container's: */
background-image:
var(--solid-white),
var(--solid-white),
var(--solid-white);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
@keyframes moveImages {
/* The `@keyframes from {}` rule is optional, btw. */
to {
background-size:
53px 302px,
58px 302px,
154px 302px;
background-position:
431px 94px,
209px 28px,
280px 194px;
}
}
<div id="container">
<div id="div1">
<p id="pWhite">Fashion Give<br />Impression.</p>
</div>
<p id="pStroke">Fashion Give<br />Impression.</p>
</div>
解释:
div#container
元素有一个background-image
属性 设置为 3 个不同的来源图像(使用模因图像代替您发布的示例中的时尚照片) .- 这些图像可以通过
background-size
和background-position
属性独立定位和缩放。
- 这些图像可以通过
另一个元素(
#div1
)通过absolute
定位覆盖div#container
并且具有相同的background-size
和background-position
属性,但是使用单个纯白色背景图像(来自linear-gradient(white,white)
)而不是照片,然后这 3 个白色背景图像层被#div1
的内部<p>
文本使用background-clip: text;
.- 这个例子必须使用
background-image: linear-gradient
(或background-image: url("1x1px-white.png");
)而不是background-color: white;
,因为它需要在3个不同的层中重复,而background-color: white;
不能用于定义背景内的矩形区域,也不能有 多个background-color
层(即使 semi-transparent)。 - 该示例还必须使用DOM文本来遮盖白色矩形——而不是使用白色矩形来遮盖DOM文本——因为CSS-in-HTML 不支持任何类型的 reversed 文本掩码,否则这会容易得多。不过,我相信这在 SVG 中很容易实现。
#div1
的<p>
元素用于通过仅使用其内部padding
而不是position: absolute;
来正确定位文本,因为定位的文本不能与background-clip: text;
,不幸的是。
- 这个例子必须使用
带有文本副本的另一个
<p>
元素用于描边文本(text-stroke: 1px white;)
虽然文本内容在 HTML 源中被复制,但 3 个图像(及其各自的白色蒙版)的更繁琐的大小和位置信息不需要被复制到CSS,还好;感谢 CSS 的选择器如何工作(因为
#container
和#div1
的background-size
和background-position
属性由单个 CSS 规则设置).
可能的替代方法:
不是为纯白色部分使用重复的相同大小的
background-image
层,而是单个(但非常复杂)clip-path
跟踪 3 个框(就像一条线画得像 etch-a-sketch) 可以用在#pWhite
上,但这不可能是可动画的。我认为最好的方法是这样的:
- 为 3 张照片使用 3 个单独的
<img />
元素(而不是background-image
)并在新的<div id="images">
. 中使用 - 然后纯白色文本
<p>
(在div#images
的兄弟元素中)将absolute
-ly 定位在div#images
之上z-index
并用mask-image: element(#images);
掩盖
- 但是Chrome似乎不支持在HTML+CSS中使用
element()
,据我所知只有Firefox支持。 - 描边文本将作为重复的
<p>
元素保留在div#images
后面。 - 这种方法的另一个优点是
<img/>
元素s 可以使用transform: translate
定位,而不必通过background-position
或position: absolute
来定位,这会产生更好的性能和帧率。
absolute
定位- 为 3 张照片使用 3 个单独的
不过,我想不出任何不需要复制文本内容的方法 - 至少直到 CSS 的
content:
属性允许元素从其他元素复制文本。