DarkRift
DarkRift

Reputation: 234

How to vertically and horizontally center SVG text with different font size

I have a component to represent a tab header like the following :

import Svg, { G, Path } from 'react-native-svg';

const Tab = ({ height = "57.8", width="104", children, fill='#D1D3D4' }) => (
  <Svg height={height} width={width} viewBox="0 0 104 57.8">
    <G>
      <Path d="M-0.1,57.8h85c19.1,0,19.5-13.9,19.1-17.9L97.8,0H0.1L-0.1,57.8z" fill={fill}/>
      { children }
    </G>
  </Svg>
)

The children is to be svg Text that will have multiple text segments with different font size to be baseline aligned between each other. This text also need to be vertically AND horizontally centered inside it's parent.

I have tried different things, but I can't seem to find the proper configuration. This is my latest which centers the inside text baseline with the center of it's parent.

import { Text, TSpan } from 'react-native-svg';
...
return (<Tab><Text x={52} y={28.9} textAnchor={'middle'} alignmentBaseline={'central'}>
  <TSpan alignmentBaseline={"baseline"}>
    <TSpan fontSize={44}>{text.charAt(0)}</TSpan>
    <TSpan fontSize={32}>{text.substring(1)}</TSpan>
  </TSpan>
</Text></Tab>)

Any help is greatly appreciated.

Upvotes: 2

Views: 8286

Answers (1)

Paul LeBeau
Paul LeBeau

Reputation: 101800

SVG has no automatic layout capabilities. You are required to position text yourself using the x and y attributes and/or the transform attribute.

However, you can embed HTML in an SVG using the <foreignObject> element. If you do that you can use HTMLs layout capabilities to center text horizontally and vertically.

You can find examples of how to use <foreignObject> on this site.

Update

I think part of the reason why you are having so much trouble, is that alignment-baseline is not inherited. Also the browsers don't seem to agree on how to render it. IT generally works on <text> elements, but things get a lot messier/buggier when you put it on <tspan> elements.

I would suggest using the dy="Xem" technique instead. It works the same on every browser.

<svg width="104" height="57.8" viewBox="0 0 104 57.8">
  <line x1="0" y1="28.9" x2="104" y2="28.9" stroke="red" stroke-width="1"/>
  <text x="52" y="28.9" dy="0.35em" font-size="44" text-anchor="middle">
    <tspan>T</tspan><tspan font-size="32">ext</tspan>
  </text>
</svg>

Upvotes: 4

Related Questions