Css 自动缩放SVG以适应子内容(例如文本)的宽度[无JS]

Css 自动缩放SVG以适应子内容(例如文本)的宽度[无JS],css,svg,Css,Svg,我发现的一切都是相反的,例如“如何缩放文本以适应SVG”。但我想实现相反的目标: 我的html中的SVG: 一些文本 CSS: svg.text{ 字体大小:2.5rem;//不同屏幕大小的更改 高度:0.8em; 宽度:auto;//这不起作用……无论文本的内容如何,宽度都会变得奇怪,总是一样的 } svg.text文本{ transform:translateY(0.8em);//需要这样才能使文本可见 } 我希望增长以匹配文本元素的宽度,就像将普通DOM元素设置为显示:内联块一样或位

我发现的一切都是相反的,例如“如何缩放文本以适应SVG”。但我想实现相反的目标:

我的html中的SVG:


一些文本
CSS:

svg.text{
字体大小:2.5rem;//不同屏幕大小的更改
高度:0.8em;
宽度:auto;//这不起作用……无论文本的内容如何,宽度都会变得奇怪,总是一样的
}
svg.text文本{
transform:translateY(0.8em);//需要这样才能使文本可见
}
我希望
增长以匹配
文本
元素的宽度,就像将普通DOM元素设置为
显示:内联块一样
位置:绝对或<代码>浮动:左侧

有什么想法吗

编辑 多亏了这一点,我想到了这个:

JavaScript:

/**
*将SVG适配到其第一个文本子视图框
*/
fitSvgTextElements(){
const elements=document.querySelectorAll('svg.text');
for(元素常数){
const box=el.querySelector('text').getBBox();
el.setAttribute('viewBox',`${box.x}${box.y}${box.width}${box.height}`);
}
}

这很有效。但是有没有办法用纯CSS/SVG属性来解决这个问题呢?

由于SVG格式的基本设计决定,如果没有脚本,您想要实现的大小更改是无法实现的。描述了如下相关概念:

所有SVG内容都在SVG视口中绘制。每个SVG视口定义一个绘图区域,其特征是大小(宽度、高度)和原点

SVG视口的宽度、高度和原点由生成SVG视口的SVG文档片段与该片段的父级(无论是真实的还是隐式的)之间的协商过程确定

这意味着视口的尺寸取决于它们的外部上下文,但与它们的内部内容无关

如果试图按视口元素的内容调整其大小,则会颠倒该逻辑顺序,并且只能在最初完成渲染后才能实现。此时,只有脚本才能更改呈现的DOM

您已经在您的问题中演示了如何使用脚本解决方案,尽管我会用不同的方式编写它。而CSS规则
width:auto;高度:1em
应该足够了,一些较旧的浏览器对此有问题。我更愿意明确地计算
元素的
宽度。(与CSS样式表规则相比,
width
属性的特异性更低。)

fitSvgTextElements(){
const elements=document.querySelectorAll('svg.text');
for(元素常数){
const box=el.querySelector('text').getBBox();
el.setAttribute('viewBox',`${box.x}${box.y}${box.width}${box.height}`);
//元素位于HTML上下文中,
//因此,需要与页面视口相关的尺寸
const viewport=el.getBoundingClientRect();
//保留高度,重新计算相对宽度
常量宽度=viewport.height*box.width/box.height;
el.style.width=`${width}px`;
}
}

事实上,我发现了一种更干净的方法。魔法属性是,如图所示

HTML格式的SVG(在
文本
元素上带有
主基线=“挂起”
):

…现在我可以调整CSS中的文本大小,例如:

svg.text{
显示:block;//或内联块
font size:inherit;//将响应父级的字体大小
}

使用getBBox()方法获取文本元素的边界框,并使用边界框的属性为svg元素构建viewBox属性谢谢!我很想解决这个问题,不用担心,谢谢!实际上,在我的例子中,即使没有明确定义
(在Chrome和FF中测试)的
宽度属性,它也可以工作。
视口
属性使
的行为类似于普通的
标记,不是吗?So
高度:1米;宽度:自动将缩放相对于高度的宽度。无论如何,谢谢你提供的深入信息,它很有效!在将您的答案标记为解决方案之前,我将等待这一点得到澄清。该属性称为
viewBox
。Viewport=要显示图形的区域,viewbox=要显示的图形部分。是的,使用CSS规则
width:auto
它应该可以工作,但较旧的浏览器可能无法正常工作。
fitSvgTextElements() {
  const elements = document.querySelectorAll('svg.text');
  for( const el of elements ) {
    const box = el.querySelector('text').getBBox();
    el.setAttribute('viewBox', `${box.x} ${box.y} ${box.width} ${box.height}`);
    // the <svg> element is in HTML context,
    // so you need dimensions in relation to the page viewport
    const viewport = el.getBoundingClientRect();
    // retain height, recompute width in relation
    const width = viewport.height * box.width / box.height;
    el.style.width = `${width}px`;
  }
}
<svg class="text" xmlns='http://www.w3.org/2000/svg'>
  <text dominant-baseline="hanging">
    My Text
  </text>
</svg>