welcome: please sign in
location: Appearance

1. Overview

Conkeror provides a set of primitives to help you change the appearance of not only Conkeror itself, but also of web content, in your rc. Most appearance changes that you probably want to make can be done by writing style sheets, which is the topic of this article. We won't go into the syntax of CSS itself, as there are already many books and online publications devoted to that topic. In this article, we will explore how to load stylesheets in Conkeror, and get an understanding of some of the common difficulties in dealing with CSS.

If you have experience with Firefox, you may be familiar with using userChrome.css or the Stylish extension to make these kinds of customizations. While both of those approaches can work with Conkeror, we find it preferable to customize appearance in the rc because it keeps all of your configuration in a central location with the power and convenience of maintaining it with your favorite text editor and version control tools.

2. Single Stylesheets

Single stylesheets can be loaded and unloaded by two pairs of utility functions: register_agent_stylesheet, unregister_agent_stylesheet, and register_user_stylesheet, unregister_user_stylesheet. The difference between an agent sheet and a user sheet is in cascade precedence. The CSS2 specification gives a very cogent explanation of the cascade. If you wanted a rule of thumb, use agent sheets for chrome and user sheets for content.

2.1. Loading a File Stylesheet

Each of the utility functions so far mentioned are called with a string URL or nsIURI as their sole argument. So to get underway with some examples, assume the following scenario. My .conkerorrc is a directory in my home directory. That means Conkeror will load all .js files in that directory at startup. Within .conkerorrc, I have made a subdirectory called stylesheets, and I have place several .css files in it. The cross-platform way to load one of these sheets is like this:

let (sheet = get_home_directory()) {
    sheet.append(".conkerorrc");
    sheet.append("stylesheets");
    sheet.append("foo.css");
    register_user_stylesheet(make_uri(sheet));
}

Of course, if you don't need Windows compatibility, you could shorten the foregoing example by using sheet.appendRelativePath(".conkerorrc/stylesheets/foo.css"); instead of the three calls to append. Or if you didn't need any multi-platform compatibility, you could simply provide a literal file: url to the css file as a string. If you have many sheets to load, you can use a for loop and the methods and properties of nsILocalFile to load many sheets at once. But we will leave the teaching of JavaScript to other tutorials.

2.2. Loading an Inline Stylesheet

It is also possible to include the source of a stylesheet inline in your rc. This is done by encoding the stylesheet as a data: url, and it provides a convenient way to write short stylesheets without cluttering your filesystem. A simple one would look like this, in Conkeror:

"data:text/css,"+escape("body{background:black; color:white;}")

2.2.1. make_css_data_uri

Conkeror provides a utility to simplify the construction of such urls, called make_css_data_uri. It takes one positional argument, rules, and the keyword arguments $namespace, $domains, $urls, $url_prefixes, and $regexps. A description of each of these parameters follows.

rules
css rules, not including any @namespace or @-moz-document headers. given as a string or an array of strings.
$namespace
optional string url for a @namespace header.
$domains
optional string, or array of strings, for a @-moz-document domain(...) header.
$urls
optional string, or array of strings, for a @-moz-document url(...) header.
$url_prefixes
optional string, or array of strings, for a @-moz-document url-prefix(...) header.
$regexps

optional string or RegExp, or array of strings or RegExps, for a @-moz-document regexp(...) header. This header is only available in XULRunner 6 or higher.

Now some examples. Here is how I make a dark style for Astronomy Picture of the Day.

// darken apod
register_user_stylesheet(
    make_css_data_uri(["body{background: black !important; color: grey !important;}",
                       ":link, :link * {color: #4986dd !important;}",
                       ":visited, :visited * {color: #d75047 !important;}"],
                      $url_prefixes = "http://apod.nasa.gov/apod/"));

3. Styling Chrome

A window in Conkeror is a XUL document, commonly referred to as "chrome". Chrome includes such visual elements as the mode-line, the minibuffer, and the tab-bar. For simple customizations, these elements can be styled just as you would style content. If you wanted to make more extensive changes, then you could write a theme instead, or you may find that using a GTK theme is the most appropriate way to do what you want. Both of these options will be discussed later.

The only difference between a stylesheet for styling chrome and one for styling content is that in the former, you specify that the sheet applies to the XUL namespace.

3.1. Namespaces

To make a stylesheet which only affects Conkeror's gui, put the following line before the css rules in your stylesheet. (If the stylesheet contains any @import directives, @namespace must come after all @imports, and before any css rules.)

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");

For inline sheets, make_css_data_uri provides a compact syntax for specifying the namespace. You provide the namespace keyword like so: $namespace = XUL_NS. In the following example, we increase the font size of the minibuffer and mode-line, and color the prompt red.

register_user_stylesheet(
    make_css_data_uri(["#minibuffer, .mode-line {font-size: 16px;}",
                       "#minibuffer-prompt {color:red;}"],
                      $namespace = XUL_NS));

4. Using a GTK2 Theme

Suppose you want to make extensive changes to the colors of the Conkeror gui, like using dark colors. Generally, using a GTK2 theme will be the simplest way to do this, and whether you use an existing GTK2 theme or write your own, it has the benefit of being reusable for all GTK2 programs, rather than limited to one. GTK2 themes can also style things that Conkeror's theme system is not capable of, like scrollbars and form elements in content. Conkeror's default styling will use your system-wide GTK2 theme automatically, or alternatively, you can arrange to use a specific GTK2 theme just for Conkeror.

To use a particular GTK2 theme only for Conkeror, create a file, ~/.gtkrc-2.0.conkeror that looks something like this (modified to suit your needs):

## uncomment and adjust the following line if you also want
## to load your default .gtkrc-2.0:
#include "/home/YOU/.gtkrc-2.0"

include "/home/YOU/.themes/SomeTheme/gtk-2.0/gtkrc"

GTK2_RC_FILES=~/.gtkrc-2.0.conkeror conkeror

5. Theming

In physical terms, a theme is a directory containing a group of .css files, and an index file called theme.json.

theme_load_paths is a variable like load_paths, but it gives chrome directories and file directories that contain themes. Example:

theme_load_paths.unshift("/path/to/my-themes-root/");

Themes require the theme.json index file because it is both simpler implementationally, and faster to load a theme, if Conkeror does not have to search for all of the .css files itself. (Themes can be stored in chrome:// urls, and it is non-trivial to get a list of files in a "chrome directory".)

Example theme.json file:

{ "sheets": [
      "tab-bar--my-theme.css",
      "new-tabs--my-theme.css"
  ]
}

The .css files themselves are specially named. The part of the basename before an optional double-hyphen separator is the name of the module that this stylesheet is for. Following the optional double-hyphen is a name for this specific stylesheet.

Multiple themes may be loaded in what we call a "theme stack". Stylesheets from themes higher in the stack override stylesheets of the same name lower in the stack.

To load a theme:

theme_load("my-theme");

To unload a theme:

theme_unload("my-theme");

5.1. Provided Themes

5.1.1. Base Themes

default
The default theme, automatically loaded at startup. It styles Conkeror to use the system GTK2 style.

5.1.2. Accessory Themes

gesso
This theme is a convenience layer for people who want to style the UI to use colors other than system colors. It is meant to be loaded on top of the default theme to counteract certain things which are problematic for people who want to use non-system colors. It's like a priming coat for color themes, and that is why the name is "gesso".
mono
The mono theme makes the default font of Conkeror's UI monospace.

6. Preventing background flashes

If one is using a dark gtk theme then there may be a dark background flash when loading a new buffer. By loading the following stylesheet Conkeror will have a white background when loading a new buffer, and since the web mostly has a white background, there will be fewer background color flashes.

register_user_stylesheet(make_css_data_uri(["@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul); browser { background-color: #ffffff !important; }"]));

If one is using a global dark user stylesheet for pages themselves, there will be an annoying white background flash when loading a new buffer even without the above code. Use the above code substituting #000000 (change as needed) for #ffffff and use the following code:

session_pref("browser.display.background_color", "#000000");

7. Resources

When using CSS to modify chrome or webpage appearance, the obscur rules for precedence in CSS selectors confound even the wise at times. We list particularly good articles on this subject here, which will hopefully help Conkeror hackers have more success in their themes and schemes.

Conkeror.org: Appearance (last edited 2014-11-06 18:17:27 by scottjad)