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 .
×
Create a free account

Styling Checkboxes - I'm going crazy

1604601661
Yui V.
Pro
Sheet Author
Hello, I'm styling checkboxes for a character sheet, instead of a classic checkbox, I want a big red one. I used the old pure html+css solution for this case because I need other unstyled checkboxes on the sheet to pair with them (same attr_name). Here's my code: html: <td class='sheet-carton'> <input type='checkbox' class="sheet-carton-jaune" name='attr_puissance1' value='-10[Carton jaune]' /><span></span> <input type='checkbox' class="sheet-carton-rouge" name='attr_puissance2' value='-10[Carton rouge]' /><span></span> </td> css: /* Fake checkbox carton jaune */ input[type="checkbox"].sheet-carton-jaune {     opacity: 0;     width: 16px;     height: 16px;     cursor: pointer;     z-index: 1; } input[type="checkbox"].sheet-carton-jaune + span::before {     margin-left: -16px;     margin-right: 4px;     line-height: 12px;     text-align: center;     display: inline-block;     vertical-align: middle;          content: " ";     color: #f4df42;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #f4df42;     width: 10px;     height: 10px;     font-size: 12px; } input[type="checkbox"]:checked.sheet-carton-jaune + span::before {     content: "✔";     position: relative;     top: -1px; } /* Fake checkbox carton rouge */ input[type="checkbox"].sheet-carton-rouge {     opacity: 0;     width: 16px;     height: 16px;     cursor: pointer;     z-index: 1; } input[type="checkbox"].sheet-carton-rouge + span::before {     margin-left: -16px;     margin-right: 4px;     line-height: 14px;     text-align: center;     display: inline-block;     vertical-align: middle;          content: " ";     color: #b74437;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #b74437;     width: 10px;     height: 10px;     font-size: 12px; } input[type="checkbox"]:checked.sheet-carton-rouge + span::before {     content: "✔";     position: relative;     top: -1px; } They'll both be on the same line. The problem I encounter is that when the boxes are unchecked, all's right, I can check them, but when they're checked, I can't access the invisible checkbox anymore... Does anyone have an idea of what might be causing this problem? Thank you.
1604601749
Yui V.
Pro
Sheet Author
Both checkboxes are styled the same, except for color, btw.
1604601976
Kraynic
Pro
Sheet Author
What happens if you make the class in the html simply: class="carton-jaune" The sandbox that the sheet is running in will automatically add sheet to the beginning, so you need the full .sheet-carton-jaune in the css.  Just remove the "sheet-" part of your class labels in the html and see if that works for you.
1604602350
Yui V.
Pro
Sheet Author
It doesn't change anything. The issue is somewhere else...
1604605555
Andreas J.
Forum Champion
Sheet Author
Translator
maybe this input[type="checkbox"]:checked.sheet-carton-jaune + span::before {     content: "✔";     position: relative;     top: -1px; } should be: input[type="checkbox"] .sheet-carton-jaune:checked + span::before {     content: "✔";     position: relative;     top: -1px; }
1604607727

Edited 1604607821
GiGs
Pro
Sheet Author
API Scripter
I dont think anyone has gotten the pure CSS example from CSS Wizardry page to work. I know I never did. The reason the sheet worker version exists on that page is because someone was struggling like you to get the pure CSS version worked, and while others were offering suggestions, I pointed out that the code on the wiki doesnt work and started a conversation where people started testing it. No-one could get it working, and IIRC Cassie posted the sheet worker version which does work. I think the only reason the pure CSS version still exists on the wiki is that it was posted by a CSS genius named Brain, long long ago, and if he posted it, there must be a way to get it working. But no-one active on the forums now has been able to get it working. (Maybe me posting this will prompt someone to get it working - if so I can later claim credit for that!) So, I recommend using the sheet worker version. This will get you close, but you'll have to tweak the CSS for styling a bit probably. I've tested that the basic mechanics (clicking and unclicking the checkbox) does work. I used a div as container, but you should be able to use a td. HTML: <div class="carton">     <input type="hidden" class="carton-jaune" name="attr_jaune_flag" />     <button type="action" name="act_jaune" class="carton-jaune">       <span class="checked">✔</span>     </button>     <input type="hidden" class="carton-rouge" name="attr_rouge_flag" />     <button type="action" name="act_rouge" class="carton-rouge">       <span class="checked">✔</span>     </button> </div> Sheet Worker const toggleList = ["jaune", "rouge"];     toggleList.forEach(function(button) {     on(`clicked:${button}`, function() {       const flag = `${button}_flag`;       // Check the current value of the hidden flag.       getAttrs([flag], function(v) {         // Update the value of the hidden flag to "1" for checked or "0" for unchecked.         setAttrs({           [flag]: v[flag] !== "1" ? "1" : "0"         });       });     });   }); CSS .sheet-carton {     display: inline-flex;     align-items: center;   }   button.sheet-carton-jaune,   button.sheet-carton-rouge {     padding: 0;     border: solid 1px #a8a8a8;     cursor: pointer;        width: 12px;     height: 12px;     border-radius: 3px;     display: flex;     justify-content: center;     align-items: center;        font-size: 12px;   }      /* Hide the "checked" section of the toggle if the attribute value is not "1". */   input.sheet-carton-jaune:not([value="1"]) ~ button.sheet-carton-jaune > span.sheet-checked,   input.sheet-carton-rouge:not([value="1"]) ~ button.sheet-carton-rouge > span.sheet-checked {     display: none;   }   button.sheet-carton-jaune,   button.sheet-carton-jaune > span.sheet-checked {      color: #f4df42;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #f4df42;   }   button.sheet-carton-rouge,   button.sheet-carton-rouge > span.sheet-checked {      color: #b74437;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #b74437;   }
1604607994
GiGs
Pro
Sheet Author
API Scripter
Note: the sheet worker version did have a small error (referring to a class by name of sheet-radios, when it should have been sheet-toggle-container). The checkbox code still worked, but the aligning of multiple checkboxes wouldn't, so I just corrected that.
1604611006
Yui V.
Pro
Sheet Author
Thanks for replying. It sucks for the pure css+html... Regarding it, I had this version of the coded that actually worked, but I couldn't align it right: in this form, the invisible checkboxes are shifted aprox 5-8px to the left, so they work perfectly, but you need to click on the left part of the fake box to do it. What made me crazy was spending over a hour trying to shift the invisible checkboxes to the right via margin and relative position... I couldn't do it in the end. /* Fake checkbox carton jaune */ input[type="checkbox"].sheet-carton-jaune {     opacity: 0;     width: 16px;     height: 16px;     position: relative;     margin: -10px;     cursor: pointer;     z-index: 1; } input[type="checkbox"].sheet-carton-jaune + span::before {     margin-right: 4px;     line-height: 12px;     text-align: center;     display: inline-block;     vertical-align: middle;          content: " ";     color: #f4df42;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #f4df42;     width: 10px;     height: 10px;     font-size: 12px; } input[type="checkbox"]:checked.sheet-carton-jaune + span::before {     content: "✔";     position: relative;     top: -1px; } /* Fake checkbox carton rouge */ input[type="checkbox"].sheet-carton-rouge {     opacity: 0;     width: 16px;     height: 16px;     position: relative;     margin: -10px;     cursor: pointer;     z-index: 1; } input[type="checkbox"].sheet-carton-rouge + span::before {     margin-right: 4px;     line-height: 14px;     text-align: center;     display: inline-block;     vertical-align: middle;          content: " ";     color: #b74437;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #b74437;     width: 10px;     height: 10px;     font-size: 12px; } input[type="checkbox"]:checked.sheet-carton-rouge + span::before {     content: "✔";     position: relative;     top: -1px; } Now, your script... I'm trying to wrap my head around it (I was in the middle of re-watching Ghost in the Shell SAC the eleven individual right now so my head's not quite here). If I think this straight, since I need my other noraml pair of checkboxes to trigger the stylised ones too (by sharing attribute name essentially), with the script, I'd have to trigger the script both with on:click  for the button and on:change  for the outsider cboxes, then read their values, set a hidden input to something that triggers the display:none  of the content as well as set another hidden input form 0 to "-10[carton Jaune/Rouge]"(this part is parsed into a roll). So the outsider cbs would trigger the action button style change, but I'd need a way to check/uncheck the outsider cbs by clicking the buttons too... Is that possible? I think I remember failing to check/uncheck a checkbox with a script before. Or do I just need to change a hidden input that will check/uncheck the cb with the same attribute name? ...
1604611407
Yui V.
Pro
Sheet Author
ᐰndreas J. said: maybe this input[type="checkbox"]:checked.sheet-carton-jaune + span::before {     content: "✔";     position: relative;     top: -1px; } should be: input[type="checkbox"] .sheet-carton-jaune:checked + span::before {     content: "✔";     position: relative;     top: -1px; } This does not affect the issue, sadly
1604613473
Andreas J.
Forum Champion
Sheet Author
Translator
GiGs said: I dont think anyone has gotten the pure CSS example from CSS Wizardry page to work. I know I never did. Long ago I got it to work on my Weaverdice sheet, but now testing the sheet it seems to be broken, so I'd say the trick got permanently broken at some point during the last year, by either a browser update, or an update by Roll20. Ugh, now I need to update that one...
1604619149

Edited 1604619586
Yui V.
Pro
Sheet Author
Hey, I think I solved it!! I've worked more on the second version I posted, nitpicking margins, and managed to do it right with the pure html+css! /* Fake checkbox carton jaune */ input[type="checkbox"].sheet-carton-jaune {     opacity: 0;     width: 16px;     height: 16px;     position: relative;     cursor: pointer;     z-index: 1; } input[type="checkbox"].sheet-carton-jaune + span::before {     margin-left: -16px;     margin-right: 4px;     line-height: 12px;     text-align: center;     display: inline-block;     vertical-align: middle;          content: " ";     color: #f4df42;     background-color: rgba(255, 255, 255, 0.4);     border: solid 4px #f4df42;     width: 10px;     height: 10px;     font-size: 10px;     font-weight:bold; } input[type="checkbox"]:checked.sheet-carton-jaune + span::before {     content: "✔";     position: relative; } /* Fake checkbox carton rouge */ input[type="checkbox"].sheet-carton-rouge { opacity: 0; width: 16px; height: 16px; margin-right: -16px; cursor: pointer; z-index: 1; } input[type="checkbox"].sheet-carton-rouge + span::before { margin-right: 4px; line-height: 14px; text-align: center; display: inline-block; vertical-align: middle; content: " "; color: #b74437; background-color: rgba(255, 255, 255, 0.4); border: solid 4px #b74437; width: 10px; height: 10px; font-size: 10px; font-weight:bold; } input[type="checkbox"]:checked.sheet-carton-rouge + span::before { content: "✔"; } First, the problem of this (second) version was that the true CBs (checkboxes) were shifted left from the fake ones. Having the '' margin-left: '' attribute of the second box set(carton-rouge) at -16px, 16px being the width of the true CBs, did correct the shift, but as the <td> the CBs are in is  text-align: center 'd, doing the same to the first box set (carton-jaune) would misalign both boxes from the table cell's center, so I moved the  margin-left:  attribute of the first box set, carton-jaune, to the jaune fake box, and all is centered, while the invisible CBs cover all of the fake boxes. Secondly, the problem I encountered when fiddling with the first version I presented here was caused by a  position: relative;  combination. The issue was that after checking the fakebox, I couldn't access the invisible checkbox anymore to uncheck it. To solve this problem, the true check box ( .sheet-carton-X , the first css entry) needs to have the same position as the checked fakebox ( :checked.sheet-carton-X +span::before , the last entry) if the latter has one. So, here, with ' position: relative; ': .sheet-carton { [no position] } :checked.sheet-carton +span::before {position: relative;} ^Does not work, While: {pos: rel.} {pos: rel.} as well as {pos: rel.} { [no position] } as well as { [no position] } { [no position] } ^All work (I've tested it). The reason there was a  position: relative;  in the last  :checked  entries was that I wanted the  content: "✔";  to go up by 1px, hence the   top: -1px  that was there, but obviously, it affects the container, not the content, so it was an error and I removed it. As you can see on the complete code in this post, the carton-jaune fakebox uses the 2 pos:rel combo, while the carton-rouge fakebox uses the 0 pos:rel combo as an example. Both do work, although keeping position attributes here makes no sense, so the 0 combo is what you (and I) need to go with. Thank you for thinking about all this with me. I didn't try out the script version GiGs suggested in the end, I'm sorry (I'm too dumb right now to risk wrestling sheetworkers).
1604664119

Edited 1604664271
GiGs
Pro
Sheet Author
API Scripter
Well done! I went through and optimised the code a little bit, and noticed an improvement that could be made. You can combine the code different classes - where the code is the same, just separate classes by commas, like below. /* Fake checkbox cartons */ input [ type = "checkbox" ] .sheet-carton-jaune , input [ type = "checkbox" ] .sheet-carton-rouge {      opacity :  0 ;      width :  16px ;      height :  16px ;      position :  relative ;       cursor :  pointer ;      z-index :  1 ; margin-right :  -16px ; } /* the SPANs */ input [ type = "checkbox" ] .sheet-carton-jaune  +  span::before , input [ type = "checkbox" ] .sheet-carton-rouge  +  span::before {      margin-right :  4px ;      text-align :  center ;      display :  inline-block ;      vertical-align :  middle ;      content :  " " ;      width :  10px ;      height :  10px ;      font-size :  10px ;      font-weight : bold ; } input [ type = "checkbox" ] .sheet-carton-jaune  +  span::before {      line-height :  12px ;               color :  #f4df42 ;      background-color :  rgba ( 255 ,  255 ,  255 ,  0.4 );      border :  solid   4px   #f4df42 ; } input [ type = "checkbox" ] .sheet-carton-rouge  +  span::before {      line-height :  14px ;           color :  #b74437 ;      background-color :  rgba ( 255 ,  255 ,  255 ,  0.4 );      border :  solid   4px   #b74437 ;      } /* the CHECKED SPANs */ input [ type = "checkbox" ] :checked.sheet-carton-jaune  +  span::before , input [ type = "checkbox" ] :checked.sheet-carton-rouge  +  span::before {      content :  "✔" ; } Doing this, I was able to look at what was different between the jaune and rouge checkboxes, and noticed the way you'd used the relative positioning on both was different, and can be made the same. (I didnt understand your description about thisbut now I do, and you can remove the position:relative  line, and it still works.) I was also able to see you'd applied the margins differently on jaune and rouge, and they can be treated the same too. That leaves just the line-height different between jaune and rouge, and I suspect that's just an oversight and they should be the same. So try this and see if it works for you.
1604669549
Yui V.
Pro
Sheet Author
Oh, you're right. Indeed, the line-height was unintentionnal, so I just moved it to the common fake-style now (leaving the jaune and rouge specific entries with just color attrbutes). Also, yes, the jaune box had position:relative attributes, while the rouge didn't, that was intentionnal, to show both worked, on the final version I had none at all. On this condensed version, even the position:relative that remains in the true checkbox isn't even needed actually. What I was scared of were the margins, I thought unifying them would cause misalignment issues, but actually, they don't! that's great! I'll use this 'condensed' version, with the afore mentioned mods, thank you for pointing it out! Thank you!
1604669980
GiGs
Pro
Sheet Author
API Scripter
Yay :)
1604699450
Richard T.
Pro
Marketplace Creator
Sheet Author
Compendium Curator
I'm mostly transitioning to label wrapped inputs for everything, it just takes out so much headache having a container that automatically makes everything inside itself a click-event. 
1604721890

Edited 1604722489
Tetrakern
Sheet Author
Compendium Curator
... here is a better working pure HTML/CSS version. I only did this quick, so you may want to change the style as needed. While hiding the default browser checkbox is one way to go about it, what I recommend is appearance: none  to reset the default browser style. This works on anything, by the way. Allows you to keep using the element, making the sibling spans obsolete. This is NOT genius level and should never be done with JavaScript, seriously. I also want to stress that the example on the CSS Wizardry page is... not good. input[type="checkbox"] { appearance: none; border: none; outline: none; } input[type="checkbox"]::after { content: ''; box-sizing: border-box; display: flex; align-items: center; justify-content: center; background-color: rgba(255, 255, 255, 0.4); color: #f4df42; font-size: 10px; font-weight: bold; line-height: 1; border: solid 4px #f4df42; width: 20px; height: 20px; } input[type="checkbox"]:checked::after { content: "✔"; } input[type="checkbox"].sheet-carton-rouge::after { color: #b74437; border-color: #b74437; }
1604737367

Edited 1604737500
GiGs
Pro
Sheet Author
API Scripter
That's great! I know I'm excited to have a much simpler example code for things like this. A lot of the older CSS Wizardry examples are really not great code (as demonstrated by how hard it is to get them working sometimes), but Brian, the guy I referred to earlier, was responsible for uncovering and discovering a lot of tricks and techniques that have become standard on roll20 - for sheet layout at least. Remember people were forced to think out of the box because of how roll20 limits what we can do. Here's a version of the above code that wont mess up all other checkboxes in the sheet (just added the missing style back in): input[type="checkbox"].sheet-carton-jaune, input[type="checkbox"].sheet-carton-rouge {     appearance: none;     border: none;     outline: none; } input[type="checkbox"].sheet-carton-jaune::after, input[type="checkbox"].sheet-carton-rouge::after {     content: '';     box-sizing: border-box;     display: flex;     align-items: center;     justify-content: center;     background-color: rgba(255, 255, 255, 0.4);     font-size: 10px;     font-weight: bold;     line-height: 1;     width: 20px;     height: 20px; } input[type="checkbox"].sheet-carton-rouge:checked::after, input[type="checkbox"].sheet-carton-jaune:checked::after {     content: "✔"; } input[type="checkbox"].sheet-carton-jaune::after {     color: #f4df42;     border: solid 4px #f4df42; } input[type="checkbox"].sheet-carton-rouge::after {     color: #b74437;     border: solid 4px #b74437; }
1604738354

Edited 1604738394
GiGs
Pro
Sheet Author
API Scripter
Here's a version of your code stripped down to what seem to me to be the essentials. I'd like to post it to the wiki as a better example. Is there anything missing or incorrect here? /* hide the checkbox and remove styling */ input [ type = "checkbox" ] .sheet-custom-checkbox  {      appearance :  none ;      border :  none ;      outline :  none ; } input [ type = "checkbox" ] .sheet-custom-checkbox::after  {      /* remove the standard checkmark, since we are replacing it below. */      content :  '' ;      /* set the layout so the new checkmark is positioned in the checkbox properly. */      display :  flex ;      align-items :  center ;      justify-content :  center ;      /* need to make the checkbox visible again, at the size you need it */      border :  solid   1px   black ;       width :  16px ;      height :  16px ;      /* might want to add extra styling, like background-color, font weight, border, etc.       anything after this point is entirely optional. */      border-radius :  3px ; } input [ type = "checkbox" ] .sheet-custom-checkbox:checked::after  { /* set the new checkmark. */      content :  "✔" ; }
1604749786

Edited 1604750070
Tetrakern
Sheet Author
Compendium Curator
Looks fine. The default checkbox is not so much hidden as turned into a regular container and the empty content just does not set a checkmark as there is nothing to remove (and pseudo-elements are not displayed without the property), but that's semantics. Edit: You could also do without the pseudo-element and just style the original checkbox, though that would not allow you to add a custom checkmark as that relies on the content property. But if you want to go for a simple color filled box or something that would do.
1604749877

Edited 1604749936
GiGs
Pro
Sheet Author
API Scripter
Thanks, that explanation helps me understand what is going on there. CSS is not my forte! :) I hadnt really grasped that the checkbox is a container, and treating it as a flex object had been puzzling me. But that clears that up.
1604750204
Tetrakern
Sheet Author
Compendium Curator
Well, it's rendered like a regular container. It still retains its functional properties. And flex is your friend whenever you need to position something to avoid position hacks.