Work Header

Fonts, and colors, and work skins, oh my!

Work Text:







CSS is just HTML, or rather: it is the same exact language, but what is now CSS used to be part of what was the whole of HTML and became reclassified as magically separate from the general stuff for semantic reasons.  It's not some different language: that change happened somewhere in the past couple of standards' changes over the decades.  If you knew HTML a couple of decades ago, then you already know how to do what is now called CSS, and you just need to know where to put it now in order to get it to work the way you're used to it doing.

My only reason for “coding” in AO3 is to enable a slightly more than basic typing (e.g.: alignment, typographical emphasis [bold, italic, etc.]), so that I can [judiciously] apply different fonts or colors.  I'm a book reader (i.e.: dead trees), and although I value the capabilities of webpages' layouts and such, my writing presentation is aimed at simpler things — but fonts or colors aren't immediately available by GUI nor even inline HTML (for some very good reasons, I'd say).  Nevertheless, the course of events brought me to the question of [CSS] work skin rules to perform these functions, and then on to the thought of applying them to the Summary section solely to demonstrate these same effects, at which point I noticed that although one can certainly cause them there, those effects (except for the choice of font, oddly enough) notably don't appear when viewing the same summary as listed in the search results page (and so I saw no impetus — for my purposes — to add the CSS code for higher level effects, if they'd be seen only when in the fic itself, where you'd be able to see them in the header Notes through straight HTML in any event).

It started when I wanted to select a couple of lines of material to be color coded in a story, but that wasn't vital, so I ignored it — after all, why go to such effort for so little added value?  Then eight months later (three days ago, in fact), I discovered that “Hồ Chí Minh” and “phở gầu trứng vịt” wouldn't render properly in AO3's default font of Lucida Grande: they should read “H Chí Minh” and “phở gu trứng vt”, and I'm a stickler for clear diacritics, so I spent a couple of hours mucking about with CSS in general (useful to ground what I learned afterward on AO3).  I use Times New Roman in my own documents and .pdfs (and it seems that I'm not the only one to think that it might be preferable to the current font defaults, but there's good reason against it: most people can read sans serif just fine, personal preferences aside, and many people have trouble reading serif fonts online, so it's better to default to sans serif whenever possible), and have no diacritics problems, hence hadn't noticed it on AO3 until now.


Basic research

Showing how to find CSS using right click's “Inspect [element]”

The pic above shows first the right-click menu's “Inspect [element]” being selected on top, then on the bottom left it shows the section of the inspection panel that will display the selected element's CSS in this case (or other useful and interesting data), and finally the bottom right shows how that CSS code actually looks when written as a rule in a work skin.  Don't panic: this is just to give you a visual and familiarize you with what we'll be talking about.

Having found AO3's Public work skins, and notably Homestuck (see this example for its “How to” and this one to see how that should look), I saw how the external CSS method isn't terribly different from raw HTML.  The Homestuck work skin uses only Courier (with a default of monospace), which makes it easy to focus solely on font color and size changes and highlighting, or coding errata (for example: although it talks about various characters' individualized fonts, it contains rules for the Caliborn character but not for the Captor character, so if one were to choose the class .captor, then the span of text selected for Captor wouldn't be in a font individualized to them, and so would default to AO3's standard Lucida Grande [or if you right-click to inspect the element: 'Lucida Grande', 'Lucida Sans Unicode', 'GNU Unifont', Verdana, Helvetica, sans-serif;]).  That caught my attention because MS specifies Courier New for Tiếng Việt (which is where the diacritic issue came up, after all).

Here's a sample of the Homestuck work skin, showing two rules (.dad and .pipefan413); this shows that rules are permitted to be identical, and that a rule can contain multiple declarations (four in this case: font size, and weight, and family [listing two values], and color):

#workskin .dad,
#workskin .pipefan413 {
  font-size: 14px;
  font-weight: bold;
  font-family: courier, monospace;
  color: #4b4b4b;

The Undertale work skin turned out to be far more streamlined (lacking multi-functioned classes) and much smoother (with intuitive names) than Homestuck was, and made it so simple to see how to arrange a font-family element.  The Basic Formatting work skin was beautiful, mostly just duplicating some HTML and RTF, and adding only font colors.

Here's a rule from Undertale (a simple rule, here: just one property [the font family] and five preferred values):

#workskin .comicsans {
  font-family: 'comic sans ms', 'comic sans', 'chalkboard se', 'chalkboard', cursive;

and a rule from Basic Formatting (which has similar simple rules for indents and spoilers and borders and so forth):

#workskin .font-green {
  color: green;


So I tested multiple fonts all at once (those already installed, at least) to see which ones would turn “ầ” into “”, “ị” into “”, & “ồ” into “” (also checking some individual fonts not installed on my system).  While I was at it, I also checked to see if these fonts would fix the problem with “̄S” (combining macron) or “̅S” (combining overline), and found that I'd have to keep using the “S̅” that I had found at (or more simply the HTML of “S̅” = “S̅” {which looks too far right-shifted over some glyphs, as in the case of “O̅”}, but they're both just too long for use with lowercase letters, as with “o̅” vs. the more satisfactory “ō” from my computer's character map, but keeping the HTML for uppercase letters, since the char map's version “Ō” simply doesn't suit).

That gave me some suitable fonts to satisfy my criteria (in order of descending priority):

  1. Fix the diacritics by placing the grave accent above the circumflex;
  2. settle for nearly above, if I must;
  3. deal with it being at the leading (left) edge if absolutely necessary.
  4. Use sans serif fonts if at all possible, in order to minimize contrast with the surrounding text;
  5. fallback to serif fonts that at least functioned for the diacritics (just in case none of the sans serif fonts were loaded to the reader's device).

TO BE CLEAR: you can download a font in order to see how your fic will look with that font, but that won't cause the fic to be written in that font for everyone else to see it in that same font if their system doesn't already have that font installed — installing a font onto your own system will only affect your own system, not the fic itself on AO3 nor any other reader's devices.  If they already have that font, then it will show up (assuming that they're not using an AO3 site skin or a browser setting / third party app to override it), but if not then their system will check for the next font listed in your declaration, and the next, until it reaches the end of your declaration.  If their system doesn't have any of the fonts in the font family that you list, then it will check for the AO3 defaults.  If it doesn't have any of AO3's defaults, then it will just use whatever it normally defaults to on its own.

For example: let's say that you had a rule that read font-family: courier, monospace;.

  1. Their system will check its fonts for courier;
  2. failing that, it will then check for monospace;
  3. if it doesn't have that one either, then it will go down AO3's default font-family in the same manner: 'Lucida Grande', 'Lucida Sans Unicode', 'GNU Unifont', Verdana, Helvetica, sans-serif;
  4. and if it had none of those named fonts, then it would try to display in whatever sans serif font it had available (presumably it would have one, I'm sure, but if not, then obviously it would just display whatever it could).


Working all of this out decided the question of the older and mostly irrelevant issue of font colors: as long as I had to make a work skin to fix the diacritics, why not incorporate those too (particularly since I'll likely enough add to it over time)?  For example... add some rules for red, green, and blue text capability (if you look carefully, you'll note that I didn't quite use Basic Formatting's green, having instead chosen to go with #27b300).  I even tossed in bright yellow and pale yellow highlighting (N.B.: the HTML term for highlighting is mark, but meh: that ain't natural) options (though I didn't see myself as likely to use these outside of tutorials, I did end up doing so for the illustration of an admission ticket in an old story]).  Once more unto the web, this time for a color picker (N.B.: you might want to stick to the standard 140 [or perhaps 147], since pretty much all browsers will take these names or values, but older browsers don't always support other colors and will have to default to the closest thing that they can approximate such other colors with).



Results  Contents ↑

After all of that, here's my CSS rule to de-concatenate diacritic marks and the other rules mentioned so far (plus a few related rules) to put into your own skin and work from there, if you'd like — it pushes 15 fairly popular fonts before giving up, so is likely robust against diacritics failing from dearth of font choice (as long as the reader hasn't disabled creator's style, at any rate):

#workskin .diacritics {
  font-family: Lucida Console, Arial, Ebrima, Helvetica, Verdana, Segoe UI, Calibri, Candara, Corbel, Microsoft Sans Serif, Tahoma, Times New Roman, Cambria, Constantia, Trebuchet;

#workskin .handwriting-printed {
  font-family: Segoe Print, Ink Free;

#workskin .handwriting-fluffy {
  font-family: Noteworthy;

#workskin .handwriting-cursive-scrawl {
  font-family: Bradley Hand ITC;

#workskin .handwriting-cursive-neat {
  font-style: italic;
  font-family: Segoe Script, Lucida Handwriting;

#workskin .handwriting-cursive-fluffy {
  font-family: Sacramento, Lucida Handwriting;

#workskin .handwriting-cursive-fancy {
  font-family: Freestyle Script, Snell Roundhand;

#workskin .handwriting-calligraphy {
  font-family: Monotype Corsiva, Harrington;

#workskin .typeset-manuscript {
  font-family: Lucida Blackletter, Luminari;

#workskin .red {
  color: red;

#workskin .green {
  color: #27b300;

#workskin .blue {
  color: blue;

#workskin .highlight-bright-yellow {
  background-color: #ffff0099;

#workskin .highlight-pale-yellow {
  background-color: #ffffb399;

#workskin .highlight-blue {
  background-color: blue;
  opacity: 0.7;
  color: white;

#workskin .large-friendly-letters {
  font-style: italic;
  font-family: Segoe Script;
  font-size: 5em;
  font-weight: bold;
  color: #27b300;

#workskin .greek {
  font-family: Times New Roman, Georgia, Cambria, Constantia, Sylfaen, Candara, Sitka Banner, Microsoft Sans Serif, Palatino Linotype;

#workskin .edwardian {
  font-family: Edwardian Script ITC, Edwardian Scr ITC TT, ITC EDWARDIAN SCRIPT, Adine Kirnberg Script, Ballet, Medusa, Kunstler Script, Palace Script MT, Zapfino, Snell Roundhand, P22 Zaner, Aphrosine, Italianno, Slight;
  font-size: 2em;

#workskin .red-dwarf {
  font-family: MicrogrammaDBolExt, Eurostile Bold condensed, Microgramma, Eurostile extended, Newton, 'Pathway Gothic One', serif;
  color: red;
  font-weight: 600;
  letter-spacing: 6px;
  text-align: justify;
/* There is definitely an issue with text-align: justify: it's working for this rule, but not for the one linked in this comment (if you have trouble, then try adding display: inline-block; width: 100%;). */
  padding: 5%;

#workskin .large-rosy-letters {
  font-style: italic;
  font-family: Edwardian Script ITC, Ballet, Medusa, Kunstler Script, Palace Script MT, Zapfino, Snell Roundhand, P22 Zaner, Aphrosine, Italianno, Slight;
  font-size: 3em;
  font-weight: bold;
  color: deeppink;

#workskin .large-rosy-shadowed {
  font-style: italic;
  font-family: Edwardian Script ITC, Ballet, Medusa, Kunstler Script, Palace Script MT, Zapfino, Snell Roundhand, P22 Zaner, Aphrosine, Italianno, Slight;
  font-size: 3em;
  font-weight: bold;
  color: deeppink;
  text-shadow: 6px 6px 12px #20202099;

#workskin .rosy-outline {
  font-family: Edwardian Script ITC, Ballet, Medusa, Kunstler Script, Palace Script MT, Zapfino, Snell Roundhand, P22 Zaner, Aphrosine, Italianno, Slight;
  font-weight: bold;
  font-style: italic;
  font-size: 3em;
  color: #FF1493;
  -webkit-text-stroke: 2px #FF1493;
  -webkit-text-fill-color: #FFFFFF;

#workskin .rosy-outline {
  color: #FFFFFF;
  font-size: 2em;
  -webkit-text-stroke: 2px #FF1493;
  text-shadow: 0px 4px 4px #0000FF;

#workskin .rosy-outline-blue-shadow {
  color: rgba(255, 255, 255, 0.9);
  font-size: 2em;
  -webkit-text-stroke: 2px rgba(255, 20, 147, 0.9);
  text-shadow: 0px 4px 4px rgba(0, 0, 255, 0.9);

Why is some of my hex code running four pairs?  The “99” at the ends of the highlighting color codes is to reduce the opacity so that they don't block text that they overlap on other rows (I went with a higher value so that I didn't have to fiddle with the colors themselves), just like the blue highlight includes “0.7”; for the record, AO3's CSS also accepts RGB and RGBA (i.e.: there are other color encodings that are not supported on AO3 at this time).  You can check the list of AO3's allowed CSS properties for more variables once you get the hang of the basics above.  And if you're thinking of changing from one font to another, but aren't sure which ones most people might have (and hence are likely to actually work as you want them to), then you might want to start with “core fonts” and then research further as needed.

Those last two on the outlined text-stroke property are a little iffy.  .-webkit isn't supported by all browsers (though I had no problem on Chrome, Firefox, Opera, TOR, or Edge in a WIN 10 environment, nor on Safari in an iOS environment), and the color codes are funky in it on AO3's parser: the parser (which clearly accepts deeppink and other standard HTML names in the CSS rules) stripped standard names in that rule when I tested it (so: no “white” or “deeppink” or “blue”).  I included them for demonstration, using the hex values for a white fill #FFFFFF, deeppink outline #FF1493, and blue shadow #0000FF in order to make each section apparent, though the respective RGB equivalents of rgb(255, 255, 255), rgb(255, 20, 147), and rgba(0, 0, 255, 0.9) also functioned; even adding :hover to the end of the work skin name functioned with it (causing text of one look to take on a whole new look upon hovering one's cursor over it [which won't work on a 'phone]; you can test this quickly at JSFiddle).  Failed CSS might mean only no effect (as with a downloaded fic or disabled creator's style), or perhaps as bad as no text at all, but just as underlying HTML can act as a partial backup with boldface and such against failed CSS, one can likewise use a fail-forward trick to allow regular CSS to act in the event of .-webkit failure:

#workskin .large-rosy-shadowed-outline {
  font-family: Edwardian Script ITC, Ballet, Medusa, Kunstler Script, Palace Script MT, Zapfino, Snell Roundhand, P22 Zaner, Aphrosine, Italianno, Slight;
  font-weight: bold;
  font-style: italic;
  font-size: 3em;
  color: #FF1493;
/* If -webkit fails, then color: #FF1493 will act as a failsafe (test your own with text coded for color: #0000FF which will be blue only if the -webkit code fails to make it pink). */
  -webkit-text-fill-color: #FFFFFF;
  -webkit-text-stroke-width: 1px;
  -webkit-text-stroke-color: #FF1493;
  text-shadow: 2px 2px 2px #000000;

While not absolutely necessary, I imagine that you might wish visual examples of those effects, and many might not be able to visualize them from the raw code alone (though the following might not show you the results that I hope for, if your device doesn't contain any of the fonts in a given example's font-family declaration), so:

Greek: Α α, Β β, Γ γ, Δ δ, Ε ε, [Ϛ ϛ], Ζ ζ,
Η η, Θ θ, Ι ι, Κ κ, Λ λ, Μ μ,
Ν ν, Ξ ξ, Ο ο, Π π, [Ϟ ϟ], Ρ ρ, Σ σ/ς (Ϲ ϲ),
Τ τ, Υ υ, Φ φ (ϕ), Χ χ, Ψ ψ, Ω ω; [Ϡ ϡ].

Padding start ►|RED DWARF (from the TV show)|◄ End of padding
Large Friendly Letters
Large Rosy Letters
Large Rosy Shadowed
Rosy Outline
Rosy Outline Blue Shadow
Large Rosy Shadowed Outline



Links that actually LOOK LIKE LINKS <le gasp!>

One last thing.  I didn't waste my time marking every single link with HTML tags to <u>underscore</u> and CSS selectors to call a work skin rule to <span class="blue">turn the font blue</span> — it'd be easy enough, but think of the character space taken up in the footnotes! 😲  I did one better: created a rule that lets all of my contents' links (in the header, footer, summary, and main body... and even my author's name link, for some reason [meh: that's cool, too, I guess]) automatically become blue and underscored (i.e.: they just do it — period — no adding the CSS selectors anywhere within my work!).  I can't guarantee that it'll work on all browsers (I checked on Chrome, Firefox, Opera, MS Edge, and TOR in a WIN 10 environment; can't be bothered trying my iPhone's Safari, but ran it through some emulations [here's a page that tells you how to change your browser's user agent to test that way, though that doesn't seem to display as one would expect, so here's a free webpage to actually see the results]), but it'll surely help make your links pop for any readers not using a site skin or a third party browser add-on!  I pulled the link rule from cherryblossom's Dark Mode site skin, tweaked the font color for my own taste, added an underscore (not strictly necessary), dropped it into my work skin, and badda-bing.  Wanna know how?

#workskin a,
#workskin a:link {
  color: #0000EE;
  text-decoration: underline;


Hidden text

As a side-note, one can even make text become invisible with a simple CSS rule (just declare width: 0px; [though I also did that to the height] and overflow: hidden; — I've tested it, and it works on AO3, as you can “see” [or rather not see] between these two pointers: ►◄ [don't believe me?  Highlight that and right-click and Inspect the Element]), and InfinitysWraith's tutorial's 13th chapter appears to be fairly empty, but clicking a link in the 14th chapter reveals some hidden text in 13 that's called directly from the CSS (not stored within the HTML).  NB: As with any CSS (almost any, since some few effects manage to carry over), the hidden text is NOT hidden in element inspection or downloaded .pdf / .html files (becoming visible: you might find a surprise or two in this very page, in fact... like being nibbled to death by cats) — amusingly, sometimes text can become sort-of-hidden through non-CSS causes, e.g.: CTRL-F for the word “inane” in ch. 6 of InfinitysWraith's tutorial and you find the whole paragraph in the source code or the downloaded .html page, but it's cut off [visually] in the .pdf after the word “couldn't” for some reason (I say “visually” because copying that paragraph and the next will show one further word when pasted: “create”) — but as an extra quirk, the zero-width CSS-hidden text remains hidden here on AO3 even with creator's style turned off (at least for paragraphs and spans, not for description lists [though that could at least be subdued by minimal opacity, I suppose]; haven't checked other element types).

StackOverflow has some leads for a CSS equivalent of Java's onclick, but I haven't gone down that rabbit hole yet (since I'm not looking to write interactive clickable fic material), so I don't know how much of that might function within AO3's CSS constraints.


...and that's that for that.  Unless you're now scratching your head with materials in hand and no tools with which to apply them...  OK, yeah, you can't simply plunk that code into a story's Work Text edit field and watch it go, even if you know how to code CSS for a web page: AO3 uses external sheets (the other two ways are internal in a page's header and inline at any given element within the body of the HTML ), so you just have to embrace the suck and use external CSS (I say embrace the suck, but actually I think that it makes things way-the-hell easier to write, more reader-flexible, and somewhat easier to explain [there are other good reasons too, on the tech and sec side of the house]).




  1. Copy my CSS rules from the Results subsection, above.
  2. Go to {My Dashboard ► Skins ► My Work Skins ► Create Work Skin}.
  3. Paste that copied material into the CSS Edit Field.
  4. /*  Don't bother putting in any notes: AO3's parser will strip 'em right out.  */
  5. Fill in all of the other fields of course, just as you would if you were writing a story or chapter.
  6. Save (edit later, as much as you need/want, as often as needed/wanted).

Want to add something?  No problem, toss it in — here, try these grey highlight (the line-height lowers its ceiling, the height raises its floor) and double-underscore options:

#workskin .highlight-grey {
  line-height: 0.3;
  height: 1em;
  background-color: #d9d9d999;

#workskin .double-underscore {
  border-bottom: 0.18em double;

  • N.B.: Look at these 3 “L”s (normal vs. code surrounds highlight vs. highlight surrounds code) and spot the highlight differences (and it isn't that one set is grey and the other is blue, the extra set being present only for potential viewscreen contrast issues and/or color blindness):
    • ...l......l......l...
    • ...l......l......l...
    • The first one (of either row) is just highlight's normal size font, but the second and third (of each row) are both highlighted and HTML tagged for coded font.  The difference is that the height of the highlighted span is either short to match the shrunken font size (code outside / highlight inside) or tall (highlight outside / code inside).  The latter looks awkward to me, but the point is that one's results depend on one's input sequence: which one (CSS selector or HTML tag) is applied first (surrounding outside) will determine what the overriding effect will actually be (like a pizza: dough then stuff, not stuff then dough).


I held off on font size 'til now for reason.  You can change font-size in a couple of ways.  In a normal web page, you might have used something like HTML (inline CSS, which I don't address here, but you can find more on it at Khan Academy as a starting point) <p style="font-size:30px">for a 30 pixel font</p>, but that's deprecated in HTML 5 and isn't even an option within AO3's HTML GUI anyway and some of the lesser HTML tags don't work right on iOS (more on that in the bonus section).  That leaves us two alternatives:

  • Use headings in HTML (the styles of which are controlled by AO3's parent skin, and you can adjust for this, but it's well beyond our scope here: see the bonus round at the end), e.g.: <h1>Heading h1 is pretty big</h1>, <h2>Heading h2 isn't quite as big</h2>, etc.
    • (or similarly: <small> and <big> [effectively ≈1.2x multiplier, actually only bumping a 16px font into the next text size category of 19.2→19px], which you can nest for n-tuple effects);
  • Adjust them in a CSS skin (and hope that the reader hasn't disabled creator's style).  The explanation for the different ways to change font size is a bit complicated, so I'll forego that and simply list what they are and how to use them (test and see which one(s) below feel right for you  ):
    • The simplest answer is to use absolute value names (e.g.: “small”, “medium”, “large”, etc. — used like this: font-size: xx-large; } [where xx-large would yield 32px]),
      • but for that, you might prefer more control over the actual sizes themselves, so just take normal font size to be 16px normally (which for me is actually 15px, which might be from my browser or monitor or AO3 or other reasons), hence if you wanted to almost double the height of some word, then you might code the CSS as font-size: 30px; },
      • alternatively (because some pixel counts don't change enough to be particularly visible: 15px comes out the same as 16, for example), if you had some specific multiple in mind, then you could code it as font-size: 1.9rem; } and get that word's height to 1.9 times the height of the words around it;
      • each of these yields the exact result that you aim for, but leaves readers locked into your specific sizes, so that zooming in/out won't help them with visual display (imagine that they don't have their glasses with them or something).
    • Sometimes you don't have an absolute size in mind for a specific element (or do wish to permit readers' zooming to affect the text's displayed size), and want them to scale relative to the element that they're in, in which case you might instead choose em, which is just like rem in multiplying a font by some amount, except that font-size: 1.9em; } will scale with window size (AO3 encourages this approach specifically, due to readers' varied browser and font settings),
      • though font-size: 190%; } should(?) come out the same (TL;DR: em on AO3 turned out to be round-down integers only, but % worked very well for me),
      • and relative keyword names (i.e.: smaller; } and larger; }) are an OK 3rd choice: not as much control, but easy to use, the increase being basically around the range of +1/8 to +1/4,
      • but the remaining possibilities might not be so great: 1.9ex; } (the height of which is relative to the height of the root element's font's lowercase “x” [e.g.: a paragraph font-size being p { font-size: 2ex; } would double the size relative to however many pixels were defined in the CSS initially, so had that been HTML { font-size: 20px; }, then the resulting doubled height would be 40 pixels for some fonts, but a bit shorter/taller for other fonts]),
      • or even 1.9ch; } (this works almost the same way as the ex method, but instead of being relative to the height of the root element's lowercase “x”, the ch is relative to the width of the zero [which can be wider/same/smaller relative to the letter “O” from one font to another]).
    • Then there are size changes that are relative to the viewscreen itself, specifically font-size: 20vw; } and font-size: 20vh; }.  These will greatly affect the font size relative to the screen itself, rather than the rest of the text — and viewscreens for computers aren't the same size as those for 'phones, so 20vw would give a result that's 1/5 of the screen width in either case, with the visual flow of text probably(?) rendering differently from one aspect ratio to another2 (I've used vw only once so far, and that was to adjust a paragraph to resemble an admission ticket [I'm disinclined to use a public domain image as a background or sketch my own, and I don't know if AO3's CSS even supports SVG to code for a fancier border {though I suspect that the ORV System Work Skin could be modified just right, and it's an amazing piece of work}], so I'm not very experienced or well-practiced with vw).
        The CSS and HTML for that ticket are shown below, for those who might be curious:

      #workskin .ticket {
        width: 20vw;
        text-align: center;
        background: #ffffb399;
        min-width: 15em;

      <p class="ticket" align="center"><a name="AcmeTicket" rel="nofollow" id="AcmeTicket"></a><br />
      <b>Ticket number 1729<br />
      Seat 25F<br />
      Acme Building Auditorium<b><br />
      <br />

      Ticket number 1729
      Seat 25F
      Acme Building Auditorium

    • I gave in to my OCD and tested them out in a skin to see their effects (except for vw/vh, for reasons).  For whatever it's worth, here are my results (taking the unaffected 100%-zoom 12px height lowercase-"h" as my standard, so that 190% = 22.8px [rounded to nearest integer would give 23px] and 200% = 24px), though I resisted checking multiple zooms and nested elements-within-elements; your mileage might vary:
      • h1, h2, h3, and big = remained 12px tall... FAIL: no change (I didn't expect these to work in CSS);
      • xx-large = 25px [x-large only 19px] — OP CK GOOD (these working surprised me);
      • 30px in CSS gave 22px(?!?) as a result... EPIC FAIL: can't rely on an "exact" measurement;
      • 22pt = 21px, and 22.5pt & 23pt both gave 22px... WORKAROUND: these should've been 30px(±0.7), but functional enough if one assumes pt≈px (30pt = 29px);
      • 1.9rem = 22px, 2rem = 23px — OP CK GOOD;
      • 1em & 1.9em = 11px (not 12px: these shrank my sample by 1px), 2em = 22px — OP CK GOOD;
      • 190% = 21px, not 22.8px→23px (N.B.: but finer control than em...) — OP CK GOOD;
      • larger = 13px (1px larger), not 14.7px(=15px)-16px... FAIL: no significant change (didn't expect it to work at all, so this is something anyway);
      • 1.9ex = 11px, 2ex = 12px, 3ex = 17px, and 4ex = 23px... EPIC FAIL: with a lowercase "x" height of 8px, these should've been ~15.2px, 16px, 24px, & 32px, respectively (i.e.: results were ~71-75% of expected values);
      • 1.9ch = 14px (2px larger), 2ch = 15 (3px larger), 3ch = 22px, and 4ch = 29px... EPIC FAIL: with the width of a zero "0" being 9px, these should've been ~17.1px, 18px, 27px, & 36px, respectively (i.e.: results were ~81-83% of expected values).
    • In every case, it might be a good idea to check their browser-compatibilities, if only to at least cover the major bases.
    • N.B.: I found that the em approach works a little differently for images, or at least on AO3 using straight HTML (not in a CSS skin, where one might expect em to be used): in the img tag, I wrote width="40em" directly within the HTML GUI, and it sorta worked.
           Based on how em should work, I had initially scaled an image's width to 2em (which at 15px height per em should give 30px of width for this image), on the assumption that this would yield a width of approximately 2 text-heights (I'm trying to control image height directly, but seem constrained to controlling it by adjusting the width); instead, the result was perhaps 2 pixels of height — but it did work (albeit not as intended).  That said, I found eventually that 40em worked optimally for my purposes; what should have resulted in an image width of 40 text-heights came out as ~2 text-row heights.
           I take this to mean that to some extent "em" is read for images as the object's pixels (that is: a row of text isn't just the height of a font, but includes some padding above and below: highlighting [with class=] some normal text at 100% zoom, a screencap dropped into MS Paint showed the letter "h" to be 12px, but the height of the row's highlighting to be 24px; this is exactly in keeping with my earlier need to adjust highlight opacity, since each text-row's span height turns out to be 20px non-overlapping + 2px overlapping padding below [merely selecting a few rows of text via cursor gave seemingly-less relevant results of 14+5]).
           For the curious: see the gilded capital-O image (basically a medieval illuminated text image) that opens the first paragraph of “Zelda Invictus” (the chapter note of which explains a bit more detail of the image size tests).

    After the rigmarole of which font size methods work in one fashion vs. another (if you clicked to here by the TOC instead of reading all the way through: try to use em, not px), here's an example of how to skin them (pick any one type of font size per rule: not more than one in a given rule, but yes you can use one type of font size in one rule and another type of font size in another rule  ):  Contents ↑

    #workskin .courier {
      font-family: courier, monospace;

    #workskin .courier-30 {
      font-size: xx-large / 30px / 30pt (maybe others) / 1.9rem / 2em / 190% / larger / 1.9ex / 1.9ch...;
      font-family: courier, monospace;

    Notice that I said that although you can't use more than one type of font size in a single rule, you can still use one type of font size in one rule and another type of font size in another rule.  In the above rules, you might choose to write .courier { font-size: 110%; } and .courier-30 { font-size: 2em; }, for example.  Here, the term “value” is fuzzy: in English, it means “how much” (which might lead you to think of something like 2 or 110), but in coding means [roughly] “a variable” [in the mathematical sense] (e.g.: em or %), so I chose to avoid ambiguity by calling that a “type of font size” (to make it explicitly clear that I was referring to em and % and all of the others listed above).

And... badda-bing, you're G2G!  Except that you might not know how to actually apply any of this; there's a decent chance that you know some common HTML tags such as <b>, <u>, and <i> (and speaking of italics, by now you might have enough to work with to consider changing font angles through the work skin using font-style: oblique 10deg; } or some other angle [a back-sloped angle being in negative degrees, which is browser-dependent at the time of this writing]; I gave it only a quick try, no dice)... but how do you use CSS selectors in your story?



Using CSS selectors in your chapters' HTML:  Contents ↑

If you need to learn how to tag paragraphs or spans with an #id selector or a .class selector, then I strongly suggest Khan Academy (or search there for another CSS course), and maybe a brief stop at W3Schools and CSS-Tricks (and CodePen and JSFiddle can both be useful for testing purposes, but a bit of a hassle that might be prettier than actually of value if you're new to CSS, much less to HTML), but here's a quick and dirty demo.  If you do have some clue, but not much, then consider this AO3 FAQ instead (or as well), and possibly AO3's allowed HTML FAQ.  If you're already a wiz, you might not be reading this — granted — but you might wish to work on some advanced special effects.

First: check my code.  Notice how the first one is called “.diacritics”?  Ignore the word diacritics, that's just a convenient choice of word for me (you might prefer to name it accent-marks or semantic_marks or IshKabibble  : don't worry [anyone get this joke?], that part is entirely up to you as long as you don't start the name with a number, so .answer42 is OK but .42answer will stay in the CSS skin but the HTML parser will strip it right back out [just don't leave a space in the name, and avoid most special symbols; I prefer the underscore conceptually, but the dash makes it so that I can double click just one word and replace it, rather than click-and-drag across the characters that I need to change in the name]).  Instead notice how that selector begins with a “.” period; that makes it a class selector, and one of those can be applied to as many different spots as you want, like a generic bar code (a can of soup at the store will have the same bar code as any other can of the same brand and type).

Sometimes you might want to identify a unique section for some reason; I had no need for that, but had I, then I would have written “#diacritics” instead.  Notice how this one starts with a “#” pound sign instead; that makes it an ID selector, and they're like a serial number: one use only and that's it.

To make the word “red” turn red, I'd simply tag that word (or set of words, or whatever) as follows:

<span class="red">red</span>

Maybe the word “span” (a term for distance) isn't familiar to you.  Let's try something more familiar: raw HTML.  Is this paragraph example a little better?

<p align="justify" class="red">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

We can even use multiple class selectors on the same element.  For example, if I wanted to mix <span class="diacritics"></span> with <span class="red"></span> in order to achieve (I made these bold to draw attention; they wouldn't automatically become bold just from the CSS used here as-is), then I could simply write it as3

<span class="diacritics red"></span>

Cool.  What if you have 20 paragraphs that you want in red, then 10 in red and italic (or a different font size, or whatever), then 20 in just italic?  Well, aside from writing a new CSS rule that turns text into italic form and combining the class selectors in your HTML (or writing a CSS rule that does both, if you're liable to use the combination often), you might have a lot of copy-and-paste on your hands — or you could just start with a <div> tag right before the beginning of that first paragraph, go to the end of those first 20 paragraphs, toss in a </div> tag, etc., and add the appropriate class selector(s), of course.

<div class="red">
  <p>The first paragraph that you want to be re-formatted.</p>
  <p>A zillion more paragraphs in the middle.</p>
  <p>The last paragraph of this set that you want formatted in one swell foop.</p>

Rinse and repeat for changing fonts or highlighting, etc..  Don't forget that you can write CSS selectors to perform the same functions as HTML tags (<b>, <u>, <i>, etc. — deprecated these days in favor of things like <em>, but I'm old school [muscle memory]: the AO3 RTE will write “<em>” if I drop a fic in, pre-formatted, but I'll use the HTML editor and write “<i>” when formatting directly); I haven't, but you never know when you might want to change all of one to all of another (or some portion of them, on a case-by-case basis).  Now consider the reduced time factors involved with one method vs. another:

  • Scrolling through the entire document and manually hitting the button-on for one and button-off for the other (or even hitting CTRL-whichever for each) in every single instance in RTF vs.
  • hitting CTRL-F / ⌘-F / grep to jump to each relevant tag in your HTML, then hitting CTRL-V vs.
  • swapping between AO3 and your offline copy for find-and-replace-all vs.
  • simply going to your work skin and changing the single value of that class selector's rule (e.g.: “.SecretSquirrel'sAddress { color: red; }” → “.SecretSquirrel'sAddress { color: blue; }”).

That might explain some use for class selectors, but why bother with an id selector?  Well, what if you don't want to sift through a hundred chapters or load them all as a single page (and CTRL-F / ⌘-F / grep) in order to find and change the properties of a specific comment in a thread or a crucial NSN (National Stock Number) somewhere in your document?  Yeah, sometimes a unique identifier can be useful.

Before you go, please, lemme ask just one last question there, Lieutenant Colombo, if I could have a moment of your time — please:#workskin” begins with “#”, so it's an id selector calling the work skin rule in the first place, so is nesting id="SomeUniqueName" even possible here?  Let's try it out.

#workskin #testpurple {
  color: purple;

If ►THIS TEXT RIGHT HERE◄ is purple, then yes, it works (I did do a perfectly functional purple font, so had to rename this one with test so that I could use the regular one elsewhere).  Oh look, it's not purple (and I tried colorizing the span using both id=... as one would here and class=... just in case).  We might have to simply use class selectors with unique names for such cases as would normally have had with id selectors' unique names (unless I ferret out some way to make id selectors function [in the CSS] within AO3 work skins [N.B.: id selectors do work on AO3 mind you, as in the case of this work's header-note/footnote links]).



  • Just like you can have a zillion fics, whether you have skins or not, you can just as easily have have a zillion skins, whether you have any fics or not.  You can always edit the skin's effects, or change which skin applies to a fic.  You can use a work skin on as many fics at once as you wish — but any given fic can't have more than one skin at a time applied to it.
  • This is just my own take on it, but if AO3 permits you to do something with HTML, then go that route instead of relying on CSS solely — if the reader disables creators style, then this will minimize that impact on their reading experience.
    • Aside from layout and style differences if the HTML weren't to parallel the CSS as closely as possible, consider a simple image: one could insert #workskin .pictures { max-width: 100%; height: auto; } into one's skin to automatically scale a map (damned good back-up in case you forget to scale it when you link the image) and hit the image's HTML with something like <img class="pictures" src="URL.jpg" alt="A few descriptive words." />, but without <img src="URL.jpg" alt="A few descriptive words." width="100%" height="auto" /> also in the HTML, that map image could still end up far too small/large if the reader were to disable creator's style.  UPDATE: not long after I wrote this, I read that AO3 was adjusting the system to ensure that images would be automatically no more than 100% screenwidth; I haven't tested this, since I scale mine to certain percentages for one reason or another, but if so then one might not need to worry quite so much about limiting the size.
  • FIFO: First-in-first-out doesn't apply here.  AO3's parser will fix mistakes, but it's still good practice to close your most recent tag or selector before closing less-recent ones.  For example, you could write <span class="blue"><code>.Fo { ob: ar; }</span></code> and it should correct it to <span class="blue"><code>.Fo { ob: ar; }</code></span> for you, but sometimes it will glitch, and you might even confuse it so badly that it can't properly correct it.  (This is otherwise an important practice if you were to write a regular webpage somewhere out there: even if it were to come out OK for you, an older browser might not be able to sort out your mistake.)
    • And here's my code for circling words (a modified version of a StackOverflow answer); I'm still trying to work out how to present a circling that doesn't rely on the border itself (since you can't shrink the border to within the height of the contents without SVG, and I'm still trying to work out if SVG is even supported on AO3, perhaps a varying gradient could be applied to ch):  Contents ↑

      #workskin .circle-red {
        border: 0.14em solid white;
        border-radius: 0.3em;
        border-color: red;
        padding: 0.05em 0.05em 0.05em 0.05em;
        text-align: center;
        margin: 0.15em;

      #workskin .circle-green {
        border: 0.14em solid white;
        border-radius: 0.3em;
        border-color: green;
        padding: 0.05em 0.05em 0.05em 0.05em;
        text-align: center;
        margin: 0.15em;

      #workskin .circle-blue {
        border: 0.14em solid white;
        border-radius: 0.3em;
        border-color: blue;
        padding: 0.05em 0.05em 0.05em 0.05em;
        text-align: center;
        margin: 0.15em;

  • AO3 does accept the CSS display: inline-block, but keep in mind that whatever it affects won't be able to line break (it will be non-wrapping — ask me how I know  ).
  • Also: do keep in mind that even if the reader hasn't disabled creator's style, even though HTML formatting should be OK in a downloaded version, nonetheless the CSS formatting still won't appear in downloads (.pdf, .epub, or .mobi files)
    • nor will the vertical bar along the left side of blockquotes,
    • nor the overspill of fonts listed in my code after Microsoft Sans Serif (Tahoma, Times New Roman, Cambria, Constantia, Trebuchet;),
    • nor any words copied from (as in the case of those at the bottom of this tutorial's summary, the {𝑫𝒐𝒏'𝒕 𝒇𝒐𝒓𝒈𝒆𝒕 𝒕𝒐 𝑳𝒊𝒌𝒆, 𝑺𝒉𝒂𝒓𝒆, 𝒂𝒏𝒅 𝑺𝒖𝒃𝒔𝒄𝒓𝒊𝒃𝒆! ❤️} text doesn't show there [nor here] when viewed in a download [though that text is visibly different in the summary even in the search lists, implying that the external font pasted in is supported by AO3's overall CSS, therefore CSS effects in a summary can be caused to be visible in search-views to an extent] — though the S̅ from will function even in a download, implying that it's maybe an actual font instead of CSS of style="text-decoration:overline" [though inspecting that page showed their “S̅” to be font-family Arial Unicode MS, 'lucida grande', tahoma, verdana, arial, sans-serif;];
      • I assume that it ultimately comes down to whether your own device has any given font available, rather than AO3 embedding-or-not of fonts into the downloads),
      • contradictorily, I tried the other download options and found that the words from (inspect element revealed their bold-italic-serif font-family to be TimesNewRoman, Times New Roman, Times, Baskerville, Georgia, serif;) remained present in the HTML, as did those missing fonts listed in the snippet of my CSS, and the code snippets are in the original code-looking font or similar enough, but I don't have any suitable programs to check the .azw3, .epub, or .mobi versions (and I'm not going to install anything just to test this);
        • N.B.: I've mentioned “inspect element” a few times now, but if you've no idea what that means, there are a few ways to open the developer tools:
          • right-click ► inspect [element] ► styles
          • F12 (at least... as long as your keyboard isn't some stupid-ass design... which mine is... [unless you're not too lazy to reprogram the keys' macros, of course, which I am... 😑 😔])
          • CTRL-SHIFT-I
          • CTRL-SHIFT-C
          • ⌘-⌥-I
          • ⌘-⌥-J
          • ⌘-SHIFT-C
          • or several ways on different browser menus
          • and apparently on iPhone or Android (I haven't tested these, so I left the search-results link rather than a specific website's instructions, since they'll change over time)
      • and the diacritics in the .pdf don't have their CSS and so are rendered a little oddly in whichever font the .pdf chose (I'm not going to even try to fix that).
  • Finally: RED LENS / BLUE LENS.  Your code might be faulty, sure, or maybe you typo'd something, ja.  Sometimes though, it's perfectly valid code with zero typos, and it still glitches.  This can happen simply due to which browser you're viewing the results in, and possibly which OS your computer (or 'phone) is running, hence my “red lens / blue lens” reference to the old 3D movie glasses: things look different when viewed through different filters.

    Case in point: a friend of mine (jld_az) was hoping to make links within her fics display as a normal link-blue font to the readers (highlighted with yellow, rather than underscored, but otherwise normal link-blue), barring readers' site skins overriding this, of course.  That was before I'd glommed the automatic link-CSS, so I just threw down a basic combo of HTML underscore and CSS blue font.  The code was fine, the work skin was applied correctly, and the HTML was wrapped around things properly to call the CSS rules, but it wouldn't display on the 'phone or in her Mac on Chrome (it did display just fine in my WIN 10 on Opera and Firefox, half-functioned with a blue-grey highlight black-font on TOR, and failed on MS Edge and Chrome [once I turned off my 3rd party app so that I could check, since I run an app that forces all links on every site to appear as font-blue and underscored]).

    It gets stranger.  I tested out the code myself, in the very paragraph that you just read (maybe you can see her linked profile name as link-blue and/or yellow-highlighted, maybe not...), and got different results: zero effect on any of those in my WIN 10 (where I know it had worked for her fic in 2½ browsers) except for full functionality on Chrome (in which I know it hadn't worked for their fic).  Go figure (damned Gremlins...).  This didn't change whether the span was wrapped around the outside of the link (as “<span class...><a href...>name here</a></span>”) or placed within it (as “<a href...><span class...>name here</span></a>”).

    The rule is below, if you're curious, but the takeaway point is that you can't count on things displaying everywhere the way that they display for your browser and OS (or apparently even in your own browser and OS from one source to another).

    #workskin .blue-in-yellow {
      color: blue;
      background-color: #ffff0099;



If you're feeling really froggy, you might even run the page through a few browser emulators to see how it presumably looks through them.  I don't plan to, but you can can find them via Google or DuckDuckGo or wherever.  How well they might work is a dice roll.  By way of example: I know how my stuff looks through several browsers in real world (not emulation), but only when running in my Win 10 environment; I went through Chrome and tried for shits and giggles, where I ran an emulation of Firefox (which I have, and so know how my stuff looks in Firefox on my system) and they set that up as if in Linux (which I'm not running, though Mint looks tempting), and their result wasn't the same, but I don't know if I should have expected it to be since I'm not dual-booted.  This idea becomes increasingly unappealing if one considers that apparently most readers access AO3 via their 'phones, and there are a lot of variables there (worse, if you tried to cover everything possible).

Alternatively (and maybe more easily, though I still don't know that it is or isn't reliably), as mentioned earlier: you can simply emulate other browsers within your own browser, and here's a page (same one as earlier) that tells you how to change your browser's user agent, though there are no doubt many more like it; as mentioned before, that doesn't seem to display as one would expect, so here's a free webpage to actually see the results. 😉


And finally: text below illustrations...

Composite Map of Light World, for "Seize the Deity".

<div class="centertext60perwide">

<p align="left" class="blue">Using a modified version (in blockquote below) of the CSS at “To skin a fic  ”, and the HTML that you see around this paragraph, you can center text below a pic and have it match the width of the pic itself.  I set the pic (from “Seize the Deity  ”) to 60% screenwidth here, hence my choice of 60% screenwidth text (the pic width and text width needn't be the same percentage of the element).  The work skin's CSS rule centers the paragraph and limits it to 60% width, but the HTML aligns the actual text within the paragraph's margins (in this case: left aligned, specifically to show more contrast than my usual preference of justified text; default on AO3 [when no alignment is specified] is left-aligned right-ragged, so this was unnecessary code, but I made it explicit for illustration purposes here).

I could have written the whole as <p align="left" class="centertext60perwide blue">, and this new paragraph would still be in black font, as it is now, but I'd then need to repeat the <p align="left" class="centertext60perwide"> if I wanted those other factors to remain true.  I could also have written it as <div align="left" class="centertext60perwide blue"> [with no per-paragraph HTML], in which case I could write a zillion paragraphs without having to repeat that same code for every single paragraph (I'd then only have to open [and keep count of] new nested-DIVs for special cases, such as making this paragraph black fonted).  I wrote it as I did to demonstrate that simultaneous strength and weakness: no need to repeat the CSS rule for centered 60% (it's inherited 'til I close the DIV: scroll down a little farther to see it in the blockquote), but the font reverted to default black after closing the blue-coded paragraph (without more code needed for anything).

It works for videos (and .gifs), too (the first three examples having come from random fics that contained vids and .gifs):

<iframe src="" width=300 height=auto frameborder="0" allowfullscreen="" title="finding you | culmets"></iframe>

I used width=300 and height=auto because I found that 60 was some tiny unit of measurement (not the 60% relative to this DIV element that I had expected it to be), and so opted for 300 units to demonstrate the result without it being so tiny that it's hidden by the play button (at least 300 doesn't quite get that small on my computer screen; it might on a 'phone).  I'm honestly half-wondering if my telling it width=300 might represent something ridiculous like “make the video's height 300% of one character's width  ”.

You could assign unquoted-values as in the code above, which I modified from araviis's “finding you”, but I would imagine their originally assigned quoted-values of width="640" height="360" to probably(?) be a better idea.  Digging back into other video fics, we find that the basic format remains the same (though not all inputs are necessary, and the sequence is flexible), though the URL can look rather different even when aimed at the same domain, as with the contrasting example of from Elokuva (Aeiouna)'s 2013 fic “[Fanvid] Ace”.  A functional and fairly typical example for percentage-values (used on a .gif) can be found in VerseNaberrie's “Wholloween”, which used the code <img alt="doc" height="30%" src="" title="doc" width="50%" data-pagespeed-url-hash="938279310" onload="pagespeed.CriticalImages.checkImageForCriticality(this);"/>.

I don't have a quick answer for the sizes though.  I didn't check on my 'phone, but the first vid (above, a few paragraphs) is tiny and the second one (down a paragraph) normal on my computer screen... until resizing my browser to 'phone aspect ratio and finding the first one to have grown to a respectable size and the second one unaffected badly: the right half goes completely off-screen).  Good luck with that.

I don't intend to load vids into my fics (I have 2 fics with 2 vids each [opening and closing themes], and that's it I think), and that's beyond this work's theater of operations anyway; this was only to demonstrate that it works, not to go into whatever controls which URLs nor which configurations do or don't function (note that I showed araviis's original URL, not “INSERT URL HERE”; that was to show one that definitely works, since just putting in a normal thing like and calling it quits didn't cut it).

I right-clicked a video (not mine) in one of my playlists to get the embedding code and played around with it.  The video above works, but trying 60% on it in my testbed wasn't so hot (cf. the explicit sizing in the code below vs. the apparently-not-percentage-sizing of the code in first example).
 That width="60%" was with height removed entirely (making no mention of it at all), height=auto, height="auto", and height="60%".  They all sucked.

<p align=center>
<iframe src="" width="712" height="534" frameborder="0" allowfullscreen="" title="The Glory Of Love, covered by New Found Glory"></iframe>

Now about the centered-60%-width CSS rule that I promised you:

#workskin .centertext60perwide {
  width: 60%;
  margin: auto;




😸   BONUS ROUND:  you've been patient, so here's your cookie!   😸  Contents ↑

Before we get to the bit that intrigues me, I'll mention one of the more recent bits that you might have run into of late and which certainly showpieces some flashy potential.  I'm assuming that you've probably dug through available resources on work skins, CSS, and semantically similar variations, but bear with me for a moment here.  (By the way: I didn't use any of the code from “All the emoji” in order to emplace the emoji in this tutorial, I just copied them from Facebook and pasted them right in without thinking; I got lucky, but this also means that maybe copying from Facebook is a workaround, or that AO3's database now supports emoji.)...
 OTOH, strange things happen with emoji: this section's header used to have normal yellow-filled cat faces,  but I just noticed (28 Dec 2021) that they'd become non-filled monochrome disregard last: they're back to being yellow cat faces, NLT 27 Feb 2022 <sigh... I give up, whatever>.  I checked without creator's style (which I didn't expect to fix it), tried turning off my 3rd party plug-in that forces all links anywhere to become blue underscore (as if that's somehow related?), and even replaced them just in case, but no dice.  Then I swapped them out with a similar set (prettier, too, I think), but same problem.  I even tried the HTML &#128568; and &#x1F638; for them, and then the Windows emoji keyboard<shrug!>
 Tested for variables (even as I thought I should maybe update my browser): it's monochrome in Chrome (hilarious, but doubly odd, since they're functioning on Chrome outside of AO3) and MS Edge, but perfectly fine [yellow filled] on Firefox and Opera (even in AO3)... and TOR shat out completely with non-emoji boxed codes 01F638 and 01F604 (even on DuckDuckGo and Google).

As a late edit, this paragraph is probably better fit with the theme of skin873 (farther down), but I'm putting it here because of its intermediate level material (way past this 101 tutorial).  Skin873 is more for the advanced students (which I most certainly am not).

  • For those who wish to know just what they can do with their outside CSS skills, or wish to work at a higher level than just fonts, please see AO3's “full list of supported CSS properties”;
  • for those who'd like to really stretch what they can do with AO3, but need more intel on what's where here, please see dustnik's “AO3 CSS Selector Ids and Classes”.

I mentioned a couple of fics linked in this tutorial's Summary section.  How to Override the Archive's Automated Chapter Headers is more tutorially dry-seeming (but beautifully concise) and less dazzling than Bleed Gold (I call it that due to the .png header [even though it's green onhover], but the title is actually the slightly less catchy “CSS in Testing”), and one can see the impact far more clearly in Bleed Gold — but Bleed Gold presents a surprising layer of subtlety in its End Notes.  Although these two examples present far more flexibility than I'm liable to make use of, those of you who seek to present eye-catching effects (webpage-like, in the case of Bleed Gold) in AO3 could benefit from it, and there are others:

  • comic book thought bubbles (disable that tutorial's style to see their CSS that they plaintexted into the body of their tutorial),
  • sticky notes,
  • La_Temperanza's OnHover (which can have trouble rendering certain characters without using CSS (ISO)), and Simbeline's OnHover (designed to also function on 'phones, though it might not work on screen readers [and obviously not with creator's CSS style turned off, or in downloads {since those don't incorporate the CSS}]), or the appealing text bubble of Red_Vines's approach,
    • though you could simply eschew the CSS in favor of pure HTML using <acronym title="Here you'd enter the words that you want the hover-box to show">using some inline HTML for a little OnHover box</acronym> (same effect as <abbr title>) from CodenameCarrot's guide to limited HTML (caution: though this OnHover box functions in HTML download for me, it might fail on mobile devices, and semi-fails in .pdf [the hover field appeared, but contained only a clickable link back to this tutorial, rather than displaying the correct text]), or Otter_Von_Bismarck's <span title="Mouseover text goes here">surreptitious mouseover</span> (hover over those words, which don't look as if there's an OnHover, and you'll get a text field [same invisibility effect as you'd get from <dfn title>], though it too might have trouble on 'phones),
    • NB: the <... title...> approach isn't limited to just those, but will instead attach to any HTML element — poke around and you'll find that you can assign a hover field to whole paragraphs <p title...> and list items <li title...> (hint: you're reading a list item right now, so maybe there's something to see here with a hover) and even entire divisions <div title...>, and even images <img src... title...> (haddya think XKCD does it? 😉),

When actually viewing the fic's page itself, the Bleed Gold effects on its summary contents are present when set to Show Creator's Style, and absent when set to Hide Creator's Style.  The fun trick (that subtle twist that I mentioned initially) comes when you click(See the end of the chapter for more notes.)” [sic]: it goes to an entirely different chapter (cf. the exact wording of the “note” link vs. standard w.r.t. the URL of Bleed Gold vs. URL of its notes): bluntly, they're actually not that same chapter's end notes themselves at the bottom of the page (though the formal function is pretty much exactly that), but rather a whole new chapter with a somewhat different summary.


Addendum: for those who would prefer some layer of security against plagiarists copying their material, I give you the following code from 0KKULTiC on Twitter (who states that it doesn't work on iOS Safari) — they provided a linked example that I was still able to copy and paste from (without first disabling creator's style), but the principle is still worth mentioning:

#workskin p {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;


Now for the bits that I haven't seen mentioned anywhere else.

I looked under the hood.  Found inherited font-family 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, sans-serif.  Couldn't shake a feeling that something was “off”, especially after seeing fonts of .pdf and .html downloads from fics with no CSS in the first place.

Tried identifying fonts through cropped shots of AO3 online vs. downloaded forms using

Right-clicked to inspect element, noticed div.userstuff.module (cf. user agent stylesheet in the flashy pages, e.g.: Sliding Doors [the body of which explicitly includes /* CSS notes */, but was written in 2011, hence prior to the note-scrubbing that occurs nowadays {which I presume was part of the 2016 Archive 2.0 sweep}, therefore its CSS likely no longer includes them])
    <link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/skins/skin_873_archive_2_0/1_site_screen_.css"/>

Long story short: the trail led to skins/873 — not itself a skin, but a parent page (either it simply lists available skins that happen to be linked, or site skins are chained to call 873 itself which in turn calls from any skin pages chained into it).  There are 32 skins listed there right now, so I'll drop only a couple of small sample snippets.  It turns out that it's not a secret though, just not something that you're liable to think about if you were to run into it early on.  Work out which ones are used where, and you might have an easier time doing your own site skins (and probably come out with a few nuggets for work skins — hell, I did [just look at the links in this work] — and CSS in general [those of you with a broader skill-set might prefer OTW's source on GitHub]).
    Archive 2.0: (1) core skin by AO3

body, .toggled form, .dynamic form, .secondary, .dropdown {
  background: #fff;
  color: #2a2a2a;
  font: 100%/1.125 'Lucida Grande', 'Lucida Sans Unicode', 'GNU Unifont', Verdana, Helvetica, sans-serif;
  margin: 0;
  padding: 0;
    Archive 2.0: (2) elements skin by AO3
    From what I can see, it seems that at least some of the raw HTML inline-seeming elements (to wit: “<code>”, if nothing else) that we code in our writing aren't actually running inline, but are apparently instead simply acting as class selectors and calling the functions defined in the relevant AO3 stylesheets (depending on whether the element is in the summary/notes, body, etc.).

body {
  font: 100%/1.125 'Lucida Grande', 'Lucida Sans Unicode', 'GNU Unifont', Verdana, Helvetica, sans-serif;

h1, h2, h3, h4, h5, h6, .heading {
  font-family: Georgia, serif;
  font-weight: 400;

blockquote, pre {
  font: 1em 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, sans-serif;
  margin: 0.643em;

kbd, tt, code, var, pre, samp {
  font: normal 0.857em 'Monaco', 'Consolas', Courier, monospace;
  margin: auto;

Well, you get the idea.  The rules that I showed here are only relevant to fonts (since I'm focused on simple typesetting and basic layout, mostly), but the original sheets contain a lot more formatting code than just this stuff (takeaway point if you're looking for bells and whistles).  Have fun!  😉  (I'm going to go back to trying to get my charmap to gen “␢” from U+2422 or ALT+09250... and maybe work on perpetual motion for an encore.)


Oh, yeah... one last thing: I don't really speak Java, but if you do, then you might like to know that the source code of this work (and any other) states explicitly “While we've done our best to make the core functionality of this site accessible without javascript, it will work better with it enabled. Please consider turning it on! ”, along with a few links (just CTRL-F for “Java” in the source).  I poked around and found an unofficial 2017 API, if that helps any!


And for extra credit for the real Wizzes out there: can you explain this quirk: chapter-footnote appears in single-chapter work (click it, then look at the extra footnote)?

That's all, folks — but if you like my writing style, then ►please subscribe to my author's page ◄ in order to get constant updates on all of my work!



O ~~~ O