Intro to Sheet Development

Building a Character Sheet

To build a sheet, you must have access to a Pro account.

To edit a custom character sheet for a game:

  1. Select the Games menu, and select My Games.
  2. Select the game to go to the campaign details page.
  3. Under the Settings menu, select Game Settings.
  4. Select Custom from the Character Sheet Template menu.

The editor has four tabs: HTML Layout, CSS Styling, Translation, and Preview.

Restrictions & Security Filtering

Generally speaking, character sheets are created with HTML, CSS, and JavaScript (for Sheet Workers), but there exist some constraints that are good to know for the intermediate and advanced user. There are a few caveats to be aware of in regards to the security filtering that Roll20 applies to your HTML as well:


In the browser, the character sheet is basically wrapped inside a giant <form> tag.

  • Id attributes cannot be used. (Any ID attributes on one character's sheet would affect another character's sheet in the same campaign when opened.
  • Any DOM functionalities can't be used.
  • Do not use reserved HTML tags such as <head> or <body> in your character sheet HTML. Doing so will prevent your character sheet from loading in the virtual tabletop.
  • Some tags like <section><header><footer>,<footer> doesn't work either.
  • Attribute names are case-insensitive when checked for uniqueness. All inputs (and selects, and text areas, etc.) should have a unique attribute name.
  • All classes that don't start with "attr_", "repeating_", or "roll_" will be prefixed with "sheet-".
  • All images will be passed through the Roll20 image proxy to prevent security attacks. This should be largely transparent to you and shouldn't affect anything, but it's something to be aware of.
  • <svg> isn't supported.
  • All attributes in Roll Templates need to be written with double quotes, as single quotes result in them being completely ignored.


  • In the CSS file, all general classes should have a start with a sheet- prefix for Roll20 to read them.
  • Media queries can't currently be utilized.
  • Default Fonts: The following fonts can be accessed by default: ArialPatrick .HandContrail OneShadows Into Light and Candal.
  • Google Fonts: Google fonts are now available with the @import-function.


  • DOM can't be used.
  • Some javascript functions or functionalities can't be used. See Sheet Worker Documentation for more details.

Only Use Classes, not IDs

You should not use IDs on your tags (for example, DO NOT do <input type='text' id='name' />). Since there are multiple copies of each sheet in the DOM at once, using an ID is incorrect since IDs should only be used on unique elements.

This does mean that you cannot utilize ID-linked <label> elements (eg, <label for="my_id">My Label Text</label>). You can place elements inside the label to link them together (eg, <label>Label Text <input ... /></label>), although that can come at the expense of some flexibility in your CSS.

Common Mistakes

1. Forgetting to name attributes with the attr_ (e.g. <input type="number" name="attr_dexterity"> vs. <input type="number" name="dexterity">). This results in no data being saved in the field after the sheet is closed.

2. Forgetting to add sheet- to the class names in your .css file. This is not needed in the .html file, Roll20 automatically assumes all classes have that prefix there. 

3. Using an underscore in the name/class of repeating sections. Each <fieldset> needs to have unique classname that starts with repeating_, and the rest of the name cannot have underscores or the section won't save any information.

4. Only looking at the Preview Panel when making changes. The preview panel doesn't show a 100% accurate view of how the sheet will look/work and completely ignores sheetworkers, so you need to login to the campaign and open a character sheet there to be sure of sheet visuals/functionality.

5. Not looking at existing sheets. Seeing how existing sheets have been made and structured can help you avoid reinventing the wheel or making mistakes as a result of knowing HTML/CSS/JavaScript but having little familiarity with how character sheets are created. All sheets in the Character sheet repository are under MIT license so are free(and encouraged) to be used as templates for creating your own sheet instead of making everything from scratch.

6. Not asking for help when you get stuck. Roll20 has a small but active community who works with creating and improving character sheets, and are often eager to help out if you got stuck on some feature you've tried to figure out. Roll20 Character Sheet & Compendium Forums.

The Sheet Editor

Preview Panel

The "Preview Panel/Sheet Editor" showing a preview of a character sheet. This preview is not identical to how the sheet looks in Roll20, and is only an approximation.

The Preview panel applies all the same security precautions and filtering as the main Roll20 application. Be sure to right-click and Inspect Element if you are seeing strange behavior (e.g. your styles aren't being applied correctly) -- it may be that there is a security filter that is changing the name of a class or something similar.

The preview panel updates in real-time whenever you change the HTML, CSS, or Translation on your sheet. This shows you an approximation of what the sheet would look like in-game. It's useful for quickly checking superficial changes while you're editing, but to be sure of the actual end-result, you need to enter the game and open the sheet itself.

If you make any changes in the character sheet editor while in the game, you must save your changes and refresh the active Roll20 game. In addition, if the character sheet contains <rolltemplate>, the code for it will be seen as unprocessed in the preview window. It's recommended that roll templates are placed at the end of the sheet's code so they don't obscure the sheet's visuals when using the preview panel.

Custom Sheet Sandbox

As an alternative to the Sheet Editor, you can now try to use the Custom Sheet Sandbox for developing your sheet. The Custom Sheet Sandbox allows you to select and upload HMTL, CSS & Translation files from inside the sandbox and see the sheet update instantly. The Sandbox also allows for testing of your Default Sheet Settings via your sheet.json file.

HTML Layout

HTML is used to define the fields and layout inside the character sheet template.  You can use most of the basic HTML tags, such as p, div, textarea, input, select, img in your sheet. However, be aware, Roll20 utilizes HTML differently than what you would normally expect. Some tags, such as <button>, will have different default functionality in the Roll20 environment. We'll further discuss this later in the article.

Note that you cannot use Javascript on your sheet template except in the case of Sheet Worker scripts.

Storing User Data

Most HTML-tags used for storing user input can be used in a Roll20 sheet, with a notable distinction. For each tag, you must include a name-attribute which begins with attr_. This defines the unique attribute-name for the tag, and tells that it's an attribute that should be saved to the character. This must also be done for values & attributes that the user can't edit, for that data to be usable in calculations or similar. All these attributes (except in repeating sections) will show up in the "Attributes & Abilities" tab on the character sheet, after having been edited for the first time.

Text & Numbers

To create a field for saving text or numbers entered by the user, use the <input type="text"><input type="number"> or <textarea> tags. (Note: <input> tags must have a type specified (text, number, hidden, checkbox, or radio)).


<input type="number" name="attr_Strength" />
<input type="text" name="attr_class" />
<textarea name="attr_notes"></textarea>

If you want the field to utilize the "max" of an attribute instead of the normal value, you can append _max onto the name of the field, e.g. <input type="number" name="attr_Strength_max" />.

You can also use a < span> tag to display a read-only value on your sheet, e.g. < span name="attr_Strength"></ span>. It is possible to include a span tag that has the same attribute name as an input tag, and the span tag will be updated whenever the input is modified.

Default Values

You can also optionally include a value attribute on the tag, which will define the default value for the field.

For example, the following would define an "AC" field with a default value of "0". If no default value is specified, it is an empty string ("").

<input type="number" name="attr_AC" value="0" />

Auto-Calculating Values

You can include a formula in the default value for the field, and specify the disabled="true" attribute on the field. If you do so, the sheet will display the result of the formula instead of the formula itself. For example, <input type="number" name="attr_StrMod" value="@{Strength}/2" disabled="true" /> would create a "StrMod" field that shows half the Strength value. These auto-calculating attributes can be used in Sheet Rolls, Macros, and Abilities as normal.

Note that you can only include attributes from the current Character. You also can't include macros, abilities, or rolls...just basic math such as @{Intelligence}/2+@{Level}. You also have access to the floor, round, and ceil functions, such as floor(@{Intelligence}/2).

If your auto-calculated field depends of another auto-calculated field(s), you have to add parenthesis around intermediate formula(s). Otherwise miscalculations could appear.


<input type="number" name="attr_StrMod" value="(@{Strength}/2)" disabled="true" />
<input type="number" name="attr_StrModLeveled" value="@{StrMod}+@{Level}" disabled="true" />

Note: Calculations do not show up in the Preview, they only show on a character sheet in-game.

Auto-calculating values will increase the load of a sheet when its opened and as a result should be used sparingly. Consider using Sheet Worker Scripts to complete calculations that are conditional.

Character Names

When adding a text field for the name of the character, you can make it automatically link with the journal's character name by giving it the name attribute of attr_character_name.

<input type="text" name="attr_character_name" />


It can be useful to save hidden variables on the character sheet that the user doesn't need to see, in which case the "hidden" input-type can be used. It will save the value of the input, but won't be shown on the character sheet in any way, making it easier to user than having to hide it with CSS.


<input type="hidden" value="10" name="attr_str_mod" value="0" />

Usercases: Saving stats used by Sheet Worker Scripts, Advanced Character Sheet Translation options, and some CSS Wizardry examples.

Dropdown menu

The <select> tag can be used to save info a pre-determined list of options the user can access from a dropdown menu.


<select name="attr_WoundLevel">
  <option value="0" selected="selected">Healthy</option>
  <option value="1">Stunned</option>
  <option value="1">Wounded</option>
  <option value="2">Wounded Twice</option>
  <option value="5">Incapacitated</option>
  <option value="10">Mortally Wounded</option>

To choose which option is selected by default, include the selected="selected" like in the example.

Checkboxes and Radio Buttons

For checkboxes and radio buttons, you must always specify a value-attribute.

For checkboxes, if the box is checked the attribute will be set to the value of the checkbox. If it is not checked, it will be set to "0". If you would like a checkbox to be checked by default, add the checked="true"-attribute.


<input type="checkbox" name="attr_HasShield" value="1" checked="true" />

For radio buttons, if one of the radio buttons is selected, the attribute will be set to the value of that radio button. If no radio buttons are selected, the value will be an empty string. At least one of the radio buttons should have the checked="true" attribute to set a default value. Radio buttons are the only type of field where it is meant to have more then one field with the same name-attribute.


<input type="radio" value="10" name="attr_Multiplier" />
<input type="radio" value="25" name="attr_Multiplier" checked="true" />

Static Info

General text, such as names & labels for different fields & other info can be displayed with mostly any of the common HTML tags. The default looks of most tags varies a bit, but can be be changed with CSS when wanted.


<span>Character Name:</span>
<input type="text" name="attr_character_name" />
  • <h1> - <h5>: Good for section titles
  • <span><p>: Good for a block of text, doesn't have much formatting
  • <label>: Good for labelling input fields. Is by default bold font and leaves extra space under itself
  • <div>: Generally best tag for structuring the sheet. Contains no styling, can be used for text.

Sheet Rolls and Roll Buttons

You can include pre-defined rolls on your sheet. This is a great way to add the rolls that will be needed by the player when using the standard rolls in the game system.

For example, you may want to add a "Roll Check" button next to each skill on the sheet. To define a roll button, use the <button> tag. The type-attribute is set to "roll". The roll itself is defined in the value-attribute. You can also add a name attribute which allows the roll to be referenced in external Macros, Abilities or the Chat. The name needs to have the roll_-prefix to work.

Example of a "Bluff check" roll button:

<button type="roll" value="/roll 1d20 + @{Bluff}" name="roll_BluffCheck"></button>

Referencing attributes/fields on the sheet is done with the @{AttributeName} syntax. You could also then roll that example in other Macros or Abilities using %{BoB|BluffCheck}.

Read more via the community Button article.

Note: The names you give your roll buttons must be unique from any Ability or other roll button on your characters, if you want to reference them in Abilities or Macros. If a character sheet have several roll buttons with identical names but different values, calling the roll button name will prompt the last entry in the sheet's HTML.

See also:

Repeating Sections

Sometimes you may have a type of object where there may be one or more of them, and it's not known ahead of time how many there are. A good example of this is the Skills listing for a Character in Savage Worlds. Roll20's sheets allow you to define a template for each item in the section, and the player can then add as many of these in the listing as they need. To define a repeating section, use a <fieldset> tag. Add a class called "repeating_sectionname" to the tag, and inside the tag put the fields that each item will have.

Warning: Each section name should be unique, and you cannot use underscores in your sectionname. Do not use repeating_melee_weapon. Use repeating_melee, or repeating_meleeweapon.

Here's an example of a Skills listing:

h3>Skills</h3> <fieldset class="repeating_skills"> <select name="attr_dtype" class="dtype"> <option value="d4">d4</option> <option value="d6">d6</option> <option value="d8">d8</option> <option value="d10">d10</option> <option value="d12">d12</option> </select> <input type="text" name="attr_skillname" /> </fieldset>

When the sheet is displayed, Roll20 will automatically include an Add and Modify buttons to allow the player to add as many of each item as needed. Each item will have its own set of fields (in the example above, each has its own attr_dtype and attr_skillname).

Internally, each repeating item is stored in an attribute like so: repeating_skills_-ABC123_dtype or repeating_skills_$0_skillname. The ID (the -ABC123 part of the previous example) will never change for a repeating section row, so you can reference it in macros, abilities, and using the Mods (API). New rows that you add will be randomly assigned a new unique ID. Rows are currently ordered in the order in which they were created.

Note: All attributes in the repeating section should have a unique name globally. So if you have attr_Qty in your repeating section, don't have another field called attr_Qty outside of a repeating section or in another repeating section. Repeating sections are hard or impossible to create around a HTML table, and is recommended to be placed within a single cell.


Many sheet authors recommend using your own CSS for styling and to layout the sheet using CSS Flexbox and/or CSS Grid instead of the built-in column/rows option or HTML tables.

Roll20 provides a few basic classes you can use to organize things into a simple column-based layout. To suse them, just create a div with a class of '3colrow', '2colrow', or 'row'. Then inside of that div, create a div for each column with a class of 'col'. For example, to create a 3-column layout, you could do the following:

<div class='3colrow'>
  <div class='col'>
    <!-- Put the content for the first column here -->
  <div class='col'>
    <!-- Second column -->
  <div class='col'>
    <!-- Third column -->

 Read more via the community Designing Character Sheet Layout article.

CSS Styling

You can & should use custom CSS to style the way that your sheet looks to players. You can use nearly any CSS styling that you want, including background images, colors, font sizes, etc. There are just a few caveats to note:

  • All of your CSS styles will be restricted to the .charsheet parent class. So if you put a style called input, the system will automatically prefix that with .charsheet input. This shouldn't affect you in general, but it prevents you from changing any of the Roll20 application CSS outside of the character sheets.
  • Note that by default, any HTML classes defined in your HTML layout which don't begin with attr_, roll_ or repeating_ will be prefixed with sheet-. So for example, if you want to style some of your input tags to be shorter than others and you define the HTML as <input class='shortfield'>, when processing your layout it will be changed to <input class='sheet-shortfield'>.

Read more via the community CSS Wizardry article.

Google Fonts

Google Fonts can be called in your CSS using the @import-function:

@import url('');

You can then call the font from inside your CSS with the font-family-attribute:

font-family: 'Sigmar One';

For now, this is limited to Google Fonts, from

Read more about Google Fonts here.

Dark Mode Styling Details

  • Theme Switch
    When a user switches to dark mode, the virtual tabletop adds the specific CSS class .sheet-darkmode to the <body> element. When flipping the switch back to light, that class is removed.
  • Theme Change
    By adding color choices to the end of your sheets your sheet’s CSS, wrapped in a body.sheet-darkmode { } users will see the change when they flip the switch.

Advanced Sheet Options

Advanced options are not required for a basic character sheet but can enhance your sheet's capability and usability.

Default Sheet Settings

Selectable options can be specified in the sheet.json file provided with your Custom Character Sheet. These options provide default settings across all Characters when your Character Sheet is in use.

Read more at Default Sheet Settings.

Sheet Workers Scripts

Sheet Worker Scripts are an advanced feature of the Character Sheets system which allows the sheet author to specify JavaScript which will execute during certain events, such as whenever the values on a sheet are modified. It is highly recommended to use these in place of Auto-Calculating Fields whenever you have values that infrequently change, such as when a Character levels up or adds a new spell or attack.

Read more at Sheet Worker Scripts.

Roll Templates

Roll Templates allow you to fully customize how the rolls from your sheet appear in the chat window to all players. It's a great way to make the entire Roll20 experience match a common theme.

Read more at How to Make Roll Templates.

Compendium Integration

The Roll20 Compendium feature is a repository of information such as rules, spells, items, and monsters for select open-license gaming systems. By designating that your sheet is compatible with a Compendium, players will have direct access to that Compendium in the right sidebar during gameplay.

Read more via the main Compendium Integration article.


The Charactermancer is Roll20 system for guiding a user through a decision making process on the Virtual Tabletop. 

Community sheets should not include character creation or advancement due to potential copyright restrictions. 'By Roll20' sheets may include this content thanks to our partnerships with game creators. Sheets that are developed from the code of a 'By Roll20' sheet will need to ensure any character creation or advancement options code is removed. It's okay to have attributes that auto-calculate based on other attributes (including the current level). We'll let you know if your submitted sheet violates this rule.

However, the Charactermancer framework could also be used for other purposes, such as creating a character sheet importer framework.

Read more at Charactermancer Development.

Translating Character Sheets

Character sheets can be translated into other languages using the crowd-sourced translation service Crowdin. Character sheet authors have a number of controls over how the sheet is translated, and how the translation is displayed. Users willing to become translators should reach out through our web form.

Read more at Character Sheet Translation.

Roll20 Character Sheets Repository

The Roll20 GitHub repository is a collection of all the community-contributed character sheets that are available for use on Roll20.  It's intended purpose is to provide fans a way of creating system-specific support of games that Roll20 doesn't have an official character sheet for. Sourcecode of many official character sheets exists in the repository, but they are no longer updated. This is due to Roll20 have changed their workflow to keep their own sheets in a separate repository.

A number of older sheets(that doesn't show up in Roll20's sheet selection dropdown)also exist in the repository.

Patreon and Tipeee Linking Rules for Community Sheet Contributors

For sheet authors that are contributing to the Roll20 community character sheet database, they are approved to advertise via subscription/donation service sites: Patreon and Tipeee. Roll20 is not responsible for any payment transactions and cannot enforce any private arrangements.

In order to qualify, a sheet author must first have their sheet contribution approved by the Roll20 staff and included into the community character Sheet database.

You will want to include your Patreon or Tipeee account information in the sheet.json file that should be included with your sheet submission on GitHub.

The json file should have one of these fields added to it if you wish to advertise with Patreon or Tipeee:

patreon: Place the URL for a Patreon campaign here, and it will appear under your sheet's description when selected. (e.g."<name>")

tipeee: Place the URL for a Tipeee here, and it will appear under your sheet's description when selected. (e.g. "<name>")

For more information, see

Linking to Patreon/Tipeee on the Roll20 Forums

Linking to Patreon or Tipeee on the Roll20 Forums are only permitted for pre-approved community members who have contributed either Character Sheets or Mod (API) Scripts. If you wish to solicit users directly for funding you may do so privately, but no such links are permitted in a public forum without any contributed material.

Community Sheet Minimum Requirements and Best Practices

Roll20 and the community have put together a set of minimum requirements needed for sheet submission. Additionally, we have some included some general best practice guidelines to help increase consistency among sheet authors. This helps to make a clean and more maintainable code repository for the community.

Read more at Minimum Requirements & Best Practices.

See Also

Sheet Templates/Examples

Useful scripts

Was this article helpful?
31 out of 52 found this helpful