0

This code is supposed to center the text vertically after changing some font properties.

The calculations look correct, but for some reason, the text isn't pushed down as far as the calculations say they should, causing the text to be off-center.

Codepen: https://codepen.io/anon/pen/NepNjb?editors=1111

What's causing this?

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<svg id="rootBox" width="375" height="812" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

    <style type="text/css">@import url('https://fonts.googleapis.com/css?family=Lato|Open+Sans|Oswald|Raleway|Roboto|Indie+Flower|Gamja+Flower')</style>

    <svg id="textBox1" class="textBox" x="0" y="0" width="100%" height="25%">
      <rect class="background" x="0%" y="0%" width="100%" height="100%" fill="gray" fill-opacity="0.5" />

      <text class="tspanGroup" x="50%" y="50%"><tspan x="50%" dy="0" text-anchor="middle">tspan line 0</tspan><tspan x="50%" dy="1.5em" text-anchor="middle">tspan line 1</tspan><tspan x="50%" dy="1.5em" text-anchor="middle">tspan line 2</tspan></text>
    </svg>

</svg>
Crashalot
  • 33,605
  • 61
  • 269
  • 439

1 Answers1

2

Add dominant-baseline="hanging" to your .tspanGroup and alignment-baseline="middle" to your <tspan>s. This will fix the baseline-behaviour of the text elements.

To see the effect of the default values versus the altered values, change the y-value of your .tspanGroup to 0 in your pen and the snippet in this answer. You will see that the text flows over the upper edge in your example, while starting at the edge on mine.

console.log("Start");


function setTspan(elem, fontFamily, fontSize, fontStyle) {
  // Set font family?
  if (fontFamily) {
    elem.attr("font-family", fontFamily);
  }
  
  // Set font size?
  if (fontSize) {
    elem.attr("font-size", fontSize);
  }
  
  // Set font style?
  if (fontStyle) {
    elem.attr("font-style", fontStyle);
  }
}


function centerText() {  
  // Get tspan group.
  var textBox = $("#textBox1");
  var tspanGroup = textBox.children(".tspanGroup");

  // Set font styles.
  var fontSize = 30;
  var fontFamily = "Open-Sans";
  var fontStyle = "";
  tspanGroup.each(function(){
    setTspan($(this), fontFamily, fontSize, fontStyle);
  });
  
  // Get heights.
  var textBoxHeight = textBox[0].getBoundingClientRect().height;
  var tspanGroupClientRect = tspanGroup[0].getBoundingClientRect();

  // Update text
  var newY = textBoxHeight/2 - tspanGroupClientRect.height/2
  tspanGroup.attr("y", newY);
  
  // Print results
  console.log("Text box height: " + textBoxHeight + ". Tspan group height: " + tspanGroupClientRect.height + ". New Y: " + newY + ".");
}


centerText();


console.log("Done");
html, body {
  margin: 0;
  padding: 20px;
}
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<svg id="rootBox" width="375" height="812" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  
    <style type="text/css">@import url('https://fonts.googleapis.com/css?family=Lato|Open+Sans|Oswald|Raleway|Roboto|Indie+Flower|Gamja+Flower')</style>
        
    <svg id="textBox1" class="textBox" x="0" y="0" width="100%" height="25%">
      <rect class="background" x="0%" y="0%" width="100%" height="100%" fill="gray" fill-opacity="0.5" />
      
      <text class="tspanGroup" dominant-baseline="hanging" x="50%" y="50%"><tspan x="50%" dy="0" text-anchor="middle" alignment-baseline="hanging">tspan line 0</tspan><tspan x="50%" dy="1.5em" text-anchor="middle" alignment-baseline="hanging">tspan line 1</tspan><tspan x="50%" dy="1.5em" text-anchor="middle" alignment-baseline="hanging">tspan line 2</tspan></text>
    </svg>
    
</svg>
Tom M
  • 2,815
  • 2
  • 20
  • 47
  • Thanks for the answer! But isn't alignment-baseline not supported in all browsers? – Crashalot Dec 21 '18 at 10:40
  • Well it works on my machine ¯\_(ツ)_/¯. Jk, I couldn't find much information on the browser support but it seems to work on Chrome and Firefox while edge just strips the attribute and ignores `dominant-baseline`. Can't test it on safari right now – Tom M Dec 21 '18 at 10:47
  • But this really looks like a baseline issue since there is nothing else pulling the `` out of the parents bounding box and tampering with the baseline seems to fix it – Tom M Dec 21 '18 at 10:49