์ผ€์ด์Šค ce-0314-nested-inline-span-tags-created-ko ยท ์‹œ๋‚˜๋ฆฌ์˜ค scenario-nested-inline-span-tags-created

Unwanted span tags with inline styles created when removing line breaks

OS: Any Any ๊ธฐ๊ธฐ: Desktop or Laptop Any ๋ธŒ๋ผ์šฐ์ €: Chrome Latest ํ‚ค๋ณด๋“œ: US ์ดˆ์•ˆ
spaninline-stylesbackspacechromeformatting

Phenomenon

In Chrome, when using the backspace key to remove line breaks in a contenteditable element, the browser may insert unwanted <span> tags with inline styles. This behavior can interfere with subsequent styling efforts and create unnecessary HTML structure.

Reproduction example

  1. Create a contenteditable div with multiple paragraphs or line breaks.
  2. Place cursor at the beginning of a line (after a line break).
  3. Press backspace to remove the line break.
  4. Inspect the HTML to see if <span> tags with inline styles were inserted.
  5. Observe the structure of the resulting HTML.

Observed behavior

  • Span tags inserted: <span> elements are created during backspace operations.
  • Inline styles: Spans may contain inline styles like style="font-weight: normal;" or similar.
  • Unnecessary structure: HTML structure becomes more complex than needed.
  • Styling interference: Inline styles in spans can override intended formatting.
  • Chrome-specific: This behavior is more common in Chrome than other browsers.

Expected behavior

  • Backspace should remove line breaks without inserting unnecessary HTML elements.
  • No inline styles should be added unless explicitly applied by user.
  • HTML structure should remain clean and minimal.
  • Formatting should not be affected by structural changes.

Analysis

Chromeโ€™s contenteditable implementation may insert spans to preserve formatting state when removing structural elements. The browser tries to maintain style information, which can result in unwanted span tags.

Workarounds

  • Monitor input event and remove unnecessary spans:
    element.addEventListener('input', () => {
      const spans = element.querySelectorAll('span');
      spans.forEach(span => {
        if (!span.attributes.length || 
            (span.attributes.length === 1 && span.hasAttribute('style') && !span.style.cssText.trim())) {
          const parent = span.parentNode;
          while (span.firstChild) {
            parent.insertBefore(span.firstChild, span);
          }
          parent.removeChild(span);
          parent.normalize();
        }
      });
    });
  • Sanitize HTML after editing operations.
  • Use libraries that normalize HTML structure automatically.
  • Implement custom backspace handling to prevent span insertion.

Playground for this case

Use the reported environment as a reference and record what happens in your environment while interacting with the editable area.

Reported environment
OS: Any Any
Device: Desktop or Laptop Any
Browser: Chrome Latest
Keyboard: US
Your environment
Sample HTML:
Event log
Use this log together with the case description when filing or updating an issue.
0 events
Interact with the editable area to see events here.