我最近遇到了这个dribbble/landing page concept with hollow/filled text.

enter image description here

首先,我不完全确定这个概念是否可以在CSS中重新创建.

根据文本背后的背景是否有图像,我如何重建空心/填充文本?

推荐答案

  • 它可以在纯HTML+CSS(没有任何SVG)中完成.

    • 而且它也可以在纯SVG中完成.
      • 仅SVG选项将更简单,因为SVG具有HTML元素(CSS框)(尚不能)使用的更强大的混合和掩码功能.
  • 我决定使用HTML+CSS,因为我觉得这是一个挑战.

    • 此HTML版本是动画形式,文本完全可选.
    • 这个HTML+CSS版本can进一步简化了by using mask-image: element(#target) which意味着我们不需要只使用掩码的文本,不幸的是Chrome似乎还不支持element()(但Firefox支持).
  • warttext-stroke的轮廓与纯白文本不完全对齐(至少在我的电脑Helvetica版本为96dpi的Windows10的Chrome中,但在192dpi(2x,又名Retina))下,在相同的浏览器和电脑上它看起来很完美.

  • Here's how it looks at different points in the animation on my machine at 96dpi:

  • 下面的示例实现可在以下浏览器中运行(在编写本文时):

    • chromium 98
    • 边缘98
    • Firefox 97
    • MacOS Safari技术预览(版本137)
      • kinda可以在MacOS Safari 15.2中运行,但由于某些原因,您必须先单击它.
      • 它在iOS Safari 15.1中不起作用(只有轮廓文本可见,实心文本根本看不到).
      • 因为它does可以在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个不同的源图像(使用meme图像代替发布示例中的时尚照片).

    • 这些图像可以通过background-sizebackground-position属性独立定位和zoom .
  • 另一个元素(#div1)覆盖div#containerabsolute定位,并且具有相同的background-sizebackground-position属性,但是使用单个纯白背景图像(来自linear-gradient(white,white))而不是照片,然后这3个白色背景图像层被#div1的内部<p>的文本使用background-clip: text;遮蔽.

    • 此示例has to使用background-image: linear-gradient(或background-image: url("1x1px-white.png");)而不是background-color: white;,因为它需要在3个单独的层中重复,而background-color: white;不能用于在背景中定义矩形区域,也不能有multiplebackground-color个层(即使是半透明的).
    • 该示例还使用了has to个DOM文本来屏蔽白色矩形,而不是使用白色矩形来屏蔽DOM文本,因为HTML中的CSS不支持任何类型的reversed文本屏蔽,否则这会容易得多.不过,我相信这在SVG中很容易实现.
    • 不幸的是,#div1<p>元素仅使用其内部padding而不是position: absolute;来正确定位文本,因为定位的文本不能与background-clip: text;一起使用.
  • 另一个带有文本副本的<p>元素用于笔划文本(text-stroke: 1px white;))

  • 幸运的是,当文本内容在HTML源中复制时,3个图像(以及它们各自的白色蒙版)的更繁琐的大小和位置信息不需要在CSS中复制;这要归功于CSS的 Select 器的工作方式(因为#container#div1background-sizebackground-position属性都是由单个CSS规则设置的).

可能的替代方法:

  • 代替对纯白部分使用重复的相同大小的background-image层,可以在#pWhite上使用单个(但极其复杂)clip-path跟踪3个方框(就像像蚀刻草图一样绘制的单个线条),但这将不是可行的动画.

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

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

Css相关问答推荐

Css:有没有更快捷的方式来编写多媒体查询?

如何使用TailwindCSS溢出?

如何在容器查询体中重新定义:Root的CSS自定义属性值?

material 设计--Bootstrap输入域问题

react native 容器样式

显示 P 元素中加载数据的空行

为什么 CSS Calc() 函数只需要+或-运算符前后有空格

当滚动量较小时,在滚动问题上动画粘性导航

为什么 width: 100% 在 Flex 父级中缩小这个 div ?

如何使我的标语(h1元素)不居中对齐?

如何使用来自单独模块的代码将自定义标头插入到使用 DT Shiny 呈现的表中?

当值小于 1 时理解 flex-shrink

在 WooCommerce 变体 Select 中转换属性文本以大写

如何在 flex-wrap 中优先考虑第一行?

直观地指示 IFrame 内的表单正在提交,但没有 javascript

AngularJS Graphs & Charts - 实线和虚线的混合

基于类的 CSS Select 器

CSS 中的区域类似于 C# 区域?

CSS 悬停与 JavaScript 鼠标悬停

如何将页脚(div)与页面底部对齐?