tauri-apps/tauri

[bug] Page scroll jumps on every keystroke when typing RTL text with spaces

Open

#15330 opened on May 3, 2026

View on GitHub
 (0 comments) (0 reactions) (0 assignees)Rust (106,642 stars) (3,597 forks)batch import
help wantedplatform: macOSstatus: needs triagetype: bug

Description

Describe the bug

When typing Arabic or Hebrew text (RTL languages) in a contenteditable element or rich text editor (TipTap), the page scroll jumps on every keystroke when the text contains spaces (triggering word wrap).

This issue only occurs in the Tauri desktop app (macOS WebView), not in standard web browsers (Chrome, Safari, Firefox). The scroll jump makes the app completely unusable for Arabic/Hebrew-speaking users as the page jumps unpredictably while typing.

The issue specifically occurs when:

  • ✅ Text is RTL (Arabic/Hebrew characters)
  • ✅ AND text contains spaces (triggers word wrap)
  • ✅ AND running in Tauri desktop app (WebView)

Does NOT occur when:

  • ❌ Typing English text (LTR)
  • ❌ Typing Arabic text WITHOUT spaces (no word wrap)
  • ❌ Running the same code in regular web browsers

Reproduction

Steps:

  1. Create a Tauri app with a scrollable page container
  2. Add a TipTap editor (or any contenteditable element) to the page
  3. Scroll the page down so there's scroll offset
  4. Focus the editor and type Arabic text with spaces (e.g., "مرحبا بك في")
  5. Observe the page scroll position jumps on every keystroke

Minimal Code Example:

<!-- Scrollable container -->
<div class="app-content" style="height: 100vh; overflow-y: auto;">
  <div style="height: 200vh;">
    <!-- Forces scrollable content -->

    <!-- Contenteditable with RTL support -->
    <div
      contenteditable="true"
      dir="auto"
      style="
      unicode-bidi: plaintext;
      min-height: 100px;
      border: 1px solid #ccc;
      padding: 10px;
      contain: layout;
      overflow-anchor: none;
    "
    >
      <!-- Type Arabic text here: مرحبا بك في العالم -->
    </div>
  </div>
</div>
.app-content {
  overflow-y: auto;
  overflow-anchor: none;
}

[contenteditable] {
  unicode-bidi: plaintext;
  text-align: start;
  contain: layout;
  overscroll-behavior: contain;
}

Test text to reproduce: Type this in the editor: مرحبا بك في العالم (Arabic with spaces)

Expected behavior

The page scroll position should remain stable when typing RTL text with spaces, just like it behaves when:

  • Typing English text (LTR)
  • Typing Arabic text WITHOUT spaces
  • Running the same code in a regular web browser

Full tauri info output

**Note: Issue persists in both versions below. Updated to latest (2.11.0 / WRY 0.55.0) and issue still occurs.**


[✔] Environment
    - OS: Mac OS 26.2.0 arm64 (X64)
    ✔ Xcode Command Line Tools: installed
    ✔ Xcode: 26.4.1
    ✔ rustc: 1.95.0 (59807616e 2026-04-14)
    ✔ cargo: 1.95.0 (f2d3ce0bd 2026-03-21)
    ✔ rustup: 1.28.2 (e4f3ad6f8 2025-04-28)
    ✔ Rust toolchain: stable-aarch64-apple-darwin (default)
    - node: 23.5.0
    - npm: 11.11.0

[-] Packages (Current - Issue Still Present)
    - tauri 🦀: 2.11.0
    - tauri-build 🦀: 2.6.0
    - wry 🦀: 0.55.0
    - tao 🦀: 0.35.0
    - @tauri-apps/api  ⱼₛ: 2.11.0
    - @tauri-apps/cli  ⱼₛ: 2.11.0

[-] Packages (Original - When Issue First Discovered)
    - tauri 🦀: 2.10.2
    - tauri-build 🦀: 2.5.5
    - wry 🦀: 0.54.2
    - tao 🦀: 0.34.5
    - @tauri-apps/api  ⱼₛ: 2.10.1
    - @tauri-apps/cli  ⱼₛ: 2.10.0

[-] Plugins
    - tauri-plugin-deep-link 🦀: 2.4.7
    - @tauri-apps/plugin-deep-link  ⱼₛ: 2.4.7
    - tauri-plugin-upload 🦀: 2.4.0
    - @tauri-apps/plugin-upload  ⱼₛ: 2.4.0
    - tauri-plugin-window-state 🦀: 2.4.1
    - @tauri-apps/plugin-window-state  ⱼₛ: 2.4.1
    - tauri-plugin-opener 🦀: 2.5.3
    - @tauri-apps/plugin-opener  ⱼₛ: 2.5.3
    - tauri-plugin-os 🦀: 2.3.2
    - @tauri-apps/plugin-os  ⱼₛ: 2.3.2
    - tauri-plugin-notification 🦀: 2.3.3
    - @tauri-apps/plugin-notification  ⱼₛ: 2.3.3
    - tauri-plugin-dialog 🦀: 2.6.0
    - @tauri-apps/plugin-dialog  ⱼₛ: 2.6.0
    - tauri-plugin-fs 🦀: 2.4.5
    - @tauri-apps/plugin-fs  ⱼₛ: 2.4.5
    - tauri-plugin-store 🦀: 2.4.2
    - @tauri-apps/plugin-store  ⱼₛ: 2.4.2
    - tauri-plugin-updater 🦀: 2.10.0
    - @tauri-apps/plugin-updater  ⱼₛ: 2.10.0
    - tauri-plugin-single-instance 🦀: 2.4.0

[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../out
    - devUrl: http://localhost:3000/
    - framework: React (Next.js)
    - bundler: Webpack

Stack trace

No JavaScript errors or stack traces. The issue is at the WebView/rendering layer. The scroll behavior appears to be triggered by WebKit's automatic "scroll into view" behavior for the text cursor during RTL word wrap, which is more aggressive in Tauri's WebView than in standard browsers.

Additional context

Extensive Debugging Attempts

We've spent many hours attempting to fix this at the JavaScript/CSS level with zero success:

1. CSS Isolation Techniques:

  • overflow-anchor: none on scroll containers
  • contain: layout on editor elements
  • overscroll-behavior: contain
  • isolation: isolate for stacking context

2. ProseMirror/TipTap Plugin:

// Custom plugin to override scrollIntoView
new Plugin({
  view() {
    return {
      update(view) {
        view.scrollIntoView = () => {}; // Disable auto-scroll
      },
    };
  },
});

3. DOM API Overrides:

// Attempted to prevent all scroll mechanisms
editorElement.scrollIntoView = () => {};
window.scrollTo = () => {};

4. Aggressive Scroll Event Prevention:

// MutationObserver watching ALL DOM changes
const observer = new MutationObserver(() => {
  lockedPosition = container.scrollTop;
});

// Scroll event listener with prevention
container.addEventListener(
  "scroll",
  (e) => {
    e.preventDefault();
    e.stopImmediatePropagation();
    container.scrollTop = lockedPosition;
  },
  { passive: false, capture: true },
);

// Window-level scroll prevention
window.addEventListener(
  "scroll",
  (e) => {
    e.preventDefault();
    e.stopImmediatePropagation();
  },
  { passive: false, capture: true },
);

5. Other Attempts:

  • Direction switching with dir="rtl" / dir="ltr" attributes
  • Self-scrolling editor (making editor itself scrollable instead of page)
  • React ref-based scroll restoration (avoiding state updates)
  • Multiple timing strategies (immediate, requestAnimationFrame, setTimeout)

None of these approaches worked. The scroll jump persists despite maximum JavaScript/CSS prevention measures.

Why This is a WebView Issue

  1. ✅ Works perfectly in standard browsers: Same exact code with zero scroll issues in Chrome, Safari, Firefox
  2. ✅ Only RTL + word wrap: LTR text or RTL text without spaces works fine
  3. ✅ JavaScript can't prevent it: Even e.preventDefault() and stopImmediatePropagation() fail
  4. ✅ Timing indicates layout recalculation: The scroll happens specifically when text wraps to a new line

This strongly suggests the WebView layer is triggering scroll behavior that bypasses all JavaScript event handlers and occurs at the native rendering level.

Impact

This bug makes the Tauri app completely unusable for:

  • 🌍 Arabic-speaking users (400+ million speakers)
  • 🌍 Hebrew-speaking users (9+ million speakers)
  • 🌍 Any RTL language users (Farsi, Urdu, etc.)

It's a critical accessibility and internationalization issue.

Requested Solutions

  1. WebView Configuration: Add a Tauri config option to disable automatic "scroll to cursor" behavior
  2. WRY Update: Investigate if newer WRY/WebKit versions handle RTL differently
  3. Native Bridge: Provide a Tauri API to control WebView scroll behavior from Rust
  4. Documentation: If unfixable, document this limitation so developers can work around it

Workaround

The only current workaround is using the web version instead of the desktop app for RTL input, which defeats the purpose of having a desktop app.

Contributor guide