Closed cpsievert closed 1 year ago
These styles are making the checkboxes too close to the checkbox group label
/* For checkbox groups and radio buttons, bring the options closer to label,
if label is present. */
.shiny-input-checkboxgroup label ~ .shiny-options-group,
.shiny-input-radiogroup label ~ .shiny-options-group {
margin-top: -10px;
}
/* Checkbox groups and radios that are inline need less negative margin to
separate from label. */
.shiny-input-checkboxgroup.shiny-input-container-inline label ~ .shiny-options-group,
.shiny-input-radiogroup.shiny-input-container-inline label ~ .shiny-options-group {
margin-top: -1px;
}
They were added back when migrating to Bootstrap 3
They also interact with these rules
where $form-check-input-selector
is set over here
In short: the negative margin-top
adjusts the placement of the checkbox to be in line with the text label. Without that margin-top
adjustment, the check boxes would be correctly spaced, but out of line with their labels.
The above is actually for BS5. BS4 takes a different path in both Bootstrap and bslib. These lines in Bootstrap set the margin
and then bslib extends the .form-check-input
class for BS4.
To set the correct negative margin for all versions of Bootstrap in a themeable way, we need to undo both the margin-top
adjustment and also take into account the top border width of the checkbox/radio input. The border width is driven by $input-border-width
in BS4 and $input-btn-border-width
in BS5
After much investigation, I think most of the issues described in this thread are the result of the markup choices for checkbox and radio groups.
Where we use
<div id="checkbox2" class="form-group shiny-input-checkboxgroup shiny-input-container shiny-bound-input" role="group" aria-labelledby="checkbox2-label">
<label class="control-label" id="checkbox2-label" for="checkbox2">Check this out</label>
<div class="shiny-options-group">
<div class="checkbox">
<label>
<input type="checkbox" name="checkbox2" value="aenean">
<span>aenean</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="checkbox2" value="magna nullam sem">
<span>magna nullam sem</span>
</label>
</div>
</div>
</div>
in Bootstrap 5 (at least), the preferred markup is closer to the following where the primary difference is using <fieldset><legend></legend><!-- radio groups --></fieldset>
(note: the following example is for styling purpose and doesn't include all required id/aria attributes)
<fieldset>
<legend class="col-form-label">Check this out</legend>
<div class="shiny-option-group">
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="checkbox2" value="aenean">
<span>aenean</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="checkbox2" value="magna nullam sem">
<span>magna nullam sem</span>
</label>
</div>
</div>
</fieldset>
The biggest advantage of using the above markup is that inline radio and check groups are super easy and do everything you'd expect (wrapping inputs, indented wrapped lines in labels, etc.):
.shiny-input-container-inline .shiny-option-group {
display: flex;
gap: 1rem;
flex-wrap: wrap;
flex-direction: row;
}
For now I've worked on fixing behavior in bslib for Bootstrap 4 and 5 and specifically styling the Shiny preset in the way I'd like to see all inline check/radio groups styled. Without changing the markup, we're swimming against Bootstrap styles with hacks like the negative margin-top
in shiny's css, and the cleanest way to ensure consistent behavior across all Bootswatch themes would be to use the <fieldset>
markup.
Thanks @gadenbuie. Would you mind creating a new issue with that last comment and use it as an argument for bslib to gain a input_checkbox()
, etc. (that or have Shiny change it's markup)?
This issue has been automatically locked. If you have found a related problem, please open a new issue (with a reproducible example or feature request) and link to this issue. :raising_hand: Need help? Connect with us on Discord or Posit Community.
inline = TRUE