如何在某些区域制作单行文本概述,而在其他区域制作实心填充?

Raz*_*zón 2 css css-mask

我最近遇到了带有空心/填充文本的运球/登陆页面概念

在此输入图像描述

首先,我不完全确定这个概念是否可以在 CSS 中重新创建。谷歌确实让我找到了 CSS 文本蒙版,但我找不到任何可以真正重现这种效果的帖子。

我如何能够重建空心/填充文本,具体取决于文本后面的背景是否有图像?

Dai*_*Dai 5

  • 它可以用纯 HTML+CSS 完成(无需任何 SVG)。

    • 也可以用纯 SVG 来完成。
      • 仅 SVG 选项会更简单,因为 SVG 具有更强大的混合和遮罩功能,但 HTML 元素(CSS 框)尚无法使用这些功能。
  • 我决定为 HTML+CSS 做这件事,因为我觉得这是一个挑战。

    • 该 HTML 版本是动画的,并且文本是完全可选的。
    • 这个 HTML+CSS 版本可以通过使用mask-image: element(#target)进一步简化,这意味着我们不需要仅遮罩文本,不幸的是 Chrome 似乎还不支持element()(但 Firefox 确实支持)。
  • 一个小问题text-stroke轮廓与纯白色文本不完全对齐(至少在 Windows 10 上的 Chrome 中,我的计算机版本为Helvetica96dpi,但在同一浏览器和计算机中为 192dpi(2x,又名Retina ))看起来很完美。

  • 以下是我的机器上 96dpi 下动画中不同点的外观:

  • 下面的示例实现适用于以下浏览器(在撰写本文时):

    • 铬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;
    }
}
Run Code Online (Sandbox Code Playgroud)
<div id="container">

  <div id="div1">
    <p id="pWhite">Fashion Give<br />Impression.</p>
  </div>
  
  <p id="pStroke">Fashion Give<br />Impression.</p>

</div>
Run Code Online (Sandbox Code Playgroud)

解释:

  • div#container元素的background-image属性设置为 3 个不同的源图像(使用 meme 图像代替您发布的示例中的时尚照片)。

    • 这些图像可以通过background-sizebackground-position属性独立定位和缩放。
  • 另一个元素 ( #div1)div#container通过absolute定位进行叠加,并具有相同的background-sizebackground-position属性,但使用单个纯白色背景图像(来自 a )而不是照片,然后使用的内部文本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图层(即使是半透明的)。
    • 该示例还必须使用 DOM 文本来屏蔽白色矩形 - 而不是使用白色矩形来屏蔽 DOM 文本 - 因为 CSS-in-HTML 不支持任何类型的反向文本屏蔽,否则这会容易得多。不过,我相信这在 SVG 中是很容易实现的。
    • #div1<p>元素用于通过仅使用其内部padding而不是正确定位文本position: absolute;,因为不幸的是,定位的文本不能与 一起使用background-clip: text;
  • 带有文本副本的另一个<p>元素用于描边文本(带有text-stroke: 1px white;)

  • 虽然文本内容在 HTML 源中重复,但幸运的是,3 个图像(及其各自的白色蒙版)的更复杂的大小和位置信息不需要在 CSS 中重复;这要归功于 CSS 选择器的工作方式(因为#container和都由单个 CSS 规则设置#div1它们的background-size和属性)。background-position

可能的替代方法:

  • 可以使用background-image单个(但非常复杂)clip-path跟踪 3 个框(就像蚀刻草图一样绘制的单线),而不是对纯白色部分使用重复的相同大小的图层#pWhite,但这不太可行。

  • 我认为最好的方法是这样的:

    • <img />对 3 张照片使用 3 个独立的元素(而不是background-image),并absolute在新的<div id="images">.
    • 然后纯白色文本<p>(在 的同级元素中div#images)将被absolute-ly 定位在div#imagesby上z-index并用mask-image: element(#images);
    • element()但据我所知,Chrome似乎不支持在HTML+CSS中使用,只有Firefox支持。
    • 描边文本将保留为<p>位于 后面的重复元素div#images
    • 这种方法的另一个优点是<img/>可以使用元素来定位元素,transform: translate而不必通过background-position或者position: absolute这将产生更好的性能和帧速率。
  • 不过,我想不出任何不需要复制文本内容的方法——至少在 CSS 的content:属性允许元素从其他元素复制文本之前是这样。