How is it possible? Because it's implemented that way. ;)
Vim help details this is at the end of the
:h up-down-motions section and it says:
k] put the cursor in the same column (if possible) as it was after the last command that changed the column
Two things that I take from this are
- There is no mention of a builtin alternative that goes straight up/down, and Vim's help is usually pretty good about noting such things. That suggests there isn't one. (I thought for a moment Up and Down arrows would behave differently but they appear to have the same effect. They're off the home row anyways.)
- Since it mentions "the last command that changed the column" that suggests you can precede
k with something like
hl and you'll remain in the column.
So if that's something you prefer you could add to your vimrc:
nnoremap j hlj
nnoremap k hlk
There's a problem, though. That won't work if the cursor is at the beginning of the line. You'll be in the second column since
h can't actually move the cursor. (If you used
lh instead it would break at the end of the line.)
This works better (and has a less "hacky" feel to it)...
nnoremap j :call cursor(getcurpos()+1, 0)<CR>
nnoremap k :call cursor(getcurpos()-1, 0)<CR>
The second parameter is column number. A value of 0 there means you want to stay in the same column.
Be forewarned, though, that this may act funky in some circumstances. For instance, if you're leaning on
k to scroll up/down a bunch of lines (which, to be honest, means you rely on j/k way too much) then once you hit an empty line the cursor will remain in column 1 the rest of the way.
So if there are things that bother you a better idea might be to use some unmapped keys and leave the native commands as is. Use the mappings only when you're in a situation where you definitively want to apply straight up/down movement. One easy-to-remember alternative is
nnoremap <leader>j ....