Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
Advertisement Create a free account Compendium in Game, Join Today

Creating a progress bar/health bar on the Character Sheet

1597756915

Edited 1597765563
ᐰndreas J.
Forum Champion
Sheet Author
So, what's the available methods for creating a progress bar on Roll20 sheets? Like with many things, we are somewhat restricted in what we can do in Roll20, so HTML elements like <progress> and <meter>   doesn't seems to be supported by Roll20. In this list I'll display the various methods that could be used within Roll20 to create a Progress/Health bar, and I hope people comment with their own takes, and mentions any existing sheets that have implemented this subject well. I'll link this thread to the relevant CSS Wizardry section, and update my post if new methods or improvements are figured out. Methods for creating a progress bar on Roll20 Character sheets 1. CSS Wizardry Method - Custom Progress Bar There is the CSS Wizardry example Custom Progress Bar that can be used, which essentially styles a generic element like <div> to look a certain way depending on the value of an <input> inside of it. You can just show show the bar at different length depending on the value, or you can add some color variation depending on if it's high or low. Original Thread But this method seems to result in the max value & any threshold values to bee hardcoded to the css, and can't be made a variable with a _max attribute. < div class = "sheet-container" > < input type = "hidden" value = "2" name = "attr_Character_overweight" class = "sheet-hidden sheet-overweight" > < div class = "sheet-overweight" > < /div > < /div > div.sheet - overweight { width: 90 %; height: 20px; border: 1px solid black; color: black; text - align: center; } input.sheet - overweight[value = "0" ] ~ div.sheet - overweight { background: white; } input.sheet - overweight[value = "1" ] ~ div.sheet - overweight { background: linear - gradient (to left, white 60 %, green 75 %); } input.sheet - overweight[value = "2" ] ~ div.sheet - overweight { background: linear - gradient (to left, white 40 %, yellow 75 %); } input.sheet - overweight[value = "2" ] ~ div.sheet - overweight:before { content: "Bags half full" ; } input.sheet - overweight[value = "3" ] ~ div.sheet - overweight { background: linear - gradient (to left, white 20 %, orange 75 %); } input.sheet - overweight[value = "3" ] ~ div.sheet - overweight:before { content: "Bags nearly full" ; } input.sheet - overweight[value = "4" ] ~ div.sheet - overweight { background: linear - gradient (to left, white, red 100 %); } input.sheet - overweight[value = "4" ] ~ div.sheet - overweight:before { content: "Bags full !" ; } input.sheet - overweight[value = "5" ] ~ div.sheet - overweight { background: black; color: white; } input.sheet - overweight[value = "5" ] ~ div.sheet - overweight:before { content: "Bags too heavy !" ; } 2. CSS Wizardry Method - Modify "Fill Radio Buttons to the Left" There is the CSS Wizardry example Fill Radio Buttons to the Left , which uses either <input type["radio"]>   or a <button type"action">, plus a <span> element to display a row of radio buttons that are progressively filled out. The elements could be styled and placed close together to make it look like a progress bar instead of a row of dots. This method seems to me be more easily adjusted to accommodate a customizable _max value that selectively hides some elements to show the max length of the bar. (Gif, click to make it play) < div class = "dots" > < input type = "hidden" name = "attr_strength" class = "dot" value = "1" / > < button type = "action" name = "act_strength_1" class = "dot" > < span class = "checked" > < /span > < /button > < button type = "action" name = "act_strength_2" class = "dot gt-1" > < span class = "checked" > < /span > < /button > < button type = "action" name = "act_strength_3" class = "dot gt-1 gt-2" > < span class = "checked" > < /span > < /button > < button type = "action" name = "act_strength_4" class = "dot gt-1 gt-2 gt-3" > < span class = "checked" > < /span > < /button > < button type = "action" name = "act_strength_5" class = "dot gt-1 gt-2 gt-3 gt-4" > < span class = "checked" > < /span > < /button > < /div > < script type = "text/worker" > const strengthValues = [ "1" ," 2 "," 3 "," 4 "," 5 "]; strengthValues. forEach ( function (value) { on (`clicked:strength_${value}`, function () { setAttrs ({ "strength" : value }); }); }); < /script > .sheet-dots{ display:flex; } /* Configure the button styling. This example makes it look like a radio. */ button.sheet - dot { padding: 0 ; border: solid 1px #a8a8a8; cursor: pointer; width: 14px; height: 14px; border - radius: 50 %; display: flex; justify - content: center; align - items: center; } button.sheet - dot > span { width: 6px; height: 6px; border - radius: 50 %; background: buttontext; } /* Hide the "checked" section of the radio if the hidden attribute value is greater than the button value */ input.sheet - dot[value = "1" ] ~ button.sheet - gt - 1 > span.sheet - checked { display: none; } input.sheet - dot[value = "2" ] ~ button.sheet - gt - 2 > span.sheet - checked { display: none; } input.sheet - dot[value = "3" ] ~ button.sheet - gt - 3 > span.sheet - checked { display: none; } input.sheet - dot[value = "4" ] ~ button.sheet - gt - 4 > span.sheet - checked { display: none; } 3. Using <input type="range"> <input type="range">   looks like a volume slider, but it might be possible to style it heavily with CSS to instead look like a progress bar. It is confirmed to work in Roll20, and adjusting it's positing seems best achieved by have another input keyed to the same attribute. More info: Styling Range Inputs with CSS Stackoverflow: style beofre/after thumb with different colors In this example I've hidden the slider button, and color-coded the slider before and after the slider button with different colors to tell them apart. I then use the duplicate input to set the hp to a value within the range(0-10 in this example). (GIF: click to make it play) <div class="health-bar"> <span>HP:</span> <input name="attr_hp" class="rangetest" type="range" min="0" max="10" value="10"> <input name="attr_hp" class="rangetest" type="number" value="10"> </div> input[type="range"].sheet-rangetest{ width: 100px; } /* works only on firefox atm */ input[type="range"].sheet-rangetest::-moz-range-thumb{ background: transparent; border-color: transparent; color: transparent; } input[type="range"].sheet-rangetest::-moz-range-progress{ background: green; height: 10px; } input[type="range"].sheet-rangetest::-moz-range-track{ background: red; height: 10px; } Methods that doesn't work: <progress> & <meter> elements I've tried both, and neither seems to be supported by Roll20, which is too bad as they are elements that are made for this kind of thing. The <progress> and <meter> elements would be perfect for this, and if Roll20 creates a method for dynamically adjusting the min and max value limits of <input> and these new elements, like optionally keying them to  attributes with _min and _max in their name. It would enable nice progress bars on the sheet & enhance existing elements if you can now adjust the min/max for attribute fields. <meter> does have a few fun things like low and high thresholds, that adjusts the color of the bar. If roll20 would enable adjusting the min and max values with my suggested method, it could probably be easily extended to something like _low and _high Something like this would be great: <label>HP:</label> <meter min="0" max="100" low="33" high="66" optimum="100" value="50" name="attr_hp"> </meter> <input type="hidden" min="0" max="100" value="50" name="attr_hp"> <input type="hidden" value="0" name="attr_hp_min"> <input type="hidden" value="100" name="attr_hp_max"> <input type="hidden" value="33" name="attr_hp_low"> <input type="hidden" value="66" name="attr_hp_high"> Existing Sheets using Progress bars Here we list the sheets with the best existing progress bar implementations. Looking at them might give us hints on how to make a better versions in the future. (I don't know any examples yet)
1597774264
Vince
Pro
Sheet Author
Nothing to add...(replying to add to my history)  ;-) Thanks for posting this Andreas.
1597774977
GiGs
Pro
Sheet Author
API Scripter
Great post. I dont have anything to add, just wanted to say its a great idea for a post. The range one is new to me, I'll have to tinker with that.
1597775965
ᐰndreas J.
Forum Champion
Sheet Author
GiGs said: Great post. I dont have anything to add, just wanted to say its a great idea for a post. The range one is new to me, I'll have to tinker with that. Yeah this is interesting. Scott pointed out to me that instead of directly linking a stat to the range input, one should use a percentage attribute instead, and have a sheetworker update the percentage value based on the actual stat's value and max value. That way we get around the not min max tags in the element that we otherwise couldn't change. This could also be used to show how much xp is left to the next level, and with some smart CSS, we could alter the bars color depending on how much you have left, like making the bar red when you're close to zero.
1597798448
Richard T.
Pro
Marketplace Creator
Sheet Author
Huh, CSS classes based on values of inputs sounds a lot of fun, particularly for systems with paper doll health/wounds. Looking forward to having this added to my toolbelt, thanks Andreas and everyone else. 
1602320374
Dave
Pro
I'm looking at Method #3. So, it's not possible to have a "max" value determined by calculation or user input? I've tried live calculating fields and sheet workers, but the bar's "max" field doesn't seem to work unless I just use a raw number. This is what I'm trying to do: <input name="attr_hp" class="rangetest" type="range" min="0" max="@{hpmax}" value="@{hpset}" disabled> hpmax is setting successfully via sheetworker, but the bar does not fill when I use that attribute for max="..." Any thoughts?
1602321668
ᐰndreas J.
Forum Champion
Sheet Author
Dave said: I'm looking at Method #3. So, it's not possible to have a "max" value determined by calculation or user input? I've tried live calculating fields and sheet workers, but the bar's "max" field doesn't seem to work unless I just use a raw number. Someone pointed out to me that this would probably be best achieved by having the range input just having a min/max range of 0/100, and then have a separate stat that tracks the current/max hp, which makes it possible for a sheetworker to set the value of the range input as a percentage of the max health. Please share your example if you manage to figure it out.