Manual:Skinning Part 2

If you're a person who prefers learning from examples, a basic skin built according to this guide exists. See Skin:Example for details and downloads.

Introduction
Let's start with the skin name – we'll call ours "Foo Bar" for tutorial purposes – and the blank files. You should come up with a name of your own for your skin.

When building a skin you'll be working with your skin name in two forms (and a half): In our example skin, these are, respectively, "Foo Bar",  and.
 * The localized skin name is displayed to wiki users in their preferences, where they can choose the skin to use. It may contain anything whatsoever, including spaces, and may be translated into other languages. It should be used as the name of skin description page here on MediaWiki.org if you decide to create one.
 * The skin name, usually CamelCased, is used as a part of the names of PHP classes used by the skin. It may only contain Latin letters and numbers (A-Z, a-z, 0-9)..
 * The lowercase skin name, identical to the skin name but lower cased, it is used for names of site-wide and user CSS/JS customization pages, for the name of the localization message used to define the localized skin name, and internally as value of the 'skin' user preference, parameter &useskin=, and identifier for the skin in JS and CSS requests.

The name of the subdirectory under skins/ where your skin will be placed should be equal to either the skin name or its lowercase version (this guide uses the CamelCase skin name). The same name should also be used for the main .php file of the skin (see below) and as the name of the repository if you put the skin in version control.

Wherever we use "Foo Bar",  or   in examples, remember to replace those with the name of your own skin.

The Example skin
To start building your skin, download or clone the Example skin to a new directory in your skins/ folder, in our case skins/FooBar/.

Boilerplate and definitions
For this tutorial you should have the following blank files and empty subdirectories to start with. If you are using non-ANSI characters, ensure that the files are coded with UTF-8 (without BOM). Starting with MediaWiki 1.25, it is possible to define the boilerplate in JSON format. This is the recommended way for skins compatible with only newer MediaWiki versions. The older PHP way is currently still supported, but deprecated. See Manual:Extension registration for details and migration guide.
 * : the entry point containing metadata and definitions of resources used by your skin. This filename must be exactly this or the MediaWiki engine cannot load your skin.
 * Before MediaWiki 1.25, the entry point was defined in
 * : will contain the actual skin code.
 * : directory for localisation messages and their translations.

Start with the documentation header. The practice of including this metadata can help with documentation generation. The  and   are organizational and should be left as-is, while you'll want to customize the   and   to what's correct for your skin. You can note the typical practice for each is  or   and. For MediaWiki 1.25 and later, the  file is already machine-readable.

Like extensions you may want to include a quick bit of boilerplate to prevent running standalone and credits so when installed people know who authored your skin: Be sure to customize things to what's correct for you too.

Next we want the boilerplate to declare our skin's name, auto loaded classes, and localisation messages (the content of the files and directories references here is described in the latter sections):

The value provided in the  line, prepended with "Skin", is used as the name of your skin's main PHP class: the name of the class for your skin must be "Skin{Your Identifier}" (in this example,  ). Keep that in mind since that means that you do want to replace the  in   above with the identifier for your skin, and likewise you will want to do so in the class names in the .skin.php file.

Skin styles and scripts (Resource Loader modules)
To provide styles and/or scripts for your skin, you must define ResourceLoader modules that include them. The 'styles' array itself does not have to be a single style sheet, ResourceLoader combines all the style sheets into a single style sheet so you can separate your style sheet into as many separate files as you want. You'll probably want to read up on ResourceLoader because it has other features like @embed and RTL flipping to consider when writing the CSS for your skin.
 * You can use  or   with MediaWiki version 1.22 and up.
 * You can use three Resource Loader modules to get some common content styling without having to copy it into your own CSS: 'mediawiki.skinning.elements', 'mediawiki.skinning.content' and 'mediawiki.skinning.interface', which provide progressively more default styling. They can be loaded like any other module (see the example in "Skin code" section below). We will use 'mediawiki.skinning.interface'.
 * The modules are available as of MediaWiki 1.23.

MediaWiki 1.24 adds a global which allows skins to define custom styles for particular Resource Loader modules.

Only add a module for 'scripts' if your skin actually needs custom JavaScript:

Localisation messages
The next thing you'll want to deal with is the i18n files. These are stored in the JSON format.

At minimum you are going to need two i18n messages in English: One for the skin name so that it displays correctly in the lists of skins in Special:Preferences where the user selects his or her skin, and another for the credits that will be visible on Special:Version.

Create a file  with the following contents:

You'll want to customize the keys and contents of both messages ( is the description that will appear on Special:Version) and the authorship metadata. You can add translations in further files named after language codes, e.g.  for German and   for Spanish. A special "language code" of  is for documentation explaining the message keys.

The above way is only compatible with MediaWiki 1.23 and later. To be compatible with earlier versions up to and including MediaWiki 1.17, you should provide a compatibility shim file. The generateJsonI18n.php maintenance script generates one. You invoke it by entering the following command line: php maintenance/generateJsonI18n.php --shim-only skins/FooBar/FooBar.i18n.php skins/FooBar/i18n/. You declare it by adding another line in main skin file below :

Skin code
The last PHP file to deal with now is the  file where the bulk of our actual skin is. In this tutorial, the two classes of the skin are in this single file.

Start with the usual header comment:

Extend SkinTemplate
Then extend the  class.

SkinFooBar is your class in  (or   for MW 1.25 and earlier) from above. It inherits a lot of functionality from the  class, which  sets up many of the elements described in Skinning Part 1 that a MediaWiki skin needs to render. Also many MediaWiki extensions "hook" into events it fires such as  and   in order to add elements to skins.

You'll want to update the skin name and also the  and   variables (the first declares the internal skin name used for  again, the second declares the directory name used in  definitions again).

Both the  and   functions import the necessary ResourceLoader modules you declared in your skin.json file. Remember to update the key there!

Extend BaseTemplate
In addition to implementing a lot of common skin functionality, class  approaches skin construction by relying on a separate template class that outputs the HTML markup for the skin. Hence its name "SkinTemplate" – it isn't the template, it's a kind of skin that uses a template.

This separate template class usually extends the  class, which defines various useful methods to organize and output items for a skin, such as ,  , etc. in turn extends the  class, which provides some convenience methods to   and   items in the template.

This is the outermost part of the boilerplate. Keep in mind that headelement defines the  tag itself, so you shouldn't include one. If you want to add some attributes or classes to the body tag, override the  method in your SkinFooBar class.

Now we get into your actual skin-specific markup here. Because that's entirely dependent on the skin you are building, the remaining examples on this page show you how to output the MediaWiki elements to HTML.

To start with you should take your markup and insert it into the. You may want to consider taking this time to also setup the CSS for your skin. Doing so should give you a skin that doesn't function but displays all the dummy markup you have inserted. It's a good way to test your skin with just dummy markup and then make pieces of it functional and test them piece by piece.

Screenshots
After you're done, you should take a screenshot of the skin as shown in a browser and include it in the screenshots/ directory. These screenshots will be shown in the installer (and possibly elsewhere in the future). See T68295 for some examples.
 * You should include at least one 1280x800px screenshot, plus any extra screenshots if your skin looks different at different screen resolutions or with different configuration options.
 * You should disable any extensions or uncommon configuration options when taking the screenshots.
 * Make sure not to include any copyrighted content in the screenshots – here's some public domain content you can use:
 * Page content: https://phabricator.wikimedia.org/P5878
 * Site logo: the MediaWiki logo
 * Images: 1 2 3

General information about adding elements
There are different ways of getting the skin elements to be output to the user's browser. All of the navigation items are contained within PHP arrays.
 * The notable items in arrays are Namespaces, Sidebar, Actions and Personal Tools.
 * These arrays then contain sub-arrays which hold the data that needs to be output to the browser.
 * Example: you can find the data needed for the namespace links in the  array, which then contains an array with [href], [tooltip] and others, which, when assembled into the proper HTML, create the link for the user to click on.
 * The examples below generally use the helper method  within a   loop to generate items from an array of data. This helper intelligently knows how to properly format a list item and all the attributes it needs, as well as create the correct links and other contents that belong in the list item.
 * By default, this method outputs a . If you wish to output something other than an unordered or ordered list of items, makeListItem can accept an array of options as a third argument. You can use that to change the tag from a 'li' to something else.
 * For example, to use  tags instead of   tags, you can use  . Naturally when doing this you would also change the boilerplate examples to output something other than a   to surround the list.

User message (newtalk)
MediaWiki can output a message to a user about new messages on their talkpage. Historically MonoBook and Vector have outputted the newtalk message in the content area and for now they are still there for compatibility with some out-of-content area hacks used on Wikipedia. However practically the newtalk message may actually make more sense alongside the JavaScript message inside your skin.

The boilerplate to output it is:

The newtalk message has no wrapping or style on its own, so you should wrap this in a block to style. The message doesn't always show up so be sure to wrap it in a conditional:

Site notice
The boilerplate to output a wiki's sitenotice is:

Because you'll likely be wrapping the sitenotice in a block you'll probably want to test if the sitenotice is present, to do that you'll use similar boilerplate:

Site name
The boilerplate to output a wiki's sitename is:

Logo and main page link
The logo is comprised primarily of the key for the logo, the key for the main page's URL, and a call to insert a tooltip and accesskey for the logo.


 * creates an array containing a tooltip and associated accesskey. 'p-logo' is the id typically used for the logo so that's the key that is used by MW to define the accesskey and tooltip.
 * If you output a second logo in the page you should avoid re-using the accesskey. Use  as a value of the   attribute instead of the   call.
 * returns an associative array of attributes that can be used with the  interface, here it is expanded to HTML code with.
 * Be sure to remember to HTML-escape the href and logopath, either using  or.

Keep in mind a something about the logo itself. We currently only have one config for logopath. As a result the same logo will be used in every skin, that includes the built-in skins. MediaWiki's built-in skins generally have a logo area that restricts logo sizes to around 155x155px. If your skin has a logo area intended for a logo of a different size you may want to consider including a separate config variable to let users of your skin define a skin-specific logo.

Title
The title of the page is included into the skin's keys as HTML. Generally, a title is plain text. However, a limited set of HTML formatting may be permitted inside of a DISPLAYTITLE and some extensions may add HTML to it.

The boilerplate to output the page's title is:

If you want to use extra styling:

The content area
The content area in MediaWiki usually has some extra styles like icons on external links.

MonoBook and Vector both have a  and a   though MonoBook styles stuff inside bodyContent while Vector styles stuff inside content.

Whether you keep these ids or not you should consider adding a class="mw-body" wherever you do decide links should be styled. 1.19 has some stylesheets you can opt-in to that will use that class.

Tagline
MediaWiki has a "Tagline" which usually goes right below the title, however is also typically hidden by default. The text usually goes something like "From Your Wiki's Name". Some wiki like to show it and style it, though the primary purpose of this seems not to be for normal viewing, but for printing to identify the source of the content. Be sure to include this and test your print styles, we'll go into more detail in a later print section.

The tagline's boilerplate is:

If you want to add styling:

Subtitles
Besides the tagline MediaWiki has two subtitles below the title to take into account. One is used for various things like the subpage hierarchy and redirected from line while the other is specifically for the undelete message.

The two pieces to output the subtitle lines are:

Naturally both of these are optional so you'll want to test for them:

Body text
The body of the page is dead simple to output, you might even want to do this first:

Categories
The function to output the categories block is different from other functions. Many other functions hold an array, but the function for categories contains a string of HTML. Here is the code to use:

Because this function outputs HTML, it is trickier to format in your skin. Here is an example of what is output using the function above:

This function is the only way to display the categories on the page, so you can have only one category list.

Page status indicators
Page status indicators are icons (or short text snippets) usually displayed in the top-right corner of the page, outside of the main content, or right before page title. They are also known as top icons, page icons, heading icons or title icons. (In wikitext they can be added using ; see Help:Page status indicators for more information.)

In the simplest version, the page status indicators block can be inserted on a page using:


 * The PHP above produces  in the HTML that is output to the browser.
 * Your skin's CSS should, therefore, have a definition for.
 * Each time a user adds  to a page in the wiki, the MediaWiki software will generate   inside the empty "mw-indicators" div above. This means that a particular wiki needs to define the style for the "mw-indicator-foo" div within its common.css.

dataAfterContent
MediaWiki skins have another little hack in place. Extensions have the ability to add blocks which should go somewhere after the body text, but they aren't supposed to go before the catlinks block. Because the catlinks block typically goes right after the body text we have a separate key to insert these.

Be sure to include this or else some extensions may not work properly in your skin.

Personal tools
BaseTemplate includes some helpers that make building a list of personal tool links easy. Vector and MonoBook display the personal tools in the far upper corner of the page. They generally contain things like the login link, logout link, the user's username with a link to their userpage, talkpage, watchlist, preferences, and other links.

This boilerplate can output the personal tools as an unordered list.

Content actions
As of 1.18 MediaWiki supports the use of two different lists to access what is usually outputted as tabs for a page.
 * The  array provides these tabs as a single flat array, and is was the original format of the actions. This was is used by Mono Book.
 * The other is  which was introduced by Vector.   provides the list of tabs as an array of arrays array containing  ' ', ' ', ' ', and ' ' with the tabs that are put into   nicely separated into groups.
 * If you want to differentiate between any of the tabs in any way at all, be it some special styling, or outputting them in separate lists, you are better off making use of the new . Note that the   also includes a redundant 'Read' tab in views which is omitted in the flat   list.

This is better explained with a number of examples.

This example outputs just the links of the Namespaces.

You can use this to output the Namespaces links wherever you want in whatever order you want.

This example outputs all the Namespaces links as separate lists:

This example outputs all the the Namespaces links as one unified list. This will include the slightly redundant 'Read' tab, however you can use the separation of groups to add separators or other things wherever you want.

This example outputs the flat content_actions list as a single list:

For most of these you'll probably want to add something like a CSS class or id based off the $group to target with styles as you please.

Sidebar
Currently for navigation MediaWiki only supports a built-in sidebar – including the toolbox, language links, and site-defined navigation (see Manual:Interface/Sidebar). For other types of navigation you can hard code or preferably have someone implement the code to support your own custom navigation message. For now all I can show is the sidebar boilerplate.

The boilerplate is of course a little plain. This contains the typical CSS ID and a tooltip; you can also add a class or other formatting. If you don't care about the ability to customize the output of lists, you can use  and drop the whole is_array test and just keep the.

Language links
''Note that language links are already included in the sidebar, above. If you use that method, you can skip this section.''

A MediaWiki page may have links to the same page in other languages on the wiki when inter-language links are added to the page. If you do wish to follow the MonoBook and Vector methods, you may output this as part of the sidebar.

Toolbox
''Note that language links are already included in the sidebar, above. If you use that method, you can skin this section.''

The MediaWiki toolbox contains various links. Some are general links like a links to a list of Special Pages so a user always has a way to access them. Others are page-sensitive links like permalinks, printable links, block links, feed links, and a link to a list of pages linking to the current page.

The boilerplate to output the toolbox is:

The SkinTemplateToolboxEnd hook is included for compatibility with some extensions. As more skins use the BaseTemplateToolbox hook and more extensions switch to using it we may be able to drop the hook and no longer include it.

Like personal URLs the array that  returns can be set to a variable can can be easily modified and unset if you want to move parts of the toolbox elsewhere in your skin.

Search form
MediaWiki skins usually include a search form that can be used to search the wiki. If the feature is enabled and the form is setup correctly this form usually also supports search suggestions. MonoBook does this as part of the sidebar, while other skins such as Vector have a dedicated place for the search form.

To start the search form, let's begin with the form itself:

A search form itself uses the HTTP GET method rather than a POST. As a result you can't include any query arguments in the. So a search form is built initially of a form with the action pointed to the wiki's index.php and a hidden input with the search page's title to ensure it's in the URL.

You should probably give the form itself an id. Keep in mind that MediaWiki supports autocompletion of the search form. Starting in version 1.18, MediaWiki will only look for search forms with one of the id's "searchform" "searchform2" "powersearch" or "search". So the best practice is to use id="searchform" for your form. It is recommended you use the CSS class  for your form.

Moving on, naturally every search form needs a text field to enter a search query into. At its base level you can use this helper method to build a search input:

However, this helper supports an array, which is output to the user's screen. Note that:
 * The form uses  by default. A browser that supports this type of input field usually displays it with a special style.
 * This means that, if you wish to add a special style like what Vector does for its simple search, you may want to override this and force MediaWiki to output a text  instead.  See the following example:

Another thing to keep in mind is you may want to use an id on your search input. You'll probably have some label nearby like "Search:" or something, at the very least it may be one that is hidden but is still around for accessibility purposes. You'll probably need an id to target the input with a label if you don't put the input inside the label itself. This is especially true if you put the label inside a header like vector does. The search input's helper also accepts an id to use. For example MonoBook and Vector use the id 'searchInput' to output a search input with the searchInput id you can use:

Note that the array is basically a list of attributes that are modified with the pieces important to a search input then passed to the HTML method that generates the input. This means you can add just about any HTML attribute that you want. Feel free to use it to add a CSS class, an inline style, some HTML5 data-attributes, or so on.

Next we're going to need a search button so that the user can submit the search. However this helper has 3 different modes to keep in mind. MediaWiki supports two forms of search.
 * The default "Go" search which may redirect directly to a page if the search term matches a page's title.
 * A "Full Text" search that will always go to the search page.

The search input's helper supports both a 'go' mode and a 'fulltext' mode. The 3rd mode is an 'image' mode which outputs a 'go' mode button but does it using an image instead of text. Vector uses this last mode to create its simple search icon. This helper also accepts an array of attributes as the second argument. The difference here is that in the 'image' mode the required 'src' attribute and optional 'alt' attribute go on the  while the rest of the attributes you specify go on the. Here are some examples:

The tradition in MonoBook and Vector for CSS IDs here is to use search Go Button and MW-search button for a pair of Go and Full Text Search buttons, both with a searchButton class. And to use the ID search Button for a Vector simple search style image button. The examples for those cases:

There's no standard for toggling between a classic Go+Search and a simple search as that introduction was specific to Vector. You're also free to just have a plain go button with a "Search" title if it fits your theme. The old MonoBook had a config option to only have a Go button and instead have a power search link – that is beyond the scope of this manual.

Image paths
In the above code notice that if you need to output  tags in PHP code, you need to get the path to the image asset on the server using. Where possible it's cleaner to refer to images from CSS code, e.g. . See also ResourceLoader/Images.

Footer links
A MediaWiki skin may contain a common list of links and pieces of text intended to be in the footer. These footer links may contain things like a license line and other links like about, privacy policy, and disclaimer links.

The footer links array is returned by the  helper which also accepts a "flat" argument to return a flat array instead of a categorized one.

The boilerplate to output a collection of footer links lists is:

You can output the footer links as a flat array using this code instead:

Remember that like the  array this is a categorized list, however in this case it's not a fixed set of categories. You may want to output these as separate lists, give each list a class or id based on the category, and do the same for the list items as well.

Footer icons
The footer may also contain a common list of icons in it. Included in these icons are the "powered by MediaWiki" icon, an optional "copyright" icon, and an icon representing the license the wiki has chosen. There will be any other icon that a user or extension has defined with $wgFooterIcons.

The footer icons list is categorized into groups.

To output a list of only icons where each group is a list item containing one or more icons you can use:

You can use the 'without Image' parameter (shown next) to make Footer Icon you can instead output a textual list instead of icons. Modern uses this kind of technique. Note that footer links has a textual representation of the wiki's license, so including the copyright/license icon as a second piece of text doesn't make that much sense. Hence to omit the copyright icon/text you can use the "nocopyright" parameter to getFooterIcons.