Personal styles

Jerks OFF! Personal Style Guide

Create expressive, contained text and image treatments with the Personal Styles editor.

Applies to Jerks OFF! 1.0.0 and styling schema 3.

Introduction

A Jerks OFF! style tells the extension how a replaced name or matched image should look. You create and preview styles in Options > Jerks > Personal Styles, using plain CSS declarations plus, for images, an optional overlay of text elements. The extension validates every style before it uses it; anything outside the rules below is rejected as a whole, never partly applied.

This guide covers the editor workflow, what the styling engine does, which CSS and template values are accepted, and how styles behave after saving. JSON examples show the validated structure that Jerks OFF! stores internally. Version 1.0 does not import or export style-pack files, so you do not need to write JSON to use the editor.

The rules are about safety, not taste. A style may change how the replaced word or image looks in many ways, but it can never load anything from the internet, run code, reach outside its own box on the page, or interfere with clicking and tapping.

Quick start

  1. Open Options > Jerks > Personal Styles.
  2. Choose New text style or New image style. To use an existing system style as a starting point, choose Duplicate on that style instead.
  3. Give the style a friendly name. Jerks OFF! generates a stable internal ID automatically.
  4. Use the Preview controls to choose a representative Jerk, nickname, and size.
  5. Enter CSS declarations in the relevant field. For an image style, you may style the original image, add an overlay, or do both.
  6. Use an Insert text value or Insert numeric value menu to place a supported template value at the current cursor position.
  7. Save the style, then select it as a default or assign it to an individual Jerk.

The preview updates while you edit. If the current draft is invalid, the preview keeps the last valid version and explains what needs attention.

How it works

Jerks OFF! watches pages for the people you've configured, called Jerks. When it finds one, it swaps the name for a nickname and applies a style to the result. Each Jerk has one text style and one image style selected.

Text styles decorate the nickname. The extension wraps each replaced nickname in its own small element, and your text style dresses that element: color, font, background, border, and so on. The surrounding page text is never touched.

Image styles act on a matched photo in one or both of two ways:

  • The subject is the original image itself. You can blur it, flip it, frame it, fade it, or hide it.
  • The overlay is a box the extension lays exactly over the image. It can cover the image completely and hold up to eight short pieces of text, such as the nickname. The overlay is see-through to clicks, so a linked image still opens its link.

Where styles come from

Styles are resolved in layers. A later layer wins over an earlier one when IDs match:

  1. Built-in styles shipped inside the extension, so it works offline from the first run.
  2. Library updates the extension downloads occasionally. These replace the built-in set as a whole.
  3. Your personal styles. A personal style with the same ID as a built-in one overrides it; removing yours brings the built-in one back.

Styles you create live in that third layer.

What happens to a style before it is used

Every style is checked when it is saved or loaded, and again when it is drawn. The checker reads each CSS property and value against an allowlist, substitutes any template tokens with safe test values, and confirms the whole style is within its size limits. If any single part fails, the entire style is refused with a message naming the problem. A refused style is never half-applied.

On the page, styles are applied one property at a time rather than as raw CSS text. This is why they work even on sites with strict security policies, and why the original page styling can be restored exactly when you choose to show original images.

Anatomy of a style

A style has a friendly name and a stable internal ID. The name is what you normally see in menus and may be changed later. Jerks OFF! generates the ID when the style is first saved and does not change it when you rename the style.

The editor handles this structure for you. The JSON below is a reference representation, not something you need to paste into the app.

"my-soft-blur": {
				  "kind": "image",
				  "label": "My soft blur",
				  "subject": { "declarations": "filter: blur(6px) grayscale(1); border-radius: 12px;" }
				}

Style IDs

  • Lowercase letters and digits only, separated by single hyphens or underscores: my-style, retro_2, neon.
  • Must start with a letter; at most 64 characters.
  • Not allowed: capitals, spaces, dots, leading or trailing or doubled separators (My Style, -neon, neon--pink).
  • New styles created in the editor use a reserved user-txt- or user-img- prefix and avoid existing IDs automatically.
  • Older personal data may contain a style with the same ID as a system style. That personal definition overrides the system definition; Use system style removes the override and reveals the system version again.

Style names

  • A name is required in the editor and may contain up to 80 characters.
  • Renaming a style does not break its assignments because references use the stable internal ID.
  • Two styles may have similar names, so the Personal Styles list also shows each internal ID.

Fields

Only these fields are accepted. Any other field anywhere in the style is an error.

FieldApplies toRequiredWhat it holds
kindallyes"text" or "image"
labelallno in stored data; required by the editorFriendly style name, 1 to 80 characters
subject.declarationstext, imagetext: yes; image: see belowCSS declarations for the nickname element or the original image
overlay.concealSubjectimagenotrue hides the original image under the overlay
overlay.declarationsimagenoCSS for the overlay box itself
overlay.elementsimagenoList of 1 to 8 text elements, drawn in order
overlay.elements[].contentimagenoPlain text, may include name tokens
overlay.elements[].declarationsimagenoCSS for that one element

An image style needs a subject, an overlay, or both. An overlay needs at least one of concealSubject: true, declarations, or elements. Each element needs content, declarations, or both.

Declarations

A declarations value is a single string of ordinary CSS property: value; pairs, as you would write inside an inline style="…" attribute. No selectors, no braces, no comments. Semicolons separate declarations; the final one is optional.

Text styles

A text style has kind: "text" and exactly one subject. It may not have an overlay. Its declarations style the element holding the nickname; the text inside it is always the nickname and cannot be changed by the style.

"neon-sign": {
				  "kind": "text",
				  "subject": {
				    "declarations": "color: #fff; background: linear-gradient(90deg, #ff2d95, #7a5cff); padding: 0 0.3em; border-radius: 0.3em; font-weight: 700; text-shadow: 0 0 4px #ff2d95;"
				  }
				}

What you can use

GroupProperties
Color and typecolor, font and every font-*, every text-* (decoration, shadow, transform, align…), every word-*, letter-spacing, line-height, white-space, overflow-wrap, hyphens, writing-mode, line-break, line-clamp, tab-size, initial-letter, hanging-punctuation, -webkit-text-*, -webkit-line-clamp
Backgroundsbackground and every background-*, including linear-gradient(), radial-gradient() and conic-gradient()
Boxborder*, outline*, box-* (e.g. box-shadow), padding*, margin*, width, height, min-* / max-* sizes, aspect-ratio, vertical-align
Effectsopacity, filter, backdrop-filter, mix-blend-mode, isolation, clip-path, mask*, -webkit-mask*
Transformstransform*, rotate, scale, translate, perspective*
Layoutdisplay, visibility, overflow, overflow-x, overflow-y, flex*, grid*, gap, row-gap, column-gap, align-*, justify-*, place-*, order

Normal CSS functions and units are fine: calc(), min(), max(), clamp(), rgb(), hsl(), em, rem, %, px, and so on.

Values with a fixed list

  • display: inline, inline-block, inline-flex, inline-grid, block, flex, grid, flow-root, contents, none, plus the two-word forms such as inline flex or block flow-root.
  • visibility: visible, hidden, collapse.
  • overflow: one or two of visible, hidden, clip, scroll, auto; overflow-x and overflow-y take one.

The one token text styles can use

Inside text-style CSS you may write {{ jerk.nickname.length }}, which becomes the nickname's character count (1 to 80) as a bare number. Add your own unit or wrap it in calc():

letter-spacing: calc(0.4em / {{ jerk.nickname.length }});

Image tokens such as {{ image.width }} are rejected in a text style. Name tokens such as {{ jerk.nickname }} are never allowed in CSS.

What you cannot use

  • position, top, left, right, bottom, inset, z-index: a nickname cannot move out of its place in the sentence or float above the page.
  • content, cursor, pointer-events, user-select, animation*, transition*, will-change, or any property not in the table above.
  • Image-only properties such as object-fit.

Image styles

An image style has kind: "image" and a subject, an overlay, or both. Use the subject to alter the photo itself; use the overlay to cover it with something of your own.

The subject: changing the original image

Subject declarations accept the same Backgrounds, Box, Effects, Transforms and Layout properties as text styles, plus five image properties: object-fit, object-position, object-view-box, image-rendering, image-orientation.

They do not accept text properties (color, font*, text-*, and the rest of the Color and type group). An image has no text to style.

"polaroid-flip": {
				  "kind": "image",
				  "subject": {
				    "declarations": "transform: scaleX(-1); filter: sepia(0.8) contrast(1.1); border: 10px solid #fdfdf8; border-bottom-width: 36px; box-shadow: 0 4px 12px rgb(0 0 0 / 0.35);"
				  }
				}

A subject-only style may hide the image with display: none or visibility: hidden. When the style also has an overlay, those two are rejected, because the overlay needs the image's box to size itself. Use concealSubject: true instead.

The overlay: covering the image

The overlay is a box placed exactly over the image and clipped to its edges. Think of it as a small stage the size of the photo.

  • concealSubject: true makes the original image visually transparent while keeping its geometry and link behavior. It does not promise to remove the image's existing alternative text from assistive technology. Leave it out (or false) for a see-through overlay, such as a caption or a tinted pane over the photo.
  • declarations style the stage itself: background, border, padding, and how its elements are laid out (flex or grid work well).
  • elements is an ordered list of up to eight text pieces placed on the stage. Each has optional content (the words) and optional declarations (how they look). An element with declarations but no content is useful as a decorative shape, such as a stripe or badge.
"censored-bar": {
				  "kind": "image",
				  "subject": { "declarations": "filter: blur(8px) saturate(0.4);" },
				  "overlay": {
				    "declarations": "display: grid; place-items: center;",
				    "elements": [
				      {
				        "content": "{{ jerk.nickname }}",
				        "declarations": "width: 100%; padding: 0.4em 0; background: #000; color: #fff; text-align: center; font: 700 clamp(10px, 9cqw, 40px) system-ui, sans-serif; letter-spacing: 0.08em; text-transform: uppercase;"
				      }
				    ]
				  }
				}

What overlay CSS accepts

Overlay and element declarations accept everything a text style accepts (so fonts and colors are fine here), plus positioning that stays inside the stage:

PropertyAllowed values
positionabsolute, relative, static (not fixed or sticky)
top, right, bottom, left, inset, inset-block*, inset-inline*ordinary lengths and percentages
z-indexauto or a whole number from -100 to 100

Image properties such as object-fit are not accepted on the overlay; there is no image inside it.

Sizing to the image

Overlays support container query units, which scale with the image box without any extra work: cqw (1% of width), cqh (1% of height), cqmin, cqmax. font-size: 12cqmin gives text that grows and shrinks with the photo. Prefer these to the tokens below whenever they will do.

Tokens in image styles

Tokens are written {{ name }}, with optional spaces inside the braces. There are two kinds, and each kind is accepted in only one place.

Number tokens, CSS only (subject, overlay and element declarations). Each becomes a bare number; add a unit yourself.

TokenValue
{{ image.width }}Rendered image width in CSS pixels
{{ image.height }}Rendered image height in CSS pixels
{{ image.shortSide }}The smaller of the two
{{ image.longSide }}The larger of the two
{{ jerk.nickname.length }}Nickname length in characters, 1 to 80

Example: font-size: calc({{ image.shortSide }}px / 6);. Styles using image.* tokens are recalculated when the image is resized, which costs a little more than cq* units.

Text tokens, overlay content only. Each inserts plain text.

TokenInserts
{{ jerk.nickname }}The nickname shown for this Jerk
{{ jerk.id }}The Jerk's internal ID
{{ jerk.name.full }}The real full name
{{ jerk.name.title }}, {{ jerk.name.first }}, {{ jerk.name.middle }}, {{ jerk.name.last }}One part of the real name

The jerk.name.* tokens put the real name back on screen, which defeats the point for many people. They work in a style a person picks for themselves, and the app warns when one is used. Avoid them in styles you share unless that is clearly the intent.

Content rules

  • Content is always shown as plain text. <b>, &amp; or any other markup appears literally, character for character.
  • It must contain at least one non-space character, at most 500 characters as written, at most 16 tokens, and at most 1,000 characters once tokens are filled in at their maximum lengths.
  • Emoji and any Unicode text are fine.

What image styles cannot do

  • Show a picture of your own. url(), image(), image-set(), cross-fade(), element(), paint() and any http:, https:, data: or blob: address are rejected. Draw with gradients, borders, shadows, masks, text and emoji instead.
  • Use raw SVG or HTML.
  • Escape the image box: no fixed or sticky position, and no positioning on the subject at all.
  • Capture clicks or hovers: no pointer-events, cursor, or interaction properties. The overlay always lets taps through to the original image and its link.
  • Animate: no animation or transition properties.

Saving, assigning, and deleting styles

  • A personal style may be reused by any number of Jerks.
  • The two Default style menus apply when a Jerk does not make its own selection.
  • A style selected directly by a Jerk takes precedence over the corresponding default.
  • Renaming a style keeps every assignment intact.
  • When deleting a style that still has explicit assignments, the confirmation explains that those references will fall back to their defaults.
  • A personal override of a system style uses Use system style instead of ordinary deletion. Removing the override leaves its references valid and reveals the bundled or downloaded system definition again.
  • Personal styles are stored with your Jerk preferences. They remain available in the local cache and synchronize when you use a Jerks OFF! account and cloud synchronization is available.

Jerks OFF! 1.0 does not import or export style-pack files. Do not edit Firebase or extension storage directly; bypassing the editor can make the complete Jerk-preferences document invalid. A future portability feature can use the same validated style structure without changing how styles render.

Fonts must already be on the viewer's device because a style cannot download one. End a font-family list with a generic family such as sans-serif so it has a dependable fallback.

Troubleshooting and limits

When a style is refused, the message names the style ID, the part (subject, overlay, or element number), and the reason. The commonest causes:

Message saysUsual causeFix
does not allow the CSS property …Property not on the allowlist, or a text property on an image subjectMove fonts and colors to an overlay element; drop position from subjects
contains unsupported CSS syntaxA /* comment */, { }, @, or !importantRemove it; declarations are bare property: value pairs
cannot contain CSS escape sequencesA backslash, such as \201CType the actual character instead
cannot load resources or use dynamic CSS valuesurl(), var(), attr(), image-set(), or a web or data addressDraw with gradients, shadows and text
does not allow the CSS value …A display, visibility, overflow, position or z-index value outside its listUse a listed value
cannot use display: none … with an overlayHiding the subject while also using an overlayUse "concealSubject": true
references unknown token / cannot use … in the … sinkMisspelled token, a name token in CSS, or a number token in contentCheck the token tables
contains unsupported field …A typo or an extra key such as name or descriptionRemove it; only the documented fields exist
unterminated string or functionAn unclosed quote or parenthesisBalance them

Limits at a glance

LimitValue
Style ID length64 characters
Personal styles per person50
Characters in one declarations string2,000
Declaration characters across a whole style (subject + overlay + all elements)2,000
CSS declarations across a whole style64
Overlay elements1 to 8
One element's content, as written500 characters
One element's content, with tokens filled in1,000 characters
Tokens in one content16
Tokens in one declarations string32
z-index in an overlay-100 to 100

The 2,000-character and 64-declaration budgets are shared by the whole style. Adding elements does not add room, so keep declarations tight.