# 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:

bash
name	value	status
alice	senior	dev
bob	junior	ops

Each gap is a single tab character, displayed as 8 spaces (the default tabstop). You want to edit the second column. In visual block mode:

vim
Ctrl+V

Move 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:

vim
set virtualedit=block

With 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.

vim
set virtualedit=block

Options 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. 1.Position cursor at the start of the column
  2. 2.Press Ctrl+V to enter visual block mode
  3. 3.Move down and right to select the desired block
  4. 4.Press c to change, I to insert at start, or A to append at end

Example: adding a prefix to each line in a column:

vim
:set virtualedit=block
Ctrl+V    " Enter visual block
jj        " Select three lines
I// <Esc> " Insert // at the start of the block

Alternative: Convert Tabs to Spaces

If you work with columnar data frequently, consider using spaces instead of tabs:

vim
:set expandtab
:set tabstop=4
:set shiftwidth=4

Then convert existing tabs to spaces:

vim
:set expandtab
:retab

With spaces, every character occupies exactly one column on screen, and visual block mode works exactly as you expect.

Checking Current Tab Settings

vim
:set tabstop?
:set softtabstop?
:set shiftwidth?
:set expandtab?
  • tabstop -- How many spaces a tab character displays as
  • softtabstop -- 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:

vim
set tabstop=4
set softtabstop=4
set shiftwidth=4
set expandtab

Visual 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:

vim
/^I

This 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:

vim
: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.

vim
:set nolist

Turn off the display when done.