Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Fixes #23449) Normalize Custom Checkbox and Radio with Form Check #23503

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 84 additions & 61 deletions docs/4.0/components/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,11 +545,13 @@ And of course [custom form controls](#custom-forms) are supported.
</select>
</div>
<div class="col-auto">
<label class="custom-control custom-checkbox mb-2 mr-sm-2">
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Remember my preference</span>
</label>
<div class="custom-control custom-checkbox mb-2 mr-sm-2">
<label>
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Remember my preference</span>
</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2">Submit</button>
Expand Down Expand Up @@ -601,11 +603,13 @@ Custom form controls and selects are also supported.
<option value="3">Three</option>
</select>

<label class="custom-control custom-checkbox mb-2 mr-sm-2">
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Remember my preference</span>
</label>
<div class="custom-control custom-checkbox mb-2 mr-sm-2">
<label>
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Remember my preference</span>
</label>
</div>

<button type="submit" class="btn btn-primary mb-2">Submit</button>
</form>
Expand Down Expand Up @@ -876,25 +880,31 @@ Our example forms show native textual `<input>`s above, but form validation styl

{% example html %}
<form class="was-validated">
<label class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" required>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>

<div class="custom-controls-stacked d-block my-3">
<label class="custom-control custom-radio">
<input id="radioStacked1" name="radio-stacked" type="radio" class="custom-control-input" required>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
<label class="custom-control custom-radio">
<input id="radioStacked2" name="radio-stacked" type="radio" class="custom-control-input" required>
<div class="custom-control custom-checkbox">
<label>
<input type="checkbox" class="custom-control-input" required>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Or toggle this other custom radio</span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>
</div>

<div class="my-3">
<div class="custom-control custom-radio">
<label>
<input id="radioStacked1" name="radio-stacked" type="radio" class="custom-control-input" required>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
</div>
<div class="custom-control custom-radio">
<label>
<input id="radioStacked2" name="radio-stacked" type="radio" class="custom-control-input" required>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Or toggle this other custom radio</span>
</label>
</div>
</div>

<select class="custom-select d-block my-3" required>
<option value="">Open this select menu</option>
<option value="1">One</option>
Expand Down Expand Up @@ -930,21 +940,25 @@ In the checked states, we use **base64 embedded SVG icons** from [Open Iconic](h
#### Checkboxes

{% example html %}
<label class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>
<div class="custom-control custom-checkbox">
<label>
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>
</div>
{% endexample %}

Custom checkboxes can also utilize the `:indeterminate` pseudo class when manually set via JavaScript (there is no available HTML attribute for specifying it).

<div class="bd-example bd-example-indeterminate">
<label class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>
<div class="custom-control custom-checkbox">
<label>
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>
</div>
</div>

If you're using jQuery, something like this should suffice:
Expand All @@ -956,48 +970,57 @@ $('.your-checkbox').prop('indeterminate', true)
#### Radios

{% example html %}
<label class="custom-control custom-radio">
<input id="radio1" name="radio" type="radio" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
<label class="custom-control custom-radio">
<input id="radio2" name="radio" type="radio" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Or toggle this other custom radio</span>
</label>
<div class="custom-control custom-radio">
<label>
<input id="radio1" name="radio" type="radio" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
</div>
<div class="custom-control custom-radio">
<label>
<input id="radio2" name="radio" type="radio" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Or toggle this other custom radio</span>
</label>
</div>
{% endexample %}

#### Disabled

Custom checkboxes and radios can also be disabled. Add the `disabled` boolean attribute to the `<input>` and the custom indicator and label description will be automatically styled.

{% example html %}
<label class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" disabled>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>

<label class="custom-control custom-radio">
<input id="radio3" name="radioDisabled" type="radio" class="custom-control-input" disabled>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
<div class="custom-control custom-checkbox">
<label>
<input type="checkbox" class="custom-control-input" disabled>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Check this custom checkbox</span>
</label>
</div>
<div class="custom-control custom-radio">
<label>
<input id="radio3" name="radioDisabled" type="radio" class="custom-control-input" disabled>
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
</div>
{% endexample %}

#### Stacked
#### Inline

Custom checkboxes and radios are inline to start. Add a parent with class `.custom-controls-stacked` to ensure each form control is on separate lines.
Custom checkboxes and radios are stacked to start. Add class `.custom-control-inline` to each `.custom-control` to display it inline.

{% example html %}
<div class="custom-controls-stacked">
<label class="custom-control custom-radio">
<div class="custom-control custom-control-inline custom-radio">
<label>
<input id="radioStacked3" name="radio-stacked" type="radio" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Toggle this custom radio</span>
</label>
<label class="custom-control custom-radio">
</div>
<div class="custom-control custom-control-inline custom-radio">
<label>
<input id="radioStacked4" name="radio-stacked" type="radio" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Or toggle this other custom radio</span>
Expand Down
33 changes: 17 additions & 16 deletions scss/_custom-forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@

.custom-control {
position: relative;
display: inline-flex;
min-height: (1rem * $line-height-base);
padding-left: $custom-control-gutter;
margin-right: $custom-control-spacer-x;
margin-bottom: $custom-control-spacer-y;

label {
display: inline;
padding-left: $custom-control-gutter;
margin-bottom: 0;
}
}

.custom-control-input {
position: absolute;
z-index: -1; // Put the input behind the label so it doesn't overlay text
top: (($line-height-base - $custom-control-indicator-size) / 2);
left: 0;
width: $custom-control-indicator-size;
height: $custom-control-indicator-size;
opacity: 0;

&:checked ~ .custom-control-indicator {
Expand Down Expand Up @@ -123,19 +129,14 @@

// Layout options
//
// By default radios and checkboxes are `inline-block` with no additional spacing
// set. Use these optional classes to tweak the layout.

.custom-controls-stacked {
display: flex;
flex-direction: column;
// By default radios and checkboxes are stacked, add `.custom-control-inline`
// to each `.custom-control` to display it inline.

.custom-control {
margin-bottom: $custom-control-spacer-y;
.custom-control-inline {
display: inline-block;

+ .custom-control {
margin-left: 0;
}
+ .custom-control-inline {
margin-left: $custom-control-spacer-x;
}
}

Expand Down
14 changes: 0 additions & 14 deletions scss/_forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -336,20 +336,6 @@ select.form-control-lg {
margin-left: 0;
}

// Custom form controls
.custom-control {
display: flex;
align-items: center;
justify-content: center;
padding-left: 0;
}
.custom-control-indicator {
position: static;
display: inline-block;
margin-right: $form-check-input-margin-x; // Flexbox alignment means we lose our HTML space here, so we compensate.
vertical-align: text-bottom;
}

// Re-override the feedback icon.
.has-feedback .form-control-feedback {
top: 0;
Expand Down