You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何用CSS在O、Q类字母内部空白处插入可随字体缩放的图片

如何用CSS在O、Q类字母内部空白处插入可随字体缩放的图片

嗨,这个需求我之前也折腾过好一阵!确实普通的background-clip: text只能把图片填进整个文字形状(包括笔画),完全不是你要的“让字母笔画当边框,内部放图片”的效果。不过用CSS确实能实现,而且完美支持缩放和换行,不用纠结SVG的排版问题,我给你拆解下具体怎么做:

核心思路

其实就是用两层元素配合着来:

  • 一层是空心的字母边框:用文字描边实现,只留边框、去掉填充色。
  • 一层是被锁在字母内部的图片:通过CSS遮罩(mask)让图片只显示在字母的空白区域里。
  • 把它们塞进同一个容器,容器随文字流排版,字体大小用相对单位,就能实现整体跟着视口缩放。

具体代码实现

HTML结构

先给需要替换的字母单独做个容器,这样不影响其他文字,还能复用样式:

<h1 class="title">
  Hello <span class="letter-box" data-letter="O">
    <img src="your-photo.jpg" alt="风景图">
  </span> World
  <span class="letter-box" data-letter="Q">
    <img src="another-photo.jpg" alt="动物图">
  </span>uick Brown Fox
</h1>

CSS样式

/* 标题全局样式:用clamp实现响应式字体大小,随视口自动缩放 */
.title {
  font-size: clamp(2rem, 5vw, 8rem);
  font-family: "Arial", sans-serif; /* 选无衬线字体,内部空白更规整,遮罩更容易对齐 */
}

/* 字母容器:inline-block保证和普通文字一样换行,相对定位让内部元素对齐 */
.letter-box {
  position: relative;
  display: inline-block;
  line-height: 1; /* 避免图片和文字错位 */
}

/* 上层的空心字母边框:用text-stroke实现,填充色设为透明 */
.letter-box::after {
  content: attr(data-letter); /* 用data属性复用字母,不用重复写内容 */
  position: relative;
  z-index: 2; /* 把边框放在图片上面,形成“相框”效果 */
  color: transparent;
  -webkit-text-stroke: 0.05em #222; /* 用em单位,字体变大边框自动变粗,比例一致 */
  text-stroke: 0.05em #222;
  display: block;
}

/* 下层的图片:绝对定位铺满容器,用遮罩限制只显示字母内部 */
.letter-box img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover; /* 图片填充方式,可选cover(填满裁剪)/contain(完整显示) */
  z-index: 1;
  /* 关键:用两个文字形状的遮罩,通过复合模式得到字母内部空白区域 */
  -webkit-mask: 
    /* 第一层:和实际字体一样大的实心文字形状 */
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text x="50" y="80" font-size="80" font-family="Arial" text-anchor="middle">%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Ctext%20x%3D%2250%22%20y%3D%2280%22%20font-size%3D%2280%22%20font-family%3D%22Arial%22%20text-anchor%3D%22middle%22%3E%22%7B%7Bdata-letter%7D%7D%22%3C%2Ftext%3E%3C%2Fsvg%3E') 
    center/100% 100% no-repeat,
    /* 第二层:缩小一点的实心文字形状,用来减去中间部分 */
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text x="50" y="80" font-size="70" font-family="Arial" text-anchor="middle">%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Ctext%20x%3D%2250%22%20y%3D%2280%22%20font-size%3D%2270%22%20font-family%3D%22Arial%22%20text-anchor%3D%22middle%22%3E%22%7B%7Bdata-letter%7D%7D%22%3C%2Ftext%3E%3C%2Fsvg%3E') 
    center/100% 100% no-repeat;
  mask: 
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text x="50" y="80" font-size="80" font-family="Arial" text-anchor="middle">%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Ctext%20x%3D%2250%22%20y%3D%2280%22%20font-size%3D%2280%22%20font-family%3D%22Arial%22%20text-anchor%3D%22middle%22%3E%22%7B%7Bdata-letter%7D%7D%22%3C%2Ftext%3E%3C%2Fsvg%3E') 
    center/100% 100% no-repeat,
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text x="50" y="80" font-size="70" font-family="Arial" text-anchor="middle">%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Ctext%20x%3D%2250%22%20y%3D%2280%22%20font-size%3D%2270%22%20font-family%3D%22Arial%22%20text-anchor%3D%22middle%22%3E%22%7B%7Bdata-letter%7D%7D%22%3C%2Ftext%3E%3C%2Fsvg%3E') 
    center/100% 100% no-repeat;
  /* 复合遮罩:用大文字形状减去小文字形状,得到字母内部的空白区域 */
  -webkit-mask-composite: exclude;
  mask-composite: exclude;
}

关键细节说明

  • 响应式缩放:用clamp(2rem, 5vw, 8rem)设置字体大小,意思是最小2rem,最大8rem,中间随视口宽度自动调整,整个字母和图片都会跟着缩放。
  • 排版兼容:容器用inline-block,所以会像普通文字一样自动换行,完全不用担心SVG那种排版难控制的问题。
  • 边框比例:边框粗细用0.05em,是相对字体大小的单位,字体越大边框越粗,始终保持协调的比例。
  • 遮罩对齐:如果图片和字母边框不对齐,可以调整SVG里的font-sizey坐标,让遮罩的文字和实际字体完全匹配。

可选调整

  • 边框颜色:直接修改text-stroke的颜色值,比如换成#gold或者品牌色。
  • 图片填充:把object-fit: cover改成contain,可以完整显示图片(可能会在字母内部留空白)。
  • 边框粗细:调整0.05em的数值,比如改成0.03em就是细边框,0.07em就是粗边框。

这样做出来的效果完全符合你的需求:图片乖乖待在字母内部,笔画当相框,而且整个标题能跟着视口缩放,排版和普通文字一样自然~

内容来源于stack exchange

火山引擎 最新活动