JSFiddle - React, Tailwind, and code Playground
HTML
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. And then she said: <span is="char-hang">“</span>Corporis eligendi a pariatur illum provident incidunt maxime, laborum animi adipisci fugit culpa libero ipsam aliquam necessitatibus, molestiae voluptatem at quasi ratione!”
</p>
JavaScript
class CharHangElement extends HTMLSpanElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: "open" });
this.style.display = "contents";
const pull = document.createElement("span");
pull.textContent = this.textContent;
shadow.appendChild(pull);
const push = document.createElement("span");
pull.before(push);
const offsetWidthEm = pull.offsetWidth / parseFloat(
getComputedStyle(pull).fontSize
);
pull.style.marginInlineStart = `-${offsetWidthEm}em`;
push.style.marginInlineEnd = `${offsetWidthEm}em`;
}
}
customElements.define("char-hang", CharHangElement, { extends: "span" });