With XMonad you can not only control which apps are shown on which screen or workspace but also how app windows are arranged on a single workspace: These window arrangements are called layouts.

One huge benefit of XMonad is that you don’t need to arrange or drag around your windows by hand anymore. Instead they are managed in position and size by XMonad to occupy as much screen space as possible.
More: Windows, Workspaces and screens.

import XMonad.Layout.NoBorders (noBorders, smartBorders)
import XMonad.Layout.Fullscreen (fullscreenFull, fullscreenSupport)
import XMonad.Layout.Grid (Grid(..))
import XMonad.Layout.TwoPane (TwoPane(..))
import XMonad.Layout.Tabbed (simpleTabbed)

myLayoutHook =
  smartBorders $ -- layouts begin below
  noBorders Full
  ||| Tall 1 10/100 60/100
  ||| TowPane 15/100 55/100
  ||| Mirror (Tall 1 10/100 60/100)
  ||| Grid
  ||| simpleTabbed
  -- ...

myConfig = fullscreenSupport $ def
  { layoutHook = myLayoutHook
  }

You should wrap all your layouts in smartBorder which removes borders whenever you have only one screen with a single visible window. You combine layouts with ||| so that you can apply layout modifiers like smartBorders either to a single layout like

smartBorders Grid

or to a combination of layouts like

smartBorders (Full ||| Grid)

Every workspace will have its own active layout. By default it will be the first in your myLayoutHook list, which in this example is noBorders Full.

Common adjustable layouts

There are a huge variaty of layouts available in the xmonad-contrib package; namely every module that starts with “XMonad.Layout”. A few of the most common are listed and explained below:

Full Show only a single window and stretch this window to fill the entire screen. The shown windows is the currently focused one while all other opened windows are hidden behind it. You can switch focus and cycle through the opened windows with Mod+j and Mod+k. It looks as follows:
XMonad windows in Full layout
Unfortunately, Full will still show an annoying border around the window. To make this border disappear, use noBorders.
noBorders <otherLayout>

Hide borders. It modifies an existing layout. For example, layout Grid with and without borders looks like:
XMonad windows in Grid layout
XMonad windows in Grid layout with noBorders modifier
It is especially usefull with full screen layouts. For example, layout Full with and without borders looks as follows:
XMonad windows in Full layout
XMonad windows in Full layout with noBorders modifier
To make it available in your config, add

import XMonad.Layout.NoBorders (noBorders)
to the top of your file.
Tall <#master> <#delta> <#masterSize

Divide the screen into two columns: a left “master pane” column and a right “slave pane”. You define how many windows are allowed in the master pane with <#master>, how much the master pane size grows in width with <#delta>, and how big the master pane is in width inititally with <#masterSzie>.

For example, Tall 2 10/100 60/100 allows 2 windows in the master pane (additional windows appear and divide the space in the slave pane), initially uses 60 percent of the screen’s width for the master pane and increases, respectively decreases the master pane’s size by 10 percent of the screen’s width whenever you press Mod+h, respectively Mod+l. These are the default keymaps for shrinking and expanding the master pane.

For example, Tall with a single window in the master pane looks as follows:
XMonad windows in Tall layout
And Tall with two master windows looks like:
Other XMonad windows in Tall layout

Tall is the default layout if you don’t define myLayoutHook yourself.

TwoPane <#delta> <#masterSize

Divide the screen into two columns like Tall. The left column is the “master pane”, the right is the “slave pane”. Unlike Tall it only ever shows one window in the master pane and one window in the slave pane. Additional windows can be cycled through in the slave pane.

For example, TwoPane 15/100 55/100 uses 55 percent of the screen width for the master pane and whenever you press the default keymaps for shrinking and expanding the master pane, Mod+h and Mod+l, it increases, respectively decreases the master pane size by 15 percent of the screen width.
XMonad windows in TwoPane layout
To make it available in your config, add

import XMonad.Layout.TwoPane (TwoPane)
to the top of your file.
Mirror <otherLayout>

Rotate an existing layout 90 degrees clockwise. For example, you can use it with Tall or TwoPane to have an horizontal master row and a slave row instead of a vertical ones. For example, Mirror wrapped around Tall with a single master window looks like:
XMonad windows in Tall layout with Mirror modifier
To make it available in your config, add

import XMonad.Layout (Mirror)
to the top of your file.
Grid Divide all windows evenly on the screen space like on a grid. It looks like:
XMonad windows in Grid layout
And with some even more windows it looks like:
Other XMonad windows in Grid layout
simpleTabbed

Like Full show a single window, the currently focused one, and hide all others. However, show a list of all opened windows, called “tabs” like in a browser, at the top of the screen. Like Full it can be cycled through with the default focus-shifting keymaps Mod+j and Mod+k. It looks like:
XMonad windows in simpleTabbed layout

fullscreenSupport

Allow XMonad to react and show an app on the entire screen when the app changes from window to fullscreen mode, even though the active layout would show many windows on the screen.

There are two styles of full-screen. First, there is “XMonad full-screen” meaning that XMonad shows only one window and this window is stretched to fill the entire screen. However, the app being shown in this window may not be in its full-screen mode but still in its window mode. For example, the video player VLC in its window mode looks like:
VLC app in window mode tiled in XMonad
When we use a layout like Full this VLC window is stretched to fill the entire screen by XMonad, which we call “XMonad full-screen”. However, VLC is still in its window mode.
VLC app in window mode covering whole XMonad screen

Second, is “app fullscreen” which is the full-screen mode of an app. In this mode an app fills its entire given window space, even though this space may be only a part of the screen. For example, if use a layout like Tall and switch VLC into its full-screen mode, it looks like this:
VLC app in full-screen mode tiled in XMonad
VLC thinks that this space (given by XMonad) is the entire screen, but it isn’t.

With fullscreenSupport we tell XMonad to react and change into “XMonad full-screen”, that is, to use the entire screen for a single app, whenever the app changes into “app fullscreen”. For example, when a layout like Tall with fullscreenSupport shows several windows and none of them is in “app fullscreen”, the windows are arranged like in a normal Tall layout:
XMonad windows in Grid layout with fullscreenSupport layout modifier
However, when an app like VLC switches into its full-screen mode, the fullscreensupport kicks in so that this app covers the entire screen:
XMonad windows with full-screen app and fullscreenSupport layout modifier

Tags: xmonad layouts tutorial haskell configuration

Malte Neuss

Java Software Engineer by day, Haskell enthusiast by night.

Other Posts In Series

Just Enough Haskell For XMonad

Useful XMonad shortcuts

Knowing and customizing shortcuts is the essence of being productive with XMonad. To get some inspiration it’s helpful to look at how built-in and other shortcuts are defined.

Read More

Just Enough Haskell For XMonad

Learn Haskell Types and Records with XMonad's XConfig example

Small changes to XMonad like changing keyboard shortcuts require little Haskell knowledge. However, bigger customizations, especially adapting other people’s configurations, are easier when you understand Haskell types and records.

Read More

Just Enough Haskell For XMonad

Learn Haskell Functions with XMonad's XConfig example

Small changes to XMonad like changing keyboard shortcuts require little Haskell knowledge. However, bigger customizations, especially to organize your code when adapting other people’s configurations, are easier when you understand Haskell functions.

Read More