马黑黑 发表于 2022-9-25 09:15

CSS :用伪元素给文本上色

本帖最后由 马黑黑 于 2022-9-25 11:15 编辑 <br /><br /><p>之前我们的部分音画帖,利用 background-clip: text; 之设定,实现了用元素背景为文本着色的功能,我们甚至还为之加入了冷门属性 text-stroke 做出了字体镂空的效果。这是极好的创意,在当下浏览器中能够正常渲染出预设的效果。</p><p><br></p>

<p>除了 background-clip 属性,也许我们还有其他的给文本上色的途径。我最先想到的是利用伪元素。伪元素本质上是元素的子元素,它可以通过 attr 设置和父元素一样的文本,并覆盖父元素的文本。那么,我们可以有这样的思路:伪元素设置长度,且 overflow 设为 none 以防止文本溢出,如此,伪元素能够部分遮盖父元素,只要父元素、伪元素前景色不同,就能模拟给部分文字上色的功能。</p><p><br></p><p>试看如下代码:</p><p><br></p><p>&lt;style&gt;</p><p><br></p><p>#fontColor {</p><p><span style="white-space:pre">        </span></p><p><span style="white-space:pre">        </span>font: bold 4em sans-serif;</p><p><span style="white-space:pre">        </span>color: rgba(0,0,0,.1);</p><p><span style="white-space:pre">        </span>position: absolute;</p><p>}</p><p><br></p><p>#fontColor::before {</p><p><span style="white-space:pre">        </span>position: absolute;</p><p><span style="white-space:pre">        </span>content: attr(data-text);</p><p><span style="white-space:pre">        </span>color: red;</p><p><span style="white-space:pre">        </span>width: 100px;</p><p><span style="white-space:pre">        </span>height: 100%;</p><p><span style="white-space:pre">        </span>overflow: hidden;</p><p>}</p><p><br></p><p>&lt;/style&gt;</p><p><br></p><p>&lt;div id="fontColor" data-text="ABCDEFG"&gt;ABCDEFG&lt;/div&gt;</p><p><br></p><p>效果:<br><br></p>
<style>

#fontColor {
        font: bold 4em sans-serif;
        color: rgba(0,0,0,.1);
        position: absolute;
}

#fontColor::before {
        position: absolute;
        content: attr(data-text);
        color: red;
        width: 100px;
        height: 100%;
        white-space: nowrap;
        overflow: hidden;
}

</style>

<div style="position: relative; height: 90px;">
        <div id="fontColor" data-text="ABCDEFG">ABCDEFG</div>
</div>

<p>看上去,效果出来了。顺便提一下:在论坛,需要给伪元素设置一个属性:white-space: nowrap; 该属性本来是缺省默认值,由于论坛需要,预设了所有元素的文本都应自动折行,所以需要给需要不自动折行的元素重新设置一次这个属性为默认值。</p>

马黑黑 发表于 2022-9-25 09:27

本帖最后由 马黑黑 于 2022-9-25 10:53 编辑 <br /><br /><p>看个动态的效果:</p><p><br></p><p><br></p>

<style>
#papa {
      margin: auto;
      width: 600px;
      position: relative;
}
#fColor {
      font: bold 4em sans-serif;
      color: rgba(0,0,0,.1);
      position: absolute;
}

#fColor::before {
      position: absolute;
      content: attr(data-text);
      color: red;
      width: 0%;
      height: 100%;
      white-space: nowrap;
      overflow: hidden;
      animation: long 4s linear infinite;
}
@keyframes long {
      from { width: 0;}
      to { width: 100%; }
}
</style>

<div id="papa">
      <div id="fColor" data-text="ABCDEFG">ABCDEFG</div>
</div>

马黑黑 发表于 2022-9-25 09:28

本帖最后由 马黑黑 于 2022-9-25 10:58 编辑

二楼效果的代码:

<style>
#papa {
      margin: auto;
      width: 600px;
      position: relative;
}
#fColor {
      font: bold 4em sans-serif;
      color: rgba(0,0,0,.1);
      position: absolute;
}

#fColor::before {
      position: absolute;
      content: attr(data-text);
      color: red;
      width: 0%;
      height: 100%;
      white-space: nowrap;
      overflow: hidden;
      animation: long 4s linear infinite;
}
@keyframes long {
      from { width: 0;}
      to { width: 100%; }
}
</style>

<div id="papa">
      <div id="fColor" data-text="ABCDEFG">ABCDEFG</div>
</div>


由于论坛的全局设定,红色那行必须,white-space: nowrap;,这是设定伪元素不自动折行,这样才能产生平滑染色效果,否则是单个字逐一一次性染色。

文本父元素和它的伪元素都设定 position 为 absolute 至关重要,这样它们的原始宽度由于文本内容一样,会是一致的,然后我们通过控制伪元素的宽度,来模拟逐字平滑染色的效果。

红影 发表于 2022-9-25 09:48

在不设置父框宽度的情况下,感觉伪元素取宽高各100%应该是渲染一个文字吧,怎么渲染了2个文字?

红影 发表于 2022-9-25 09:50

这个也能做歌词同步,黑黑聪明,又是一种完全不同的方法{:4_199:}

马黑黑 发表于 2022-9-25 10:51

红影 发表于 2022-9-25 09:50
这个也能做歌词同步,黑黑聪明,又是一种完全不同的方法

挺好的,论坛上的问题也找到了:它的CSS有很多全局设置,其中对文本的折行就做了设定,如果不在局域里给某元素重新设定,就用默认的,从而影响了我想要的效果。

马黑黑 发表于 2022-9-25 10:51

红影 发表于 2022-9-25 09:48
在不设置父框宽度的情况下,感觉伪元素取宽高各100%应该是渲染一个文字吧,怎么渲染了2个文字?

这是论坛的设定造成的,我们要在自己的元素中加入新的设定

马黑黑 发表于 2022-9-25 11:03

红影 发表于 2022-9-25 09:48
在不设置父框宽度的情况下,感觉伪元素取宽高各100%应该是渲染一个文字吧,怎么渲染了2个文字?

伪元素是 100px。现在你再看,通过加入 white-space: nowrap 后,100px渲染了两个半字。

宽度设为 100% 时,是指子元素的宽度是父元素的宽度的 100%,如果上面都没有父元素,则宽度是浏览器视口的整个宽度。

红影 发表于 2022-9-25 11:13

马黑黑 发表于 2022-9-25 10:51
挺好的,论坛上的问题也找到了:它的CSS有很多全局设置,其中对文本的折行就做了设定,如果不在局域里给 ...

嗯,若不设置,默认的就起作用。记下了{:4_204:}

红影 发表于 2022-9-25 11:14

马黑黑 发表于 2022-9-25 10:51
这是论坛的设定造成的,我们要在自己的元素中加入新的设定

这些都不懂呢,学习了{:4_187:}

红影 发表于 2022-9-25 11:16

马黑黑 发表于 2022-9-25 11:03
伪元素是 100px。现在你再看,通过加入 white-space: nowrap 后,100px渲染了两个半字。

宽度设为 100 ...

现在调用歌词并把最后的秒数放在这个代码里,就能做新的歌词同步了吧?

马黑黑 发表于 2022-9-25 11:17

红影 发表于 2022-9-25 11:14
这些都不懂呢,学习了

道理其实简单:论坛为了让文本的可读性友好,设置了全局设定,文本自动折行。不过论坛程序也没做的好,pre标签就常常不会自动折行。

马黑黑 发表于 2022-9-25 11:19

红影 发表于 2022-9-25 11:16
现在调用歌词并把最后的秒数放在这个代码里,就能做新的歌词同步了吧?

基本,还要做其他处理:JS要能动态给 data-text 赋值、CSS要设置一个变量用以接收歌词演唱的用时信息等等。这是个思路,很多细节还是要处理的。

马黑黑 发表于 2022-9-25 11:20

红影 发表于 2022-9-25 11:13
嗯,若不设置,默认的就起作用。记下了

white-space: nowrap; 本来是默认的,是论坛设置了部分元素的这个属性为其他值。

红影 发表于 2022-9-25 11:50

马黑黑 发表于 2022-9-25 11:17
道理其实简单:论坛为了让文本的可读性友好,设置了全局设定,文本自动折行。不过论坛程序也没做的好,pr ...

哦哦,论坛程序那么多,看着就头疼,更是弄不懂了。能跟着黑黑学点玩的,已经很满足了{:4_173:}

红影 发表于 2022-9-25 11:51

马黑黑 发表于 2022-9-25 11:20
white-space: nowrap; 本来是默认的,是论坛设置了部分元素的这个属性为其他值。

还是黑黑懂得多,做帖子也要考虑论坛设置的,不懂的人永远找不到问题根源呢。

红影 发表于 2022-9-25 11:52

马黑黑 发表于 2022-9-25 11:19
基本,还要做其他处理:JS要能动态给 data-text 赋值、CSS要设置一个变量用以接收歌词演唱的用时信息等等 ...

这个听着就很困难,真弄出来要花很多心思的吧{:4_204:}

马黑黑 发表于 2022-9-25 12:53

红影 发表于 2022-9-25 11:52
这个听着就很困难,真弄出来要花很多心思的吧

也许弄不出。为什么?JS操作伪元素的能力十分有限,换个 attr 内容是可以的。所以,这个目前来讲,用来模拟歌词逐字同步,有很大的困难。

马黑黑 发表于 2022-9-25 12:54

红影 发表于 2022-9-25 11:51
还是黑黑懂得多,做帖子也要考虑论坛设置的,不懂的人永远找不到问题根源呢。

出问题时我一下子也是蒙了,思考一阵子之后才知道原理

马黑黑 发表于 2022-9-25 12:54

红影 发表于 2022-9-25 11:50
哦哦,论坛程序那么多,看着就头疼,更是弄不懂了。能跟着黑黑学点玩的,已经很满足了

{:4_190:}
页: [1] 2 3 4 5 6
查看完整版本: CSS :用伪元素给文本上色