Accepted answer

Text alignment in SVG does not work the way we are used to from HTML and CSS where everything is box with some dimensions and we can apply e.g. text-align: center.

In <svg:text> the starting coordinates define point from which will text line expand. text-anchor attribute controls which direction this expansion will occur: center value means it will expand both ways so the initial anchor point will be in the middle of bounding box width (for horizontal writing systems). See excellent answer illustrating this text-anchor as the best mean for centering text in SVG: Also, there is no CSS position properties (left/top) inside SVG, only x/y coordinates, nor margins and rest of box-model as you know it in HTML.

So in your code adding text-anchor="middle" and moving the x coordinates further right would produce centered text. I'd advise to use bare <text> elements as opposed to <tspan>s, because shifting them with dx/dy is relative to the last preceding character and this character could be some white space from parent <text> (depending on code formatting) what would produce unbalanced centering. Also for easier calculations dominant-baseline="central" (or just middle for horizontal writing systems) is useful, because it moves the anchor point from the base line to "center line". So using dy attribute (as you already do) to move the first line "one half" of line-height up and the other down should do the trick:

<svg viewBox="0 0 800 200" text-anchor="middle" dominant-baseline="central" font-size="100">
 <!-- Outline and diagonals with center point for illustration: -->
 <path d="M0,0h800v200h-800zl800,200m0 -200L0,200" fill="#FC9" stroke-width="1" stroke="rgba(0,0,0,0.3)"></path>
 <circle cx="50%" cy="50%" r="10" fill="red"></circle>
 <!-- Centered text: -->
 <text x="50%" y="50%" fill="rgba(0,0,0,0.3)">So</text>
 <!-- Shifted up and down: -->
 <text x="50%" y="50%" dy="-0.5em">So</text>
 <text x="50%" y="50%" dy="+0.5em">Food</text>

(Not entirely related: the clipping could be done in CSS only with background-clip: text; here is rough variation of your design as it appears in Chrome browser, with animated text background, but without shadows. Unfortunately adding shadows would require more elements or attributes, I think. This should work in any browser supporting background-clip.)

div {
	display: flex;
	flex-direction: column;
	align-items: center;
	font-size: 30vh;
	line-height: 30vh;
	font-weight: bold;
	font-family: Impact;
span {
	color: #fff;
	background-color: #000;
	width: 100%;
	text-align: center;
@supports (-webkit-text-fill-color: transparent) and (-webkit-background-clip: text) {
	span {
		-webkit-text-fill-color: transparent;
		-webkit-background-clip: text;
		animation: 2s wohoo infinite alternate cubic-bezier(1,0,1,1);
		background-position: 0 0;
		background-size: 100% 100%;
		background-color: transparent;
		background-image: linear-gradient(
			to right,
			#f2385a 0,
			#f2385a 20%,
			#f5a503 0,
			#f5a503 40%,
			#e9f1df 0,
			#e9f1df 60%,
			#56d9cd 0,
			#56d9cd 80%,
			#3aa1bf 0,
			#3aa1bf 100%
		background-repeat: no-repeat;
		transform-origin: center center;

@keyframes wohoo {
	from {
		background-size: 0 100%;
		background-position: -5vh 0;
		transform: scale(0.7);
	50% {
		transform: scale(0.7);
	90% {
		transform: scale(0.9);
	to {
		background-size: 500% 100%;
		background-position: 0vh 0;
		transform: scale(0.9) 

body {
	background-color: #1d1f20;
	color: snow;
	display: flex;
	flex-direction: row;
	justify-content: center;
	width: 100%;

Related Query

More Query from same tag