When searching in Vim, it can be useful to have the text scroll so that the line with the next search hit is in the middle of the screen. That's easy with the built in commands: type n to jump to the next search hit, then zz to vertically center the line. In addition, the 'scrolloff' option can be used to automatically scroll text into view, so that search hits always have some "context" lines before and after.
This tip describes 'scrolloff', and shows some mappings to vertically center search hits automatically. There is also a script with more features.
The 'scrolloff' (scroll offset) option determines the minimum number of screen lines that you would like above and below the cursor. By default, 'scrolloff' is 0 which means that you can move the cursor to any line in the window without causing scrolling.
The following command scrolls the text so that (when possible) there are always at least five lines visible above the cursor, and five lines visible below the cursor:
This option applies to all commands, including searching. After entering the above command (which can be abbreviated as :set so=5), the next search hit will have at least five visible lines of text above and below (except when near the beginning or the end of the buffer).
Entering :set so=999 will keep the cursor vertically centered.
Following are some useful mappings to make search results appear in the middle of the screen:
:nnoremap n nzz :nnoremap N Nzz :nnoremap * *zz :nnoremap # #zz :nnoremap g* g*zz :nnoremap g# g#zz
An alternative to the simple mappings is to use a script that can cycle between different states (only n and N are mapped):
- Normal – No mappings: search next and search previous work as normal (default).
- Scroll hit to middle if not on same page – No scrolling occurs if the next hit is after the first line and before the last line of the window; otherwise, the search hit is scrolled to the middle.
- Scroll hit to middle – The search hit is always scrolled to the middle (when possible).
With the following script in your vimrc, press F4 to cycle the behavior of n and N:
nnoremap <silent> <F4> :call <SID>SearchMode()<CR> function s:SearchMode() if !exists('s:searchmode') || s:searchmode == 0 echo 'Search next: scroll hit to middle if not on same page' nnoremap <silent> n n:call <SID>MaybeMiddle()<CR> nnoremap <silent> N N:call <SID>MaybeMiddle()<CR> let s:searchmode = 1 elseif s:searchmode == 1 echo 'Search next: scroll hit to middle' nnoremap n nzz nnoremap N Nzz let s:searchmode = 2 else echo 'Search next: normal' nunmap n nunmap N let s:searchmode = 0 endif endfunction " If cursor is in first or last line of window, scroll to middle line. function s:MaybeMiddle() if winline() == 1 || winline() == winheight(0) normal! zz endif endfunction
- Searching for basic search information
- Keep cursor vertically centered to keep the cursor line in the middle