Hi Leo, The Starfinder sheet does this for buff/penalty display. I'll give some modified example excerpts below: HTML <input class='base-attr attr' type='number' title='@{strength}' name='attr_strength_base' value='10' >
<input class='mod-buff' type='hidden' name='attr_strength_change' value='0'> <!-- This is the driver of the change, it's important that this be type="hidden". This attribute is set to -1, 0, or 1 depending on whether the total strength is buffed (greater than strength_base), penalized (less than strength_base), or unaffected (equals strength_base)-->
<span class='modified-attr attr input-field' readonly='true' type='number' title='@{strength}' name='attr_strength' value='10'>10</span> <!-- This has to be a span as not all browsers support the use of the :after and :before pseudoelements on inputs (e.g. chrome does, but firefox doesn't) --> CSS .sheet-mod-buff[value*="1"] ~ .sheet-modified-attr {/*if an mod-buff class entity has a value of 1, change how the modified-attr class entity(ies) following it are displayed*/
color:#2dafeb;
font-weight:900 !important;
text-shadow:none;
font-family:Contrail One;
}
.sheet-mod-buff[value*="1"] ~ .sheet-modified-attr:after{/*as above, but adds some decoration to the modified-attr using the :after pseudoelement*/
font-family:Pictos;
content:'{';
position:absolute;
}
/*The two entries below are the same as above, but for penalties*/
.sheet-mod-buff[value*="-1"] ~ .sheet-modified-attr {
color:#fa893a;
font-weight:900 !important;
text-shadow:none;
font-family:Contrail One;
}
.sheet-mod-buff[value*="-1"] ~ .sheet-modified-attr:after{
font-family:Pictos;
content:'{';
position:absolute;
transform:rotate(180deg);
transform-origin:center 45%;
} So, now we've got our html and css pattern setup, now we just need to decide what to set the strength_change attribute to. We'll need to use sheetworkers (aka javascript) for this: JS <script type='text/worker'>//You should only have a single text/worker script section. Multiple of them will crash. You can however put multiple functions/scripts in a single text/worker entity
on('change:strength_base',(event)=>{//When the user changes strength_base, do something
const setObj = {};//initializing the object we'll be storing all the attribute values in.
getAttrs(['strength_base','strength_buff','strength_penalty'],(obj)=>{//get the current values of the listed attributes. Returns as an object (aka {strength_base:14,strength_buff:2,strength_penalty:-1})
setObj.strength = (obj.strength_base*1||0)+(obj.strength_buff*1||0)-(obj.strength_penalty*1||0);//Set the strength to be equal to the base value +/- the buffs/penalties
if(setObj.strength > (obj.strength_base*1||0)){//if strength is higher than the base, it's buffed and strength_change should be set to 1
setObj.strength_change = 1;
}else if(setObj.strength <(obj.strength_base*1||0)){//if strength is higher than the base, it's penalized and strength_change should be set to -1
setObj.strength_change = -1;
}else{//Otherwise, set strength_change to 0 as strength_base and strength are equal
setObj.strength_change = 0;
}
setAttrs(setObj,{silent:true});//Set the attributes. This is done asynchronously. The {silent:true} is an optional argument that means these changes won't trigger further sheetworkers. Cascading sheetworkers are generally a bad idea.
});
});
</script> And there you have it. The above is a simplified version of what the starfinder sheet does, but should be much easier to follow since it's not spread over more than 10k lines of code. EDIT: Realized i was still using the ~ selector. That's a hold over from when I used hidden radio buttons for the _change attribute. With the type='hidden' attribute instead, you could switch to using the + selector. EDIT the 2nd: And of course if you aren't adding text decoration, then you don't need the modified attribute to be a span. If you are planning on releasing the sheet to the public though, I would encourage text decoration as it helps with accessibility so that color-blind users can differentiate between the buffed (green) and penalized (red) states. Since there are a wide range of color blindness disorders, this is easier than trying to find a color combination that no one is blind to.