Qutebrowser setup


Firefox was becoming annoying and bloated, and so I decided to go back to using Qutebrowser , a project I’d been following for a while. It’s a minimalistic web browser, which is massively extensible and keyboard driven, with default vim-like keybindings. This is about how I’ve set it up. Qutebrowser is configured using a python file called config.py which is normally found in ~/.qutebrowser/config.py.

Qutebrowser screenshot

The tab bar

By default, the tab bar looks like this:

Default tab bar

It’s pretty ugly, it doesn’t have much padding around the text and the text is quite small.

This is how I’ve modified it:

My tab bar

The relevant lines of the config.py are:

# Open new tabs in the background.
c.tabs.background = True

# Show favicons in the tab bar.
c.tabs.favicons.show = False

# Position of new tabs opened from another tab.
c.tabs.new_position.related = 'next'

# Padding (in pixels) around text for tabs.
c.tabs.padding = {'bottom': 8, 'left': 5, 'right': 5, 'top': 8}

# Position of the tab bar.
c.tabs.position = 'top'

# Alignment of the text inside of tabs.
c.tabs.title.alignment = 'center'

# Format to use for the tab title
c.tabs.title.format = '{index}: {title} - {host}'

# Width of tab indicators.
c.tabs.indicator.width = 3

# Padding (in pixels) for tab indicators.
c.tabs.indicator.padding = {'bottom': 0, 'left': 0, 'right': 5, 'top': 0}

# Background color of the tab bar.
c.colors.tabs.bar.bg = '#555555'

# Color gradient start for the tab indicator.
c.colors.tabs.indicator.start = 'black'

# Color gradient end for the tab indicator.
c.colors.tabs.indicator.stop = 'black'

# Color for the tab indicator on errors.
c.colors.tabs.indicator.error = 'black'

# Color gradient interpolation system for the tab indicator.
c.colors.tabs.indicator.system = 'rgb'

# Foreground color of unselected odd tabs.
c.colors.tabs.odd.fg = 'black'

# Background color of unselected odd tabs.
c.colors.tabs.odd.bg = 'lightgrey'

# Foreground color of unselected even tabs.
c.colors.tabs.even.fg = 'black'

# Background color of unselected even tabs.
c.colors.tabs.even.bg = 'lightgrey'

# Foreground color of selected odd tabs.
c.colors.tabs.selected.odd.fg = 'black'

# Background color of selected odd tabs.
c.colors.tabs.selected.odd.bg = 'darkgrey'

# Foreground color of selected even tabs.
c.colors.tabs.selected.even.fg = 'black'

# Background color of selected even tabs.
c.colors.tabs.selected.even.bg = 'darkgrey'

Tabs are always at the top of the screen. Tabs are all lightgrey unless they are selected, then they become darkgrey, regardless of whether they are odd or even numbered. The foreground text is black and the tab indicator is black. I didn’t like the gradient that shows on the tab indicator when a tab is loading, so it just stays black (c.colors.tabs.indicator.start, c.colors.tabs.indicator.stop). The text in the tabs is centred and a bit bigger than the default and each tab lists the number of the tab ({index}), the name of the webpage ({title}) and the top level domain ({host}).

c.tabs.indicator.padding = {'bottom': 0, 'left': 0, 'right': 5, 'top': 0} means that the tab indicator is positioned a minimum of 5 pixels left of any text in the tab.

Annotated tab bar

Status bar

Default status bar

The default status bar and completion bar are super ugly, with a dark gradient background style which doesn’t really fit with the colour scheme of the default tab bar. I want it to have a similar colour style to my custom tab bar. These are the relevant lines from the config.py:

# Height (in pixels or as percentage of the window) of the completion.
c.completion.height = '30%'

# Padding (in pixels) for the statusbar.
c.statusbar.padding = {'bottom': 5, 'left': 5, 'right': 5, 'top': 5}

# Widgets in statusbar
c.statusbar.widgets = ["keypress", "url", "scroll", "history", "tabs", "progress"]

# Position of the status bar.
c.statusbar.position = 'bottom'

# Text color of the completion widget
c.colors.completion.fg = 'black'

# Background color of the completion widget for odd rows.
c.colors.completion.odd.bg = '#F2F2F2'

# Background color of the completion widget for even rows.
c.colors.completion.even.bg = 'lightgrey'

# Foreground color of completion widget category headers.
c.colors.completion.category.fg = 'black'

# Background color of the completion widget category headers.
c.colors.completion.category.bg = 'lightgrey'

# Foreground color of the selected completion item.
c.colors.completion.item.selected.fg = 'black'

# Background color of the selected completion item.
c.colors.completion.item.selected.bg = 'darkgrey'

# Top border color of the completion widget category headers.
c.colors.completion.item.selected.border.top = 'black'

# Bottom border color of the selected completion item.
c.colors.completion.item.selected.border.bottom = 'black'

# Foreground color of the matched text in the completion.
c.colors.completion.match.fg = '#ff4444'

# Color of the scrollbar handle in the completion view.
c.colors.completion.scrollbar.fg = 'white'

# Color of the scrollbar in the completion view.
c.colors.completion.scrollbar.bg = 'darkgrey'

# Foreground color of the statusbar.
c.colors.statusbar.normal.fg = 'black'

# Background color of the statusbar.
c.colors.statusbar.normal.bg = 'darkgrey'

# Background color of the statusbar in insert mode.
c.colors.statusbar.insert.bg = '#039B9A'

# Foreground color of the statusbar in private browsing mode.
c.colors.statusbar.private.fg = 'black'

# Foreground color of the statusbar in command mode.
c.colors.statusbar.command.fg = 'black'

# Background color of the statusbar in command mode.
c.colors.statusbar.command.bg = 'darkgrey'

# Default foreground color of the URL in the statusbar.
c.colors.statusbar.url.fg = 'black'

# Foreground color of the URL in the statusbar on error.
c.colors.statusbar.url.error.fg = 'orange'

# Foreground color of the URL in the statusbar for hovered links.
c.colors.statusbar.url.hover.fg = 'blue'

# Foreground color of the URL in the statusbar on successful load
c.colors.statusbar.url.success.http.fg = 'black'

# Foreground color of the URL in the statusbar on successful load
c.colors.statusbar.url.success.https.fg = 'black'

# Foreground color of the URL in the statusbar when there's a warning.
c.colors.statusbar.url.warn.fg = 'black'
My status line

The completion widget needs different colours for odd and even rows, otherwise it’s difficult to discriminate between rows. So they alternate between a very light grey for odd rows (c.colors.completion.odd.bg = '#F2F2F2') and lightgrey for even rows. The text is always black in the completion bar and the status bar. Warnings on the status bar take their default colours of amber and red. The completion bar headers are also light grey and the selected completion item comes up as dark grey with a black border on the top and bottom. As text is matched it becomes red. The scrollbar is visible and follows the same colour pattern as the rest of the setup.

When open, the completion box takes up 30% of the screen.

When you enter insert mode to enter text into a web page field, the statusbar turns blue a la vim.

The statusbar has information on the current url (url), how far through the file you are (scroll), what tab is visible (tabs) and when a page is loading, the progress bar (progress).

Annotated status bar


The fonts are very simple, basically everything is either monospace 8pt or monospace 9pt, e.g.

# Font used in the completion widget.
c.fonts.completion.entry = '8pt monospace'


Qutebrowser has this really nice hinting system, you press f and the screen is filled with all the links you could click, you then type the corresponding letter code and it follows that link. Normally the hints look like this:

Default hints

The relevant bits of the config.py are:

# CSS border value for hints.
c.hints.border = '2px solid black'

# Font color for hints.
c.colors.hints.fg = 'white'

# Background color for hints.
c.colors.hints.bg = 'black'

# Font color for the matched part of hints.
c.colors.hints.match.fg = 'lime'

The hints are black with white text. Matched letters become lime green.

My hints


I have a few keybindings that are different to the default setup, mainly to make it feel more vim-like:

# keybindings for normal mode
config.bind('<backspace>', 'back')
config.bind('gT', 'tab-prev')
config.bind('gt', 'tab-next')
config.bind('q', None)
config.bind('qq', 'quit')
config.bind('<Meta-R>', 'reload')
config.bind('l', 'forward')
config.bind('h', 'back')

Unbinding q is necessary so it doesn’t match anything when I’m typing qq to quit.

The reload bind is because Cmd-r is so engrained in me for reloading a page, from other web browsers, though I’m using it less and less

The full config.py can be found here