Screenshot showing social media scene options for AO3 SkinGen customization.

AO3 Allowed CSS Properties: All 182, and Why Skins Fail

AO3 checks every CSS declaration when you save a site skin or work skin. One property it does not accept is enough to stop the whole skin from saving; it does not simply ignore that line. The quickest fix is to find the rejected property, replace it with an older or simpler equivalent, and check the value as well as the property name.

Below is the complete list currently used by AO3: 182 exact properties and 20 shorthand entries. Search for a property to get an immediate result, or sort either table alphabetically.

Short answer: If a property is missing from both lists, AO3 will usually reject it. There are two complications: shorthand entries match longer property names, and valid custom properties can be used in site skins but not work skins. Both are explained below.

Why one bad line rejects the whole skin

AO3 cleans user-submitted CSS before storing it. For every declaration, it checks the property name and then sanitizes the value. An unknown property produces an error. A value the sanitizer cannot parse produces another error. If cleaning removes every declaration from a rule, that empty rule produces an error too.

Because those errors make the skin invalid, this fails at save time:

#workskin .message-list {
  display: flex;
  gap: 1rem;
}

display is allowed. gap is not. The allowed line does not rescue the rejected one, so replace the gap rather than expecting AO3 to skip it:

#workskin .message + .message {
  margin-top: 1rem;
}

AO3’s error can identify the property, but a long pasted skin may contain that name more than once. Search the CSS for the exact property followed by a colon—for example, gap:—and check every occurrence.

The complete AO3 CSS allowlist

The first table is AO3’s exact SUPPORTED_CSS_PROPERTIES list. “Allowed” means AO3’s cleaner accepts the property name. It does not promise that every possible value is accepted, that every browser still implements the property, or that the property will visibly affect AO3’s HTML.

202 entries shown

182 exact properties
-replace
-use-link-source
accelerator
accent-color
aspect-ratio
align-content
align-items
align-self
alignment-adjust
alignment-baseline
appearance
azimuth
baseline-shift
behavior
binding
bookmark-label
bookmark-level
bookmark-target
bottom
box-align
box-direction
box-flex
box-flex-group
box-lines
box-orient
box-pack
box-shadow
box-sizing
caption-side
clear
clip
color
color-profile
color-scheme
content
counter-increment
counter-reset
crop
cue
cue-after
cue-before
cursor
direction
display
dominant-baseline
drop-initial-after-adjust
drop-initial-after-align
drop-initial-before-adjust
drop-initial-before-align
drop-initial-size
drop-initial-value
elevation
empty-cells
fill
filter
fit
fit-position
float
float-offset
font
font-effect
font-emphasize
font-emphasize-position
font-emphasize-style
font-family
font-size
font-size-adjust
font-smooth
font-stretch
font-style
font-variant
font-weight
grid-columns
grid-rows
hanging-punctuation
height
hyphenate-after
hyphenate-before
hyphenate-character
hyphenate-lines
hyphenate-resource
hyphens
icon
image-orientation
image-resolution
ime-mode
include-source
inline-box-align
justify-content
layout-flow
left
letter-spacing
line-break
line-height
line-stacking
line-stacking-ruby
line-stacking-shift
line-stacking-strategy
mark
mark-after
mark-before
marks
marquee-direction
marquee-play-count
marquee-speed
marquee-style
max-height
max-width
min-height
min-width
move-to
nav-down
nav-index
nav-left
nav-right
nav-up
opacity
order
orphans
page
page-policy
phonemes
pitch
pitch-range
play-during
position
presentation-level
punctuation-trim
quotes
rendering-intent
resize
rest
rest-after
rest-before
richness
right
rotation
rotation-point
ruby-align
ruby-overhang
ruby-position
ruby-span
size
speak
speak-header
speak-numeral
speak-punctuation
speech-rate
stress
string-set
stroke
stroke-width
tab-side
table-layout
target
target-name
target-new
target-position
top
unicode-bibi
unicode-bidi
user-select
vertical-align
visibility
voice-balance
voice-duration
voice-family
voice-pitch
voice-pitch-range
voice-rate
voice-stress
voice-volume
volume
white-space
white-space-collapse
widows
width
word-break
word-spacing
word-wrap
writing-mode
z-index

These are exact entries. Some also appear in the shorthand table because AO3 applies both checks.

20 shorthand substring entries
backgroundbackground-color, background-image
borderborder-radius, border-top
columncolumn-gap, grid-template-columns
cuecue-after, cue-before
flexflex-direction, flex-shrink
fontfont-family, font-size
layer-backgroundlayer-background-color
layout-gridlayout-grid-mode
list-stylelist-style-image, list-style-type
marginmargin-bottom, margin-inline
markermarker-offset
outlineoutline-color, outline-width
overflowoverflow-wrap, overflow-y
paddingpadding-left, padding-top
page-breakpage-break-after, page-break-inside
pausepause-after, pause-before
scrollbarscrollbar-color, scrollbar-width
texttext-align, text-decoration
transformtransform-origin
transitiontransition-duration

Examples show the property-name match only. AO3 still checks each declaration’s value.

Why the shorthand list behaves differently

The 20 shorthand entries are not merely 20 extra property names. AO3 checks whether a submitted property name contains one of those strings. That is why border also admits border-radius and border-bottom-left-radius, while text admits familiar names such as text-align and text-decoration.

The match is unusually broad. For example, grid-template-columns gets through the property-name check because the name contains column, even though grid-template-columns is not one of the 182 exact entries. Bare gap contains no shorthand entry and fails, while column-gap contains column and passes the name check.

A shorthand match does not guarantee that the declaration will work. AO3 checks its value next. Treat the shorthand list as an answer to “will this property name get past the first gate?”, not as a browser-support table.

Vendor-prefixed forms can also pass when they contain one of AO3’s accepted prefixes—moz, ms, o, or webkit—and a supported property. Prefer the ordinary property unless a prefixed version solves a real compatibility problem.

What about CSS variables?

There is an important site-skin/work-skin split. A well-formed custom property name such as --page-bg can pass the shared CSS cleaner for a site skin. The name must begin with two hyphens and then contain only letters, digits, hyphens, or underscores.

Work skins are stricter. They reject custom-property declarations and var() references, even though the same syntax can be accepted in a site skin. If code using variables will not save as a work skin, resolve every variable to its literal value:

/* Site-skin pattern — do not paste this into a work skin */
:root {
  --page-bg: #f7f2e8;
}

body {
  background-color: var(--page-bg);
}

For a work skin, use:

#workskin .page {
  background-color: #f7f2e8;
}

Custom properties are not included in the 182-property table: they follow a naming rule rather than a finite list, and they are not available in both kinds of skin.

Common rejected properties and what to use instead

Rejected CSSWhy it failsPractical replacement
gap and row-gapNeither name is on the exact list or matched by a shorthand.Put a margin on adjacent items. column-gap passes the name check, but is not a general replacement for every layout.
animationThe property is not accepted.Keep the final state as static CSS. Remove animation declarations rather than leaving a broken effect.
pointer-eventsThe property is not accepted.Avoid designs that depend on click-through overlays. Rework the stacking or remove the overlay.
backdrop-filterOnly filter appears in the exact list; backdrop-filter is a different name.Use a solid or semi-transparent background color, plus a border or shadow if needed.
aspect-ratioThe property is not accepted.Set explicit dimensions, use max-width with height: auto, or use a percentage-padding wrapper when appropriate.
insetThe property is not accepted.Write top, right, bottom, and left separately. All four are in the exact list.

Do not replace an unsupported property with the nearest-looking property unless it creates the same layout. filter, for example, does not reproduce backdrop-filter: one affects the element, while the other affects what is behind it.

The property may be allowed while the value is not

Checking the property list is only the first half of debugging. AO3 also restricts values and CSS structures. These are frequent failures:

  • calc(), clamp() and color-mix(): resolve them to literal numbers or colors before pasting.
  • Web fonts and @font-face: AO3 rejects @font-face. Use a web-safe font-family stack.
  • @media blocks: do not paste them into the CSS field. AO3 represents media as skin metadata rather than preserving an @media block in submitted skin CSS.
  • Image URLs: an allowed property such as background-image can still fail if its URL is not in a form AO3 accepts. A normal HTTPS address ending in .jpg, .jpeg, .png, or .gif is the safest shape; query strings and WebP are common problems.
  • The font shorthand: the property name is allowed, but a quoted font family can fail in its value. Write font-family, font-size, font-style, and font-weight separately.
  • content: use one quoted string, none, or an accepted image URL. An unquoted word or var() can be rejected.

When a skin is rejected, debug in this order:

  1. Search for property names that appear in neither table.
  2. Check for custom properties or var() in a work skin.
  3. Check functions in values, especially calc(), clamp() and color-mix().
  4. Check @font-face and @media.
  5. Check image addresses and font-family values.
  6. Save again, then read the CSS back from AO3 to confirm the stored version contains the rules you expected.

Changing several things at once makes the result harder to diagnose. Fix the first reported problem, save again, and continue until AO3 accepts the skin.

Check it before you paste

The AO3 Skin Generator app checks the CSS it generates against AO3’s property list and related value rules before you copy it. Its site-skin builder has 16 starting templates; its work-skin export covers iMessage, WhatsApp, Twitter/X, and Google-style pages. See the WordFokus AO3 Skin Generator guide for an overview of every feature.

If you write a skin by hand, keep this page open as the reference. Browser CSS documentation tells you what a browser supports; this table tells you what AO3 permits through its cleaner. You need both answers.

Limits of this reference

This list comes from the open-source OTW Archive code, not from a guess about modern CSS support. It was last checked against the upstream source on 9 August 2026. AO3 can change the allowlist, so use that date when comparing this page with a later error.

An allowed property can still be rejected because of its value. It can also save successfully and do nothing because a browser does not implement it or because its selector matches no AO3 element. This reference does not explain why the OTW selected these properties; the source does not give us that answer.

The generator and this article are unofficial and are not affiliated with the OTW or Archive of Our Own.

Sources

Similar Posts