Power BI is turning 10, and we’re marking the occasion with a special community challenge. Use your creativity to tell a story, uncover trends, or highlight something unexpected.
Get startedJoin us for an expert-led overview of the tools and concepts you'll need to become a Certified Power BI Data Analyst and pass exam PL-300. Register now.
Hello,
Setting dominant-baseline to middle isn't working for all fonts in cases where the text height exceeds svg height. I am trying to vertically center text on top of a rect element. Some fonts appear too low and others too high, while some appear just right. In short, some fonts are squat and some are tall. Is there a way for me to measure the actual glyphs, without the line height and bounding box of the whole text element?
Thanks
Emma
kpiTextHeight = Math.round(textMeasurementService.measureSvgTextHeight(kpiTextProperties));
I have tried playing with baselineDelta but it doesn't seem to change much with the font.
this.kpiText
.attr('text-anchor','middle')
.attr('dominant-baseline','central')
.attr('font-size',kpiFontSize+'pt')
.attr('y', 0 )
.attr('dy', 0)
.attr('y', kpiRectHeight/2 )
// .attr('dy', -kpiFontSize/2)
.attr('font-family',kpiFont)
.attr('x',svgWidth/2)
.attr('fill', settings.kpiTextCard.kpiFontColorSlice.value.value)
.attr('class','kpiNumber')
.text(kpiValue);
this.kpiText sits within a group, which also contains a rect element of height kpiRectHeight.
@VizDataLtd In order to vertically center a svg text to a svg rect, this should be the config
const text = svg.append('text')
.each(
function(_, i) {
// taget element for alignment
const rect = /*get the rect node either with vanilla or d3*/ document.querySelector('rect');
//get x+ half of width
const midX = parseFloat(rect.getAttribute('x')) + parseFloat(rect.getAttribute('width')) / 2;
//get y+ half of height
const midY = parseFloat(rect.getAttribute('y')) + parseFloat(rect.getAttribute('height')) / 2;
d3.select(this)
.attr('x', midX)
.attr('y', midY)
// aligns as per the text length
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'middle')
.text('Lorem Ipsum')
.attr('font-size', '140px')
}
)
<div id="viz">
<svg id="svg" viewBox="0 0 1280 600">
<rect class="svg_container" width="1280" height="600" fill="#EFEFEF" stroke="black"></rect>
<text x="640" y="300" text-anchor="middle" dominant-baseline="middle" font-size="140px">Lorem Ipsum</text>
</svg>
</div>
Thanks, yes, that should work but it wasn't working at the extremes. I added a red line at the vertical midpoint and compared fonts. For anyone struggling with the same thing, I worked out that some fonts just sit lower. Constantia, for example, sits below the others. So while my visual works brilliantly with Arial and Times New Roman, I don't think there is a fix for some fonts.
If you are using an external font (which I always do) it might be worth to wrap your calculations in Document: fonts promise and use font-display: block; to ensure that the coordinates are only applied once the external fonts are loaded and not before that.
This is your chance to engage directly with the engineering team behind Fabric and Power BI. Share your experiences and shape the future.
Check out the June 2025 Power BI update to learn about new features.