Skip to main content
ansicode

DECSTBM — Set Top/Bottom Margins (CSI r)

Define the vertical scrolling region — rows outside it stay pinned, rows inside scroll.

Byte forms

Every common string-literal form so you can paste-and-search either direction.

\\x1b[\x1b[T;Br
\\033[\033[1;24r
\\e[\e[1;24r
ESC [ESC [ T ; B r
hex1b 5b <T> 3b <B> 72

Description

Set Top and Bottom Margins. Final byte r (0x72); parameters are 1-based row numbers — T (top row, default 1) and B (bottom row, default = screen height). Once set, all scrolling — natural overflow at the bottom row, LF beyond row B, SU / SD (\x1b[NS / T), and the alt screen — operates only on rows T..B inclusive; rows above T and below B stay pinned. Sending \x1b[r (no parameters) resets to the full screen. After DECSTBM the cursor is moved to the home position of the active region (top-left). Every full-screen TUI uses this to keep a status bar (row 1 or N) frozen while the body scrolls. Pair with DECOM (?6h/l) to ALSO clip cursor addressing to the region.

Spec citation: xterm-ctlseqs (DECSTBM, CSI Ps ; Ps r)

Parameters

Ttop row, 1-based (default 1)
Bbottom row, 1-based (default = screen height)

Examples

bash
printf '\033[2;23r'   # rows 2..23 scroll; 1 and 24 pinned\nprintf '\033[r'       # reset to full screen
python
import sys; sys.stdout.write('\x1b[2;23r')
go
fmt.Print("\x1b[2;23r")
javascript
process.stdout.write('\x1b[2;23r')
c
printf("\x1b[2;23r");

Used in

Real-world tools that emit this sequence — anchors the bytes to commands you've already used.

  • tmux, GNU screennarrow DECSTBM around the body region so the bottom status line is excluded from scroll — the bar stays pinned while panes scroll inside the carved region
  • vim, neovim split windowseach window emits DECSTBM with its own top / bottom row pair so `<C-d>` / `<C-u>` scroll only that split, not the whole terminal
  • htop, btop, glances dashboardsheader / footer rows are excluded from scroll; the process / chart region rolls within DECSTBM, header survives every redraw
  • less, more — reserved status linethe bottom `:` prompt row is carved out of scroll via DECSTBM so `j` / `k` scrolling never overwrites the pager status line
  • ncurses setscrreg(3X) / wsetscrreg(3X)the curses scroll-region API translates 1:1 to DECSTBM when the window is the full terminal — TUI libraries built on curses inherit DECSTBM semantics for free

Terminal support

xterm
yes
Linux console (fbcon)
yes
macOS Terminal.app
yes
iTerm2
yes
Windows Terminal
yes
cmd.exe / ConPTY
partial
kitty
yes
alacritty
yes
WezTerm
yes
Ghostty
yes
GNOME Terminal
yes
Konsole
yes
tmux
yes
GNU screen
yes

Related sequences

In the family cookbook

CSI cookbook · 5. Margins & scroll region — DECSTBM `r` and DECSLRM `s`