# Fix Vim Visual Block Mode Misaligned on Tab Characters
You enter visual block mode in Vim (Ctrl+V) to edit a column of text, but the block selection appears misaligned. The visual block does not match the apparent column positions on screen, and edits affect the wrong characters.
This is one of the most frustrating Vim behaviors, and it stems from the difference between how tabs are stored (as single \t characters) and how they are displayed (as multiple spaces on screen).
The Problem Demonstrated
Consider this file with tab characters:
name value status
alice senior dev
bob junior opsEach gap is a single tab character, displayed as 8 spaces (the default tabstop). You want to edit the second column. In visual block mode:
Ctrl+VMove down and right to select the second column. But the block does not align with the visible text edges -- it selects based on the byte position in the file, not the screen position.
The Solution: virtual_edit
Enable virtualedit to allow visual block selection based on screen position:
set virtualedit=blockWith this setting, Vim allows the cursor to move to any screen position, even past the end of a line or into the middle of a tab character. Visual block selections now align with what you see on screen.
set virtualedit=blockOptions for virtualedit:
- block -- Allow block selection past end of line (recommended)
- all -- Allow cursor anywhere, even past end of line in any mode
- insert -- Allow cursor past end of line in insert mode
- onemore -- Allow cursor one character past end of line
Using virtual_edit for Column Editing
With virtualedit=block set:
- 1.Position cursor at the start of the column
- 2.Press
Ctrl+Vto enter visual block mode - 3.Move down and right to select the desired block
- 4.Press
cto change,Ito insert at start, orAto append at end
Example: adding a prefix to each line in a column:
:set virtualedit=block
Ctrl+V " Enter visual block
jj " Select three lines
I// <Esc> " Insert // at the start of the blockAlternative: Convert Tabs to Spaces
If you work with columnar data frequently, consider using spaces instead of tabs:
:set expandtab
:set tabstop=4
:set shiftwidth=4Then convert existing tabs to spaces:
:set expandtab
:retabWith spaces, every character occupies exactly one column on screen, and visual block mode works exactly as you expect.
Checking Current Tab Settings
:set tabstop?
:set softtabstop?
:set shiftwidth?
:set expandtab?tabstop-- How many spaces a tab character displays assofttabstop-- How many spaces the Tab key inserts (0 = use tabstop)shiftwidth-- How many spaces for auto-indent and>>/<<expandtab-- Whether Tab inserts spaces instead of a tab character
For consistent column editing, these should typically all be the same value:
set tabstop=4
set softtabstop=4
set shiftwidth=4
set expandtabVisual Block With Mixed Tabs and Spaces
If a file has both tabs and spaces (common in code with inconsistent formatting), visual block mode becomes even more unpredictable. Detect mixed indentation:
/^IThis searches for tab characters. If you find tabs mixed with spaces in the same file, normalize them:
```vim " Convert all tabs to spaces :set expandtab :retab
" Or convert all leading spaces to tabs :set noexpandtab :retab! ```
The ! flag on :retab affects all whitespace, not just leading whitespace.
Displaying Tabs Visually
To see where tab characters are:
:set list
:set listchars=tab:>\ ,trail:·This displays tabs as > followed by spaces, and trailing whitespace as ·. Seeing the actual tab positions makes it much easier to understand why visual block selections are misaligned.
:set nolistTurn off the display when done.