Help:Page styles

From Wikisource
Jump to navigation Jump to search
Page styles

An explanation of the methods use to apply CSS to a scan-backed work.

A CSS "stylesheet" can be applied to a Index page, which will allow every Page: namespace page within it to share the same styling. This CSS is automatically included when pages are transcluded using the <page/> tag.

You do not need to use CSS for a work if you don't want to. It is provided to make life easier, not harder.

How to apply CSS[edit]

The CSS is read from the /styles.css subpage of the Index page. If this page does not exist, no styles will be applied by default by the ProofreadPage extension.

Note: this is different to the CSS field in the Index page, which only applies to the Page namespace and does not transclude.

You can redirect a /styles.css to another CSS page (for example if a set of volumes share the same styles) but the redirect page may need to have the "content model" changed to "wikitext" (from "sanitized-css"), which currently requires an admin.[1]

Where the CSS is applied[edit]

Index-specific CSS is currently applied automatically in the following places:

  • In the Page namespace of that index
  • On the Index page itself[2]
  • On the transcluding page when pages are transcluded using the <page/> tag.
    • Note: is is not applied if you directly transclude with {{Page:XXXX.djvu}} syntax, or with {{page}}. Either avoid these constructions and use the <page/> tag (recommended) or you must manually invoke with <templatestyles src="Index:Foo.djvu/styles.css"/>.

How to write CSS[edit]

The CSS is a subset of full CSS called "sanitized CSS" provided by the TemplateStyles extension. It is the same as normal CSS, but it has restrictions on certain properties:

  • Some "rarer" CSS properties are not supported yet
  • Data URLs are not allowed
  • Image URLs not from Commons (or Wikisource) are not allowed

The CSS will only apply to the page content (it will not affect the rest of the Wikisource UI).

Classes and IDs[edit]

You can target CSS with "classes" and "IDs". Classes can apply to any number of elements (and any element can have any number of classes, separated by spaces). Any element can have an ID, but it can have only one, and it should be the only element on the page with that ID.

Classes are targeted by CSS rules with a dot prefix (.), and IDs with a hash (#)

The following spans have classes and IDs:

<span class="red bold">Classes: red and bold</span>
<span id="blue" class="bold">ID: blue, class: bold</span>
<span class="red">Class: red (and not bold)</span>

Paired with this CSS:

.red {
    color: red;
}
.bold {
    font-weight: bold;
}
#blue {
    color: #00008B; /* dark blue */
}

The result is something like this:

Classes: red and bold ID: blue, class: bold Class: red (and not bold)

Inheritance[edit]

You can target elements that are children of other elements with the "child" and "descendant" selectors:

  • Target direct children with parent_selector > child_selector
  • Target all descendants (any number of intervening "generations") with ancestor_selector descendant_selector

For example, if you have Wikicode that produces the following HTML:

<div class="parent">Parent content.
  <div>Child content.
    <span>Grand-child content
        <span>Great-grand-child content</span>
    </span>
  </div>
</div>

Then you can have CSS like this:

/* This will only put a border around the "Child content." box */
.parent > div {
    border: 1px solid blue;
}
/* This will put separate green outlines around each of grand-child and great-grand-child boxes
 * (but not "child", because that is a div, not a span */
.parent span {
    outline: 1px solid blue;
}

Cascading[edit]

The "C" in "CSS" means cascading. This means that the rules can override each other in a well-defined order. For each property, which rule is applied is worked out like this:

  • Styles set directly on an element have priority, otherwise,
  • More "specific" styles have priority
  • If two rule have the same "specificity", the one that occurs last has priority

"Specificity" has a certain defined meaning, but generally speaking it is a measure of how "precise" the selector is. For example in the following HTML and CSS:

HTML CSS
<div class="red">Parent
  <div class="green">Child</div>
</div>
<div class="green">Child</div>
.green {
    color: green;
}
.red > .green {
    color: red;
}

In this case, for the class="green" element inside the class="red" element, the more specific selector .red > .green "wins" over the less specific .green and the element gets the style color: red;.

What to use CSS for[edit]

CSS is ideal for applying things that would otherwise require very tedious, repetitive or verbose inline styles:

  • Sizes and spacings of chapter headings
  • Sizes of block-quotes and surrounding spacings
  • Formatting of lists (for example adjusting bullet points)

Due to the ability to use selectors like :nth-child, they are also excellent for reducing bloated inline styles in tables.

Be semantically useful[edit]

CSS is one half of the structure-style separation-of-concerns provided by HTML (structure) and CSS (style). To use it to its maximum effect, it should be used "semantically". That is to say, provide meaning to content and then use that meaning to apply styling.

For example, this is semantically empty:

<span style="font-variant:small-caps;">Duke Orsino</span>: If music be the food of love, play on,

whereas this gives meaning to the first words:

<span class="character">Duke Orsino</span>: If music be the food of love, play on,

And can be targeted, along with all other characters' names, with this CSS:

.character {
   font-variant: small-caps;
}

You should also not abuse Wikicode syntax just because it gives you a shorthand for a different HTML tag which you want to use to target with CSS. ; and : provide <dl><dt> and <dl><dd> elements, representing "description list" terms and descriptions, respectively[3]. Only use them where this makes semantic sense (for example, a glossary or dictionary).

If you have a list, * (unordered) or # (ordered) are usually the correct choices.

What not to use CSS for[edit]

You should not use Index-based CSS to provide:

  • Indentation of paragraphs, even if the original work had them (see Wikisource:Style guide#Indentation). Indentation of list items is usually acceptable, within reason.
  • Removal of spaces between normal paragraphs, even if the original work did not have them (see Wikisource:Style guide#Paragraph spacing)
  • Global changing of fonts (e.g. serif), justification, font size or line heights (even if the original work had small or dense print)

All these should be provided through Dynamic Layouts or user CSS.

Remember that not all users have full-capable CSS devices. For example, many e-readers can handle only a very tiny subset of CSS. You should not use CSS for any content that must be shown even if the reader doesn't support any CSS. For example, using CSS counters to number lists or :after selectors to add dots after list numbers will result in the wrong thing being shown to users without CSS. As a rough guide, if it can't be copy-and-pasted, users will not see it when CSS is not available.

Avoid bare classes[edit]

You should also avoid using bare CSS classes in Wikicode when a template would do. For example, say you have a work that has character names typeset in a certain way, say green italic small-caps. If you don't want to repeat the formatting for each occurrence, you should define a template {{MyWork character}} to apply this (perhaps using its own TemplateStyles):

<templatestyles src="MyWork character/styles.css"/><!-- or inline CSS, or other templates -->
<span class="mywork_character">{{{1}}}</span>

And then use it as follows:

Avast, ye, {{MyWork character|Long John Silver}}!

The following bare CSS in the work's page content is bad form:

Avast, ye, <span class="mywork_character">Long John Silver</span>!

This is to say: the classes defined in CSS (including work-specific CSS) should nearly always be invoked via a template, not directly. It is much easier to reason about and maintain templates than HTML/CSS, even if the template itself constructs HTML/CSS.

CSS vs templates[edit]

Some things are suitable to be handled by work-specific CSS, and other things are more suitable for a template. Consider using a template if:

  • The desired output requires "structural" elements like HTML tags.
  • The desired output is useful in other works (i.e. it is not work-specific). You can redirect the CSS subpage, but this means you forfeit any dedicated styles for this work.
  • As above, the styling is work specific, but so is the application. In that case, a work-specific template is more appropriate. Per-work CSS is more suitable for applying work-specific styling to generic classes.

You can still target the output of templates with work-specific CSS (the template in question should set a class to allow this).

The following are some templates set classes that can be usefully targeted with CSS (others can be found in Category:Templates applying classes for page styles):

What if I want CSS for a single page[edit]

If you have CSS that applies only to a single page (for example, a table), you can still use TemplateStyles as normal:

<templatestyles src="Index:Some book.djvu/p321_styles.css" />

This must be applied in the body of the Page page for it to transclude. Remember that the CSS will apply to the whole context where this one Page is transcluded—it will not be limited to this page only. So, use an ID or class or limit the effects of your page rule. For example:

table {
  border: 1px solid black;
}

will affect all tables on the final destination page, but

#errata {
  border: 1px solid black;
}

applies only to the element with the ID errata.

Class naming conventions[edit]

Since styles from multiple sources can be present on a single page, it is important to avoid name clashes between these style rules. For example, MediaWiki itself as well as the skin (Vector, etc.) will add some classes, the Extension:Wikisource and Extension:Proofread Page extensions may add others, and there are classes used by templates. To reduce the likelihood of collisions we have developed some conventions for how to name classes from different sources, based on giving the name a prefix indicating its origin.

Prefix Source
.mw- Classes added by MediaWiki itself
.prp- Classes added by Proofread Page
.ws- Site-wide classes for English Wikisource
.wst- Classes added by a template
._ Reserved for use in page styles
.__ Reserved for use not only within a single work, but for some kind of exceptional use on a single page within that work. Is also sometimes used in project namespaces (like this one).

There are historical exceptions, both here on English Wikisource and in MediaWiki, but diverging from these conventions in new content is strongly discouraged (and if you update old content please consider modernizing it to these standards).

For Page styles you'll mostly want to use the ._ prefix. This prefix is reserved for use within each individual work, and so templates and site-wide styles will never interfere with it. You may sometimes also need to override the styling for some templates (some newer templates are explicitly designed to be styled from Page styles), in which case you'll find the right classes with a .wst- prefix on that template's documentation page.

NB! If a template does not document overridable classes then it is not safe to style it, even if you notice a class it uses. Internal classes in templates can change at any time and it is in general not possible to detect and update any outside uses of that class.

You may also sometimes need to use the .__ prefix. This prefix is reserved for use not only within a single text, but for some exceptional use within that text. Maybe for a single page that has different formatting than the rest of the text, or maybe it's temporary while you test something out. You can achieve the same with more unique class names, but the double underscore prefix also signals to other contributors that this class is special in some way.

Some specific class names are conventional (but not mandatory) to use for certain elements of books that are common.

Prefix Source
._toc The book's table of contents
._plate A full-page plate, illustration, etc. Sometimes added to a template wrapping the whole page, sometimes directly on the image itself.
._title The book's title page, if it contains very complex formatting

Example page styles[edit]

Below are some example Page styles style sheets you can cut and paste into your own projects. If you're lucky you can use them directly for simple cases, but most likely you'll have to tweak them at least a little bit. The texts we cover are not all that uniformly laid out so some adaptation for each text is to be expected.

Tables of contents[edit]

A lot of tables of contents boil down to a two or three column table. The structure isn't that complicated, but coding it up in MediaWiki's table wikitext and templates is often very complex due to being row-oriented where the styling in the original is really column-oriented. Page styles using the CSS :nth-child selector (and the :first-child and :last-child shortcuts) can really help with this.

Simple two-column table of contents[edit]

One real life example is this table from The Works of Xenophon vol. 3 pt. 2.

Ignoring the pseudo-chapter heading ("Contents"), this table consists of two columns: one for the chapter titles and one for the page number on which it starts. The chapter titles column is left-align, uses small-caps, and has a hanging indent. The page numbers column is right aligned and has a little bit of space separating it from the chapter titles. In the row for the long chapter title that actually wraps we can also see that the chapter titles are vertically aligned to the top of their cell, and the page numbers are vertically aligned to the bottom of their cell. In other words, the page number is vertically aligned with the bottom of the last line of the chapter title.

This could be represented in wikitext with this structure (links omitted for simplicity):

{| class="_toc"
|-
| colspan=2 class="_pagecol" | page
|-
| Preface || v
|-
| Introduction || xiii
|-
| colspan=2 class="_tocgroup" | Annotated Analysis
|-
| {{gap|2em}} Hipparch || xliv
|-
| {{gap|2em}} Horsemanship || lii
|-
| {{gap|2em}} Hunting || lx
|-
| The Duties of a Hipparch || 1
|-
| On Horsemanship || 37
|-
| On Hunting: a Sportsman's Manual, commonly called Cynegeticus || 73
|-
| Index || 127
|}

Without Page styles this would render as:


page
Preface v
Introduction xiii
Annotated Analysis
Hipparch xliv
Horsemanship lii
Hunting lx
The Duties of a Hipparch 1
On Horsemanship 37
On Hunting: a Sportsman's Manual, commonly called Cynegeticus 73
Index 127


Somewhat functional, but not a very good representation. We can do a lot better with some simple and fairly reusable style rules.


First we need to make the table centered in the page.

._toc {
	margin-left: auto;
	margin-right: auto;
}

Then we make chapter titles small-caps, apply a hanging indent, left align (rather than justify) the text, and set the vertical align to the top.

/* The first column. */
._toc td:first-child {
	font-variant: small-caps; /* make text small-caps */
	padding-left: 2em; text-indent: -2em; /* fake hanging indent. */
	text-align: left; /* left-aligned text */
	vertical-align: top; /* top-aligned text */
}

Next we need to align the page numbers to the right and vertically to the bottom. We also want a little space between the page numbers and the chapter title, even for long titles, and this is a convenient place to add it.

/* The last / second column. */
._toc td:last-child {
	text-align: right; /* right-align text */
	vertical-align: bottom; /* bottom-align text */
	padding-left: 2em; /* force a little space */
}

Putting it all together we end up with this:


page
Preface v
Introduction xiii
Annotated Analysis
Hipparch xliv
Horsemanship lii
Hunting lx
The Duties of a Hipparch 1
On Horsemanship 37
On Hunting: a Sportsman's Manual, commonly called Cynegeticus 73
Index 127


That's much better, but there are still some glaring problems. The heading for the page number column is a bit off, and the chapter title "Annotated Analysis" is way off. The reason is that these two cells deviate from the others in the table: we've coded both of them to span both columns so they are getting styled as both the ":first-child" and the ":last-child". So because these two cells are different we need to add separate style rules for them.


/* The page number column heading needs special formatting. */
._toc ._pagecol {
	text-align: right; /* right-aligned text */
	font-size: 69%; /* x-smaller text */
	vertical-align: bottom; /* bottom-aligned */
	font-variant: all-small-caps; /* and all small caps */
}

/* A toc entry with no page number, because it heads sub-chapters. */
._toc td._tocgroup {
	text-align: left; /* left-aligned text */
}

With these extra styles in place the end result is:


page
Preface v
Introduction xiii
Annotated Analysis
Hipparch xliv
Horsemanship lii
Hunting lx
The Duties of a Hipparch 1
On Horsemanship 37
On Hunting: a Sportsman's Manual, commonly called Cynegeticus 73
Index 127


It's still not a pixel-perfect replica of the original page layout, but that should never be the goal. This version preserves enough of the original layout to be recognizable and preserve the feel of the original, without wasting inordinate amounts of time and volunteer effort.

Simple three-column table of contents[edit]

Another very common structure is the three-column table of contents. Here from Heart of the West:

That is a fairly simple three-column table. The first column is the chapter number, here as a roman numeral. The second is the chapter title. And the third is the page number. The chapter numbers are right-aligned, the chapter titles small-caps, and the page numbers right aligned. There's some spacing between the chapter title column and the two columns beside it. Long chapter titles also wrap with a hanging indent, so we need to vertically align the contents of each cell to make them match: the chapter number and chapter title to the top, the page number to the bottom.

This boils down to a wikitext structure like this (wikilinks and heading omitted for simplicity):

{| class="_toc"
|-
| colspan=2 class="_chapterheading" | CHAPTER || class="_pageheading" | PAGE
|-
| I. || Hearts and Crosses || 3
|-
| II. || The Ransom of Mack || 22
|-
| III. || Telemachus, Friend || 32
|-
| IV. || The Handbook of Hymen || 44
|-
| V. || The Pimienta Pancakes || 62
|-
| VI. || Seats of the Haughty || 78
|-
| VII. || Hygeia at the Solito || 99
|-
| VIII. || An Afternoon Miracle || 122
|-
| IX. || The Higher Abdication || 141
|-
| X. || Cupid à la Carte || 173
|-
| XI. || The Caballero’s Way || 200
|-
| XII. || The Sphinx Apple || 219
|-
| XIII. || The Missing Chord || 244
|-
| XIV. || A Call Loan || 257
|-
| XV. || The Princess and the Puma || 266
|-
| XVI. || The Indian Summer of Dry Valley Johnson || 276
|-
| XVII. || Christmas by Injunction || 288
|-
| XVIII. || A Chaparral Prince || 306
|-
| XIX. || The Reformation of Calliope || 321
|}

With no styling this renders as:


CHAPTER PAGE
I. Hearts and Crosses 3
II. The Ransom of Mack 22
III. Telemachus, Friend 32
IV. The Handbook of Hymen 44
V. The Pimienta Pancakes 62
VI. Seats of the Haughty 78
VII. Hygeia at the Solito 99
VIII. An Afternoon Miracle 122
IX. The Higher Abdication 141
X. Cupid à la Carte 173
XI. The Caballero’s Way 200
XII. The Sphinx Apple 219
XIII. The Missing Chord 244
XIV. A Call Loan 257
XV. The Princess and the Puma 266
XVI. The Indian Summer of Dry Valley Johnson 276
XVII. Christmas by Injunction 288
XVIII. A Chaparral Prince 306
XIX. The Reformation of Calliope 321


First we need to make the table centered in the page.

._toc {
	margin-left: auto;
	margin-right: auto;
}

Then we need to style the chapter number column. It is the first column of the table so we could have used :first-child, but since we have more than two columns in this table it is better to use :nth-child(1) so the selectors are consistent for all three columns.

._toc td:nth-child(1) {
	vertical-align: top; /* top-aligned */
	text-align: right; /* right-aligned */
	padding-right: 1em; /* force some space */
}

Then we need to make the chapter title left- and top-aligned, small caps, and turn on hanging indent.

._toc td:nth-child(2) {
	text-align: left;
	vertical-align: top;
	font-variant: small-caps;
	padding-left: 2em; text-indent: -2em; /* fake hanging indent. */
}

And the page number column right- and bottom aligned, with a little space between it and the chapter title.

._toc td:nth-child(3) {
	text-align: right;
	vertical-align: bottom;
	padding-left: 2em;
}

With these styles in place our table will render like this:


CHAPTER PAGE
I. Hearts and Crosses 3
II. The Ransom of Mack 22
III. Telemachus, Friend 32
IV. The Handbook of Hymen 44
V. The Pimienta Pancakes 62
VI. Seats of the Haughty 78
VII. Hygeia at the Solito 99
VIII. An Afternoon Miracle 122
IX. The Higher Abdication 141
X. Cupid à la Carte 173
XI. The Caballero’s Way 200
XII. The Sphinx Apple 219
XIII. The Missing Chord 244
XIV. A Call Loan 257
XV. The Princess and the Puma 266
XVI. The Indian Summer of Dry Valley Johnson 276
XVII. Christmas by Injunction 288
XVIII. A Chaparral Prince 306
XIX. The Reformation of Calliope 321


Much better. Now all we need are to style the column headings for the chapter number and page number columns:

._toc td._chapterheading {
	text-align: left;
	font-size: 69%;
	font-variant: all-small-caps;
	vertical-align: bottom;
}

._toc ._pageheading {
	text-align: right;
	font-size: 69%;
	vertical-align: bottom;
	font-variant: all-small-caps;
}

Because the heading for the chapter number spans two columns it will be affected by styles applied to both columns, and the heading for the chapter numbers will be affected by that column's styles. Therefore the selector used has to be more specific in order to override the general styles, in this case by specifying the element type (td) in addition to the class name.

With that in place the final rendering will be:


CHAPTER PAGE
I. Hearts and Crosses 3
II. The Ransom of Mack 22
III. Telemachus, Friend 32
IV. The Handbook of Hymen 44
V. The Pimienta Pancakes 62
VI. Seats of the Haughty 78
VII. Hygeia at the Solito 99
VIII. An Afternoon Miracle 122
IX. The Higher Abdication 141
X. Cupid à la Carte 173
XI. The Caballero’s Way 200
XII. The Sphinx Apple 219
XIII. The Missing Chord 244
XIV. A Call Loan 257
XV. The Princess and the Puma 266
XVI. The Indian Summer of Dry Valley Johnson 276
XVII. Christmas by Injunction 288
XVIII. A Chaparral Prince 306
XIX. The Reformation of Calliope 321


Other tables[edit]

No left or right outer border[edit]

A common style for tables is with thin borders around all cells, including the outer edges of the whole table, except for the left and right outer edges. This can be achieved by the following custom styles in the work's Index CSS:

._colhdbordernoside {
	border-collapse: collapse;
	border-top: 1px solid;
	border-bottom: 1px solid;
	margin:0 auto 0 auto;
}
._colhdbordernoside th {
	border-bottom: 1px solid;
	text-align: center;
}
._colhdbordernoside th:nth-child(n+2),
._colhdbordernoside td:nth-child(n+2) {
	border-left: 1px solid;
}

You can then add the class _colhdbordernoside to your table's wikimarkup:

{| class="_colhdbordernoside"
|-
!
! Gold
! Silver
! Lead
|-
| Lower || 0 || 6 || 6,8
|-
| Upper || 0 || 7 || 8,6
|}

Which will then render as:

Gold Silver Lead
Lower 0 6 6,8
Upper 0 7 8,6


Adding some cell padding and aligning the cell contents is left as an exercise for the reader. 😎


Notes[edit]

External links[edit]

Other CSS resources that you may find useful: