Home > Back-end >  Why there are spaces between my <span> elements in contenteditable?
Why there are spaces between my <span> elements in contenteditable?

Time:12-25

I'm trying to build a Notion-like editor in Svelte, I've made some good progress, but I'm now scratching my head trying to figure out why exactly i get spaces between span elements. I'm dividing the text in spans based on their formatting, here's an example of an output:

<div contenteditable="true">
  <p>
    <span contenteditable="true" id="a1" data-index="0">some text</span> //normal text
    <span contenteditable="true" id="a2"  data-index="0">some other text</span> //bold text
  </p>
</div>

In between them a #textnode with a little bit of space gets created and I can't figure out how to avoid it. I've tried multiple CSS options, but no matter the CSS properties, these spaces persists. My understanding is that these #textnodes are on the DOM itself.

Here's the code responsible for this output. The $fragments array is modified through keydown events and binds to the HTML of the span element, synchronizing the changes. The default behaviour of a character insertion is prevented through e.preventDefault().

{#each $fragments[$selectedFragment].children[childIndex].text as fragment, i}
    {#if fragment.tag == "span"}
        <span
            contenteditable="true"
            id={fragment.id}
            
            data-index={i}
            class:bold={fragment?.formattingOptions?.bold}
            class:italic={fragment?.formattingOptions?.italic}
        >{fragment.text}</span>
    {/if}
{/each}

I've also tried putting the code in a single line to avoid generating spaces somehow, but no changes:

    <p id={$fragments[$selectedFragment].children[childIndex].id}  data-index={childIndex} bind:this={element}>{#key $justKey}{#each $fragments[$selectedFragment].children[childIndex].text as fragment, i}{#if fragment.tag == "span"}<span contenteditable="true" id={fragment.id}  data-index={i} class:bold={fragment?.formattingOptions?.bold} class:italic={fragment?.formattingOptions?.italic}>{fragment.text}</span>{/if}{/each}{/key}</p>

Here's the demo: https://epub-theta.vercel.app/fragments If you need any further details, please let me know. Thank you for your help.

UPDATE: adding elements through browser's inspector does not generate these spaces, so it has something to do with how they get inserted by Svelte, or some space/line break somewhere somehow. Still searching.

UPDATE: definitely an issue with how Svelte renders the HTML, there is whitespace between elements by default and this is the outcome. No clear solution in sight, only some hacky workarounds that end up breaking other code.

CodePudding user response:

either place the span tags next to each other on the same line or comment out the space.

<div contenteditable="true">
  <p>
    <span contenteditable="true" id="a1" data-index="0">some text</span><!--
    --><span contenteditable="true" id="a2"  data-index="0">some other text</span> 
  </p>
</div>

CodePudding user response:

This problem is related to the ongoing issue of whitespace handling in Svelte. There are solutions for SSR pages, but since in my case the HTML is user-generated I couldn't find a non-disruptive way to fix it.

For now I'll use this workaround which leaves the impression that these small spaces are not there:

span {
    margin: -0.8px;
}
  • Related