Center buffers in Neovim

15. October 2025

This time I want to share how to center a single buffer in Neovim using only Lua and no plugins. I have not found much on this topic on the web, so I hope this helps some people!

A screenshot of Neovim with a centered buffer.

This only works on Neovim, afaik, because Vim can't yet modify the statuscolumn, like Neovim.

Note: I used Neovim v0.10.4 on Debian 13, while writing this blogpost. Statuscolumn was introduced in Neovim v0.10. This won't work with older versions.

No plugins, please

Before we dive into how to achieve this, I want to explain why I didn't use plugins. First, all plugins I found use multiple empty side windows to center the main window. In my opinion that solution is sub-optimal, because this can interfere with my workflow.

Secondly, my personal preference is to use only plugins, I really need. I don't like relying on third party dependencies and I prefer using simple and stable software. Neovim can already do a lot out of the box and if something is missing, I can add it with Lua. That is what a hackable editor is all about.

The third reason is that I use Debian. Debian does not distribute the latest bleeding edge software. The goal of Debian is to create a stable and reliable operating system. This means I don't have the latest version of Neovim installed. Most plugins move fast and require the latest version. Fewer plugins mean less trouble and version incompatibilities.

If you are interested, you can find my tiny Neovim configuration on Codeberg.

The problem

When I started using Neovim, I still had a different opinion on plugins, so I used a lot of them. NERDTree was my file explorer for some months. I always had a NERDTree buffer open on the left side, that centered the active buffer. Just like all the normal editors and IDEs have.

But time passed and I switched NERDTree for oil.nvim. Oil integrates better with the Vim workflow has no permanently open side pane. If you need to explore the current directory, you do it in a buffer. When you are done, the buffer disappears. This week I even got rid of oil.nvim for the good old default Netrw.

But without a side pane, always looking left, does not feel right :-) I guess my neck agrees with this.

The solution

I simply want to center horizontally the current window, if it is alone. If more exists or Neovim does not occupy the whole screen, they should align to the left. But if windows are separated vertically, they should be centered again.

The trick is adding a lot of spaces to the statuscolumn, if needed.

First you need to know the width (column count) of Neovim, while it is using the whole screen. For that, run the following command in Neovim.

:lua print(vim.api.nvim_win_get_width(0))

In my case, the width is 191 columns. This can vary depending on font and screen size. The width is hard-coded for now and needs to be adapted manually, if needed.

By adding the following code to your init.lua file, you get the above described behavior.

local full_screen = 191

-- default status column, simply 2 spaces
local statuscolumn = "  "
-- status column if only one buffer is open
-- (full_screen - text width) / 2
local statuscolumn_wide = string.rep(" ", (full_screen - 100) / 2) .. statuscolumn

-- set default
vim.o.statuscolumn = statuscolumn

-- check window list count and adapt padding
vim.api.nvim_create_autocmd({
    'BufEnter', 'BufWinEnter', 'BufWinLeave', 'WinEnter', 'WinLeave', 'WinResized', 'VimResized'
}, {
  callback = function()
      local winwidth = vim.api.nvim_win_get_width(0)
      if winwidth > (full_screen / 2) then
        vim.o.statuscolumn = statuscolumn_wide
      else
        vim.o.statuscolumn = statuscolumn
      end
  end,
})

Note that this triggers on different events, like WinResized, BufEnter and so on. That makes windows adapt dynamically during runtime, depending on the screen width. If you reduce the size of the terminal, the window will act accordingly.

Further fine-tuning

This setup only adds spaces to the status column, without any line number or other symbols. You can simply add one of the following codes to the statuscolumn variable defined above.

%l	line number of currently drawn line
%r	relative line number of currently drawn line
%s	sign column for currently drawn line
%C	fold column for currently drawn line

For example this would show the line numbers.

local statuscolumn = " %l"

You can also use different colors for uneven rows for example, or whatever comes to your mind. Simply read the docs for more information on that.

:help statuscolumn

One final thing must be said about performance. In the statuscolumn docs you might see a WARNING about statuscolumn.

WARNING: this expression is evaluated for each screen line so defining
an expensive expression can negatively affect render performance.

Keep this in mind if you want to keep your Neovim fast and snappy.

Every feedback is welcome

Feel free to write me an email at info@simondalvai.org and comment on Mastodon.

mastodon button Codeberg button Email button RSS button