Skip to content

🐛 Emoji/Unicode Width Calculation Causes Layout Misalignmen #562

@kolkov

Description

@kolkov

🐛 Emoji/Unicode Width Calculation Causes Layout Misalignment

Problem Description

The lipgloss library v1.1.0 has a critical issue with width calculation for emoji and Unicode characters, causing misaligned TUI layouts in terminal applications.

Root Cause

The ansi.StringWidth() function in charmbracelet/x/ansi incorrectly calculates the display width of:

  • Emoji characters (🚀, ⏰, 👥, etc.)
  • Unicode grapheme clusters
  • Multi-byte CJK characters
  • ZWJ (Zero Width Joiner) sequences

This results in boxes and tables appearing misaligned when they contain Unicode content.

Steps to Reproduce

  1. Create a simple lipgloss box with emoji content
  2. Compare with ASCII-only box
  3. Observe misalignment
package main

import (
    "fmt"
    "github.com/charmbracelet/lipgloss"
)

func main() {
    style := lipgloss.NewStyle().
        Border(lipgloss.RoundedBorder()).
        Width(15).
        Padding(1)

    asciiBox := style.Render("[*] ASCII\nTest")
    emojiBox := style.Render("⏰ Emoji\nTest")
    
    fmt.Println(asciiBox)
    fmt.Println(emojiBox) // ← This appears wider/misaligned
}

Expected Behavior

Both boxes should have the same visual width (15 cells) and align properly.

Current Behavior

The emoji box appears significantly wider, breaking layout alignment.

Visual Example:

EXPECTED:
┌─────────────┐  ┌─────────────┐
│ [*] ASCII   │  │ ⏰ Emoji    │  ← Same width
│ Test        │  │ Test        │
└─────────────┘  └─────────────┘

ACTUAL:
┌─────────────┐  ┌──────────────────┐
│ [*] ASCII   │  │ ⏰ Emoji         │  ← Too wide!
│ Test        │  │ Test             │
└─────────────┘  └──────────────────┘

Environment

  • OS: Windows 11, macOS, Linux (affects all platforms)
  • Go Version: 1.21+
  • Lipgloss Version: 1.1.0
  • Terminal: Windows Terminal, iTerm2, GNOME Terminal

Impact

This affects any TUI application using lipgloss with:

  • International content (CJK characters)
  • Modern UI with emoji
  • Dashboard layouts
  • Table formatting
  • Professional terminal applications

Proposed Solution

Implement fallback width calculation using mattn/go-runewidth for complex Unicode characters while preserving ANSI sequence handling.

The fix involves:

  1. Smart detection of problematic Unicode content
  2. Fallback calculation for accuracy
  3. Maintaining backward compatibility
  4. Performance optimization (minimal overhead for ASCII)

Additional Context

This is a critical issue for:

  • International users requiring proper CJK support
  • Modern applications using emoji in TUI
  • Professional dashboards requiring precise alignment
  • Any application mixing ASCII and Unicode content

Related: This issue stems from the complexity of Unicode width calculation in terminal environments, particularly with emoji and grapheme clusters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions