
I use a lot of HTML in chat messages to my players, and I'm looking for a better way to do it. I've tried three methods thus far, one of which works (but is cumbersome and time-consuming to use), and two others that don't. Working Method: Function Wrappers to apply inline styles to each HTML element This method works, but (A) it requires pumping a lot of code into each chat message, (B) every style has to be individually included in every HTML element, as there is no cascading possible, and (C) it's a real pain to code in a flexible manner. Step 1: Define a bunch of functions for each type of HTML element (e.g. "Block", "Title", "Header", "Body", etc.). Each function accepts a content parameter and an options object (for changing the default styles). Here's an example of the "HTML.Title()" function: const HTML = { Title : ( content , options = {}) => { // Overwrite the default styles with any passed-in options: options = Object . assign ({ height : "45px" , color : COLORS . brightred , margin : "0px" , fontFamily : "sexsmith" , fontSize : "32px" , lineHeight : "45px" , bgColor : "transparent" , border : "none" }, options ); // Then return the assembled HTML element, with inline styles and the content text: return `<span style=" display: block; margin: ${ options . margin }; font-weight: bold; color: ${ options . color }; background-color: ${ options . bgColor }; text-align: center; width: auto; font-family: ${ options . fontFamily }; font-size: ${ options . fontSize }; height: ${ options . height }; line-height: ${ options . lineHeight }; border: ${ options . border }; "> ${ content } </span>` . replace ( / \s+ / gu , " " ) } }; Step 2: Combine it with other element-wrapper functions to assemble and output a chat message: sendChat ( D . RandomString ( 3 ), "/w Storyteller " + C . HTML . Block ([ C . HTML . Title ( "Testing Inline Styles" , { color : C . COLORS . crimson} ), C . HTML . Header ( "I Know This Works" , { fontFamily : "Voltaire" } ), C . HTML . Body ( `... but it's a lot of code being posted to Chat each time: I have to manually style each element, without any cascading.` , { textAlign : "left" , fontFamily : "Voltaire" , fontSize : "14px" , lineHeight : "16px" } ) ] . join ( "" )) ); Result: ... which is great, but I'd much rather be able to make use of the cascading benefits of CSS classes. Plus, consider that every single HTML tag in there has a lengthy "styles=' ... '" value, which is a lot of text being spammed to chat (even though most of it is hidden): How I'm Trying to Improve The Working Method So, yes, the above works, and while I've explained my problems with it, I think the main functionality I want is to be able to take advantage of CSS's ability to cascade styles, and combine multiple styles. If I want a particular element to be a different font, color or alignment, I want to be able to to do it by simply adding a "font-voltaire" or a "color-red" class, and having it override the default class automatically according to standard CSS precedence rules, rather than having to configure and output the full inline style data for each element. Attempt #1: Add a <style> element with cascading styles on a per-message basis. Instead of inline styles applied to each element, I preempt the code block with a <style> element. A few things to know: the sandbox automatically prepends each style with "userscript-", to explain the discrepancy in class names I wrapped the entire thing in its own <div> element, just in case isolating the <style> element would help sendChat ( D . RandomString ( 3 ), "/w Storyteller " + `<div> <style> .userscript-Block { ... } .userscript-Title { display: block; font-weight: bold; color: ${ C . COLORS . mediumRed }; text-align: center; } .userscript-Header { ... } .userscript-Body { ... } </style> <div class="Block"> <div class="Title"> Testing &lt;style&gt; Tag Styles </div> <div class="Header"> Let's See If This Works </div> <div class="Body"> Hopefully it does! </div> </div> </div>` . replace ( / \s+ / gu , " " ) ); Result: No dice. Looking at the actual code in the developer console, Roll20 simply strips the <style> element and all of its styles completely. (Incidentally, if you're wondering about that "RandomString" bit, it's to ensure the "(From):" line is always there: If two chat messages are from the same person, the second one won't always include this line. This is important because I need these lines to be a consistent height, so I can hide them with a "margin-top: -35px;" setting on the top-level Block element (see the result in Method #1).) Attempt #2: Using styles in my Character Sheet's css file. I mean, it works for roll templates, so why not try to get it to work for chat commands sent via sendChat()? The following was added to the bottom of my character sheet css (along with styles for all of my other elements): .userscript-Title { display : block ; margin : 0 px ; font-weight : bold ; color : rgba ( 255 , 31 , 34 , 1 ); background-color : transparent ; text-align : center ; width : auto ; font-family : 'sexsmith' ; font-size : 32 px ; height : 45 px ; line-height : 45 px ; border : none ; } ... but, during processing, Roll20 adds ".charsheet" to the front of each one: ... and when I try to mimic this in the chat code, I'm instead calling on a "userscript-charsheet" style: I've tried to cheat this a few ways: Adding a comma in front of my .userscript declarations in the css merely results in ".charsheet, .charsheet-userscript-Title" in Roll20, and nothing else I've tried seems to work. Conclusion Thanks for getting this far; I wanted to be thorough in describing everything, so apologies for the length. If you have any ideas of things I might try (e.g. how to mimic the roll template behavior that does seem to bypass these issues, somehow, to apply styles from the character sheet's css to chat messages? or maybe using pseudoclasses and CSS selectors might help?), I would be very thankful!