1# Skinning the Fossil Web Interface
2
3The Fossil web interface comes with a pre-configured look and feel.  The default
4look and feel works fine in many situations.  However, you may want to change
5the look and feel (the "skin") of Fossil to better suite your own individual tastes.
6This document provides background information to aid you in that task.
7
8## <a id="builtin"></a>Built-in Skins
9
10Fossil comes with [multiple built-in skins](/skins).  If the default skin does not
11suite your tastes, perhaps one of the other built-in skins will work better.
12If nothing else, the built-in skins can serve as examples or templates that
13you can use to develop your own custom skin.
14
15The sources to these built-ins can
16be found in the Fossil source tree under the skins/ folder.  The
17[skins/](/dir?ci=trunk&name=skins)
18folder contains a separate subfolder for each built-in skin, with each
19subfolders holding at least these five files:
20
21   * css.txt
22   * details.txt
23   * footer.txt
24   * header.txt
25   * js.txt
26
27Try out the built-in skins by using the --skin option on the
28[fossil ui](/help?cmd=ui) or [fossil server](/help?cmd=server) commands.
29
30## <a id="sharing"></a>Sharing Skins
31
32The skin of a repository is not part of the versioned state and does not
33"push" or "pull" like checked-in files.  The skin is local to the
34repository.  However, skins can be shared between repositories using
35the [fossil config](/help?cmd=configuration) command.
36The "fossil config push skin" command will send the local skin to a remote
37repository and the "fossil config pull skin" command will import a skin
38from a remote repository.  The "fossil config export skin FILENAME"
39will export the skin for a repository into a file FILENAME.  This file
40can then be imported into a different repository using the
41"fossil config import FILENAME" command.  Unlike "push" and "pull",
42the "export" and "import" commands are able to move skins between
43repositories for different projects.  So, for example, if you have a
44group of related repositories, you can develop a skin for one of them,
45then get a consistent look across all the repositories by exporting
46the skin from the first repository and importing into all the others.
47
48The file generated by "fossil config export" could be checked into
49one of your repositories and versioned, if desired.  This will not
50automatically change the skin when looking backwards in time, but it
51will provide an historical record of what the skin used to be and
52allow the historical look of the repositories to be recreated if
53necessary.
54
55When cloning a repository, the skin of the new repository is initialized to
56the skin of the repository from which it was cloned.
57
58# Structure Of A Fossil Web Page
59
60Every HTML page generated by Fossil has the same basic structure:
61
62<blockquote><table border=1 cellpadding=10><tbody>
63<tr><td style='background-color:lightgreen;text-align:center;'>
64Fossil-Generated HTML Header</td></tr>
65<tr><td style='background-color:lightblue;text-align:center;'>Content Header</td></tr>
66<tr><td style='background-color:lightgreen;text-align:center;'>
67Fossil-Generated Content</td></tr>
68<tr><td style='background-color:lightblue;text-align:center;'>Content Footer</td></tr>
69<tr><td style='background-color:lightgreen;text-align:center;'>
70Fossil-Generated HTML Footer</td></tr>
71</tbody></table></blockquote>
72
73The green parts are *usually* generated by Fossil.  The blue parts
74are things that you, the administrator, get to modify in order to
75customize the skin.
76
77Fossil *usually* (but not always - [see below](#override))
78generates the initial HTML Header section of a page.  The
79generated HTML Header will look something like this:
80
81         <html>
82         <head>
83         <base href="..." />
84         <meta http-equiv="Content-Security-Policy" content="...." />
85         <meta name="viewport" content="width=device-width, initial-scale=1.0">
86         <title>....</title>
87         <link rel="stylesheet" href="..." type="text/css" />
88         </head>
89         <body class="FEATURE">
90
91…where `FEATURE` is either the top-level URL element (e.g. `doc`) or a
92feature class that groups multiple URLs under a single name such as
93`forum` to contain `/forummain`, `/forumpost`, `/forume2`, etc. This
94allows per-feature CSS such as
95
96         body.forum div.markdown blockquote {
97           margin-left: 10px;
98         }
99
100That is, affect HTML `<blockquote>` tags specially only for forum posts
101written in Markdown, leaving all other block quotes alone.
102
103In most cases, it is best to leave the Fossil-generated HTML Header
104alone. (One exception is when the administrator needs to include links
105to additional CSS files.) The configurable part of the skin begins
106with the Content Header section which should follow this template:
107
108        <div class="header">
109          ... top banner and menu bar ...
110        </div>
111
112Note that `<div class="header">` and `</div>` tags must be included in
113the Content Header text of the skin.  In other words, you, the
114administrator, need to supply that text as part of your skin
115customization.
116
117The Fossil-generated Content section immediately follows the Content Header.
118The Content section will looks like this:
119
120        <div class="content">
121          ... Fossil-generated content here ...
122        </div>
123
124After the Content is the custom Content Footer section which should
125follow this template:
126
127        <div class="footer">
128          ... skin-specific stuff here ...
129        </div>
130
131As with the Content Header, the template elements of the Content Footer
132should appear exactly as they are shown.
133
134Finally, Fossil always adds its own footer (unless overridden)
135to close out the generated HTML:
136
137        </body>
138        </html>
139
140## <a id="mainmenu"></a>Changing the Main Menu Contents
141
142As of Fossil 2.15, the actual text content of the skin’s main menu is no
143longer part of the skin proper if you’re using one of the stock skins.
144If you look at the Header section of the skin, you’ll find a
145`<div class="mainmenu">` element whose contents are set by a short
146[TH1](./th1.md) script from the contents of the **Main Menu** section of
147the Setup → Configuration screen.
148
149This feature allows the main menu contents to stay the same across
150different skins, so you no longer have to reapply menu customizations
151when trying different skins.
152
153See the [`capexpr`](./th1.md#capexpr) section of the TH1 docs for help
154on interpreting the default contents of this block.
155
156
157## <a id="override"></a>Overriding the HTML Header and Footer
158
159Notice that the `<html>`, `<head>`, and opening `<body>`
160elements at the beginning of the document,
161and the closing `</body>` and `</html>` elements at the end are automatically
162generated by Fossil.  This is recommended.
163
164However, for maximum design flexibility, Fossil allows those elements to be
165supplied as part of the configurable Content Header and Content Footer.
166If the Content Header contains the text "`<body`", then Fossil assumes that
167the Content Header and Content Footer will handle all of the `<html>`,
168`<head>`, and `<body>` text itself, and the Fossil-generated header and
169footer will be blank.
170
171When overriding the HTML Header in this way, you will probably want to use some
172of the [TH1 variables documented below](#vars) such as `$stylesheet_url`
173to avoid hand-writing code that Fossil can generate for you.
174
175# Designing, Debugging, and Installing A Custom Skin
176
177It is possible to develop a new skin from scratch.  But a better and easier
178approach is to use one of the existing built-in skins as a baseline and
179make incremental modifications, testing after each step, to obtain the
180desired result.
181
182The skin is controlled by five files:
183
184<blockquote><dl>
185<dt><b>css.txt</b></dt><dd>
186
187<p>The css.txt file is the text of the CSS for Fossil.
188Fossil might add additional CSS elements after
189the css.txt file, if it sees that the css.txt omits some
190CSS components that Fossil needs.  But for the most part,
191the content of the css.txt is the CSS for the page.</dd>
192
193<dt><b>details.txt</b><dt><dd>
194
195<p>The details.txt file is short list of settings that control
196the look and feel, mostly of the timeline.  The default
197details.txt file looks like this:
198
199<blockquote><pre>
200pikchr-background:          ""
201pikchr-fontscale:           ""
202pikchr-foreground:          ""
203pikchr-scale:               ""
204timeline-arrowheads:        1
205timeline-circle-nodes:      1
206timeline-color-graph-lines: 1
207white-foreground:           0
208</pre></blockquote>
209
210The three "timeline-" settings in details.txt control the appearance
211of certain aspects of the timeline graph.  The number on the
212right is a boolean - "1" to activate the feature and "0" to
213disable it.  The "white-foreground:" setting should be set to
214"1" if the page color has light-color text on a darker background,
215and "0" if the page has dark text on a light-colored background.
216<p>
217If the "pikchr-foreground" setting (added in Fossil 2.14)
218is defined and is not an empty string then it specifies a
219foreground color to use for [pikchr diagrams](./pikchr.md).  The
220default pikchr foreground color is black, or white if the
221"white-foreground" boolean is set.  The "pikchr-background"
222settings does the same for the pikchr diagram background color.
223If the "pikchr-fontscale" and "pikchr-scale" values are not
224empty strings, then they should be floating point values (close
225to 1.0) that specify relative scaling of the fonts in pikchr
226diagrams and other elements of the diagrams, respectively.
227</dd>
228
229<dt><b>footer.txt</b> and <b>header.txt</b></dt><dd>
230
231<p>The footer.txt and header.txt files contain the Content Footer
232and Content Header respectively.  Of these, the Content Header is
233the most important, as it contains the markup used to generate
234the banner and menu bar for each page.
235
236<p>Both the footer.txt and header.txt file are
237[processed using TH1](#headfoot) prior to being output as
238part of the overall web page.</dd>
239
240<dt><b>js.txt</b></dt><dd>
241
242<p>The js.txt file is optional.  It is intended to be javascript.
243The complete text of this javascript might be inserted into
244the Content Footer, after being processed using TH1, using
245code like the following in the "footer.txt" file:
246
247<blockquote><pre>
248&lt;script nonce="$nonce"&gt;
249  &lt;th1&gt;styleScript&lt;/th1&gt;
250&lt;/script&gt;
251</pre></blockquote>
252
253<p>The js.txt file was originally used to insert javascript
254that controls the hamburger menu in the default skin.  More
255recently, the javascript for the hamburger menu was moved into
256a separate built-in file.  Skins that use the hamburger menu
257typically cause the javascript to be loaded by including the
258following TH1 code in the "header.txt" file:
259
260<blockquote><pre>
261&lt;th1&gt;builtin_request_js hbmenu.js&lt;/th1&gt;
262</pre></blockquote>
263
264The difference between styleScript and builtin_request_js
265is that the styleScript command interprets the file
266using TH1 and injects the content directly into the output
267stream, whereas the builtin_request_js command inserts the
268javascript verbatim and does so at some unspecified future time
269down inside the Fossil-generated footer.  The built-in skins
270of Fossil originally used the styleScript command to load
271the hamburger menu javascript, but as of version 2.15 switched
272to using the builtin_request_js method.  You can use either
273approach in custom skins that you right yourself.
274
275Note that the "js.txt" file is *not* automatically inserted into
276the generate HTML for a page.  You, the skin designer, must
277cause the javascript to be inserted by issuing appropriate
278TH1 commands in the "header.txt" or "footer.txt" files.</dd>
279</dl></blockquote>
280
281Developing a new skin is simply a matter of creating appropriate
282versions of these five control files.
283
284### Skin Development Using The Web Interface
285
286Users with admin privileges can use the Admin/Skin configuration page
287on the web interface to develop a new skin.  The development of a new
288skin occurs without disrupting the existing skin.  So you can work on
289a new skin for a Fossil instance while the existing skin is still in
290active use.
291
292The new skin is a "draft" skin.  You initialize one of 9 draft skins
293to either the current skin or to one of the built-in skins.  Then
294use forms to edit the 5 control files described above.  The new
295skin can be tested after each edit.  Finally, once the new skin is
296working as desired, the draft skin is "published" and becomes the
297new live skin that most users see.
298
299### Skin Development Using A Local Text Editor
300
301An alternative approach is to copy the five control files for your
302baseline skin into a temporary working directory (here called
303"./newskin") and then launch the [fossil ui](/help?cmd=ui) command
304with the "--skin ./newskin" option.  If the argument to the --skin
305option contains a "/" character, then the five control files are
306read out of the directory named.  You can then edit the control
307files in the ./newskin folder using you favorite text editor, and
308press "Reload" on your browser to see the effects.
309
310### Disabling The Web Browser Cache During Development
311
312Fossil is aggressive about asking the web browser to cache
313resources.  While developing a new skin, it is often helpful to
314put your web browser into developer mode and disable the cache.
315If you fail to do this, then you might make some change to your skin
316under development and press "Reload" only to find that the display
317did not change.  After you have finished work your skin, the
318caches should synchronize with your new design and you can reactivate
319your web browser's cache and take it out of developer mode.
320
321## <a id="headfoot"></a>Header and Footer Processing
322
323The `header.txt` and `footer.txt` control files of a skin are the HTML text
324of the Content Header and Content Footer, except that before being inserted
325into the output stream, the text is run through a
326[TH1 interpreter](./th1.md) that might adjust the text as follows:
327
328  *  All text within &lt;th1&gt;...&lt;/th1&gt; is omitted from the
329     output and is instead run as a TH1 script.  That TH1
330     script has the opportunity to insert new text in place of itself,
331     or to inhibit or enable the output of subsequent text.
332
333  *  Text of the form "$NAME" or "$&lt;NAME&gt;" is replaced with
334     the value of the TH1 variable NAME.
335
336For example, first few lines of a typical Content Header will look
337like this:
338
339        <div class="header">
340          <div class="title"><h1>$<project_name></h1>$<title>/div>
341
342After variables are substituted by TH1, that will look more like this:
343
344        <div class="header">
345          <div class="title"><h1>Project Name</h1>Page Title</div>
346
347As you can see, two TH1 variable substitutions were done.
348
349The same TH1 interpreter is used for both the header and the footer
350and for all scripts contained within them both.  Hence, any global
351TH1 variables that are set by the header are available to the footer.
352
353## <a id="menu"></a>Customizing the ≡ Hamburger Menu
354
355The menu bar of the default skin has an entry to open a drop-down menu with
356additional navigation links, represented by the ≡ button (hence the name
357"hamburger menu"). The Javascript logic to open and close the hamburger menu
358when the button is clicked is usually handled by a script named
359"hbmenu.js" that is one of the [built-in resource files](/test-builtin-files)
360that are part of Fossil.
361
362The ≡ button for the hamburger menu is added to the menu bar by the following
363TH1 commands in the `header.txt` file, right before the menu bar links:
364
365        html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
366        builtin_request_js hbmenu.js
367
368The hamburger button can be repositioned between the other menu links (but the
369drop-down menu is always left-aligned with the menu bar), or it can be removed
370by deleting the above statements.  The "html" statement inserts the appropriate
371`<a>` for the hamburger menu button (some skins require something slightly
372different - for example the ardoise skins wants "`<li><a>`").  The
373"builtin_request_js hbmenu.js" asks Fossil to include the "hbmenu.js"
374resource files in the Fossil-generated footer.
375
376The hbmenu.js script requires
377the following `<div>` element somewhere in your header, in which to build
378the hamburger menu.
379
380        <div id='hbdrop'></div>
381
382Out of the box, the contents of the panel is populated with the [Site
383Map](/sitemap), but only if the panel does not already contain any HTML
384elements (that is, not just comments, plain text or non-presentational white
385space). So the hamburger menu can be customized by replacing the empty `<div
386id='hbdrop'></div>` element with a menu structure knitted according to the
387following template:
388
389        <div id="hbdrop" data-anim-ms="400">
390         <ul class="columns" style="column-width: 20em; column-count: auto">
391          <!-- NEW GROUP WITH HEADING LINK -->
392          <li>
393           <a href="$home$index_page">Link: Home</a>
394           <ul>
395            <li><a href="$home/timeline">Link: Timeline</a></li>
396            <li><a href="$home/dir?ci=tip">Link: File List</a></li>
397           </ul>
398          </li>
399          <!-- NEW GROUP WITH HEADING TEXT -->
400          <li>
401           Heading Text
402           <ul>
403            <li><a href="$home/doc/trunk/www/customskin.md">Link: Theming</a></li>
404            <li><a href="$home/doc/trunk/www/th1.md">Link: TH1 Scripts</a></li>
405           </ul>
406          </li>
407          <!-- NEXT GROUP GOES HERE -->
408         </ul>
409        </div>
410
411The custom `data-anim-ms` attribute can be added to the panel element to direct
412the Javascript logic to override the default menu animation duration of 400 ms.
413A faster animation duration of 80-200 ms may be preferred for smaller menus. The
414animation is disabled by setting the attribute to `"0"`.
415
416
417## <a id="vars"></a>TH1 Variables
418
419Before expanding the TH1 within the header and footer, Fossil first
420initializes a number of TH1 variables to values that depend on
421repository settings and the specific page being generated.
422
423   *   **project_name** - The project_name variable is filled with the
424       name of the project as configured under the Admin/Configuration
425       menu.
426
427   *   **project_description** - The project_description variable is
428       filled with the description of the project as configured under
429       the Admin/Configuration menu.
430
431   *   **title** - The title variable holds the title of the page being
432       generated.
433
434       The title variable is special in that it is deleted after
435       the header script runs and before the footer script.  This is
436       necessary to avoid a conflict with a variable by the same name used
437       in my ticket-screen scripts.
438
439   *   **baseurl** - The root of the URL namespace for this server.
440
441   *   **secureurl** - The same as $baseurl except that if the scheme is
442                       "http:" it is changed to "https:"
443
444   *   **home** - The $baseurl without the scheme and hostname.  For example,
445       if the $baseurl is "http://projectX.com/cgi-bin/fossil" then the
446       $home will be just "/cgi-bin/fossil".
447
448   *   **index_page** - The landing page URI as
449       specified by the Admin/Configuration setup page.
450
451   *   **current_page** - The name of the page currently being processed,
452       without the leading "/" and without query parameters.
453       Examples:  "timeline", "doc/trunk/README.txt", "wiki".
454
455   *   **csrf_token** - A token used to prevent cross-site request forgery.
456
457   *   **default_csp** - [Fossil’s default CSP](./defcsp.md) unless
458       [overridden by custom TH1 code](./defcsp.md#th1). Useful within
459       the skin for inserting the CSP into a `<meta>` tag within [a
460       custom `<head>` element](#headfoot).
461
462   *   **nonce** - The value of the cryptographic nonce for the request
463       being processed.
464
465   *   **release_version** - The release version of Fossil.  Ex: "1.31"
466
467   *   **manifest_version** - A prefix on the check-in hash of the
468       specific version of fossil that is running.  Ex: "\[47bb6432a1\]"
469
470   *   **manifest_date** - The date of the source-code check-in for the
471       version of fossil that is running.
472
473   *   **compiler_name** - The name and version of the compiler used to
474       build the fossil executable.
475
476   *   **login** - This variable only exists if the user has logged in.
477       The value is the username of the user.
478
479   *   **stylesheet_url** - A URL for the internal style-sheet maintained
480       by Fossil.
481
482   *   **log\_image\_url** - A URL for the logo image for this project, as
483       configured on the Admin/Logo page.
484
485   *   **background\_image\_url** - A URL for a background image for this
486       project, as configured on the Admin/Logo page.
487
488All of the above are variables in the sense that either the header or the
489footer is free to change or erase them.  But they should probably be treated
490as constants.  New predefined values are likely to be added in future
491releases of Fossil.
492
493
494## <a id="procedure"></a>Suggested Skin Customization Procedure
495
496Developers are free, of course, to develop new skins using any method they
497want, but the following is a technique that has worked well in the past and
498can serve as a starting point for future work:
499
500   1.  Select a built-in skin that is closest to the desired look.  Make
501       copies of the css, footer, and header into files name "css.txt",
502       "details.txt",
503       "footer.txt", and "header.txt" in some temporary directory.
504
505       If the Fossil source code is available, then these three files can
506       be copied directly out of one of the subdirectories under skins.  If
507       sources are not easily at hand, then a copy/paste out of the
508       CSS, footer, and header editing screens under the Admin menu will
509       work just as well.  The important point is that the three files
510       be named exactly "css.txt", "footer.txt", and "header.txt" and that
511       they all be in the same directory.
512
513   2.  Run the [fossil ui](/help?cmd=ui) command with an extra
514       option "--skin SKINDIR" where SKINDIR is the name of the directory
515       in which the three txt files were stored in step 1.   This will bring
516       up the Fossil website using the tree files in SKINDIR.
517
518   3.  Edit the *.txt files in SKINDIR.  After making each small change,
519       press Reload on the web browser to see the effect of that change.
520       Iterate until the desired look is achieved.
521
522   4.  Copy/paste the resulting css.txt, details.txt,
523       header.txt, and footer.txt files
524       into the CSS, details, header, and footer configuration screens
525       under the Admin/Skins menu.
526
527
528## See Also
529
530*   [Customizing the Timeline Graph](customgraph.md)
531