I have been trying to figure this out for sometime, the text will be dynamic but generally over two lines which I will break into tags myself however they will be varying widths as the copy can be different for each line. I need each line to be equal width which I have got working however the problem is getting the two lines to be vertically center and line height correct.
I have a codepen illustrating what I have done so far. The problem is I don't want to use dy attribute unless there was an accurate way to change it in JS if need be. Any assistance is deeply appreciated.
https://codepen.io/basswow/pen/wvobNWL
let rnd = document.querySelectorAll("text");
rnd.forEach((txt, idx) => {
let txtlength = txt.getBoundingClientRect().width;
let w = txt.parentNode.getBoundingClientRect().width;
let scale = w / (2 * txtlength);
txt.setAttributeNS(
null,
"transform",
`scale(${scale},${scale}) translate(${50 / scale},${
50/scale
})`
);
});
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@800&display=swap');
svg {
width: 50%;
font-family: "Open Sans, sans-serif";
font-weight: 800;
}
text {
font-size: 10;
dominant-baseline: middle;
text-anchor: middle;
}
<svg viewBox="0 0 100 100">
<circle stroke="#333" stroke-width="3" fill="white" cx="50" cy="50" r="45"></circle>
<circle stroke="#999" stroke-width="3" fill="transparent" cx="50" cy="50" r="42"></circle>
<text id="txt" font-family="sans-serif" dominant-baseline="middle" text-anchor="middle">Online Special</text>
<text id="txt" font-family="sans-serif" dominant-baseline="middle" text-anchor="middle">Only</text>
</svg>
EDIT: I have come up with something else that sort of works however it's only restricted to two lines.
let rnd = document.querySelectorAll("text");
rnd.forEach((txt, idx) => {
let txtlength = txt.getBoundingClientRect().width;
let w = txt.parentNode.getBoundingClientRect().width;
let scale = w / (2 * txtlength);
let fs = window.getComputedStyle(txt).fontSize;
let newFs = parseInt(parseInt(fs) * scale * 0.95);
txt.style.fontSize = `${newFs}px`;
txt.setAttributeNS(null, "transform", `translate(0,${idx === 0 ? 0 - newFs/2 : 0 + newFs/2})`);
console.log(fs, newFs+'px');
});
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@800&display=swap');
svg {
width: 500px;
font-weight: 800;
}
text {
font-family: "Open Sans";
letter-spacing: 0;
font-size:10px;
dominant-baseline: middle;
text-anchor: middle;
transform-origin: center center;
}
<svg viewBox="0 0 100 100">
<circle stroke="#333" stroke-width="3" fill="white" cx="50" cy="50" r="45"></circle>
<circle stroke="#999" stroke-width="3" fill="transparent" cx="50" cy="50" r="42"></circle>
<text id="txt" dominant-baseline="middle" text-anchor="middle"
x="50%" y="50%">Free</text>
<text id="txt" dominant-baseline="middle" text-anchor="middle" x="50%" y="50%">Delivery</text>
</svg>
EDIT
console.clear();
let fontSize = 10;
const MAXWIDTH = document.querySelector("svg").getBBox().width * 0.7;
const lines = Array.from(document.querySelectorAll("text")).map((el) =>
el.getBBox()
);
let lastY = Array.from(document.querySelectorAll("text"))
.map((el) => el.getBBox())
.reduce((acc, curr) => acc + curr.height, 0);
lastY = lastY / 2;
document.querySelectorAll("text").forEach((el, idx) => {
let ratio = MAXWIDTH / el.getBBox().width;
let fs = parseInt(window.getComputedStyle(el).fontSize);
el.style.fontSize = Math.round(fs * ratio) + "px";
el.getBBox().height * (el.getBBox().width / MAXWIDTH);
el.style.transform = `translateY(${
lastY + el.getBBox().height * (el.getBBox().width / MAXWIDTH)
}px)`;
// el.setAttribute(
// "y",
// lastY + el.getBBox().height * (el.getBBox().width / MAXWIDTH)
// );
lastY += el.getBBox().height;
});
text {
text-anchor: middle;
/* dominant-baseline: baseline;
alignment-baseline: baseline; */
text-anchor: middle;
font-family: arial;
}
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="100" fill="#ff0000" />
<text x="50%" fill="white">Online</text>
<text x="50%" fill="white">Specials Only</text>
<text x="50%" fill="white">for the you!</text>
</svg>