Skip to content
Merged
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
14 changes: 11 additions & 3 deletions docs/4.1/components/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -767,9 +767,9 @@ With that in mind, consider the following demos for our custom form validation s

### Custom styles

For custom Bootstrap form validation messages, you'll need to add the `novalidate` boolean attribute to your `<form>`. This disables the browser default feedback tooltips, but still provides access to the form validation APIs in JavaScript. Try to submit the form below; our JavaScript will intercept the submit button and relay feedback to you.
For custom Bootstrap form validation messages, you'll need to add the `novalidate` boolean attribute to your `<form>`. This disables the browser default feedback tooltips, but still provides access to the form validation APIs in JavaScript. Try to submit the form below; our JavaScript will intercept the submit button and relay feedback to you. When attempting to submit, you'll see the `:invalid` and `:valid` styles applied to your form controls.

When attempting to submit, you'll see the `:invalid` and `:valid` styles applied to your form controls.
Custom feedback styles apply custom colors, borders, focus styles, and background icons to better communicate feedback. Background icons for `<select>`s are only available with `.custom-select`, and not `.form-control`.

{% capture example %}
<form class="needs-validation" novalidate>
Expand Down Expand Up @@ -990,10 +990,18 @@ We recommend using client side validation, but in case you require server side,

### Supported elements

Our example forms show native textual `<input>`s above, but form validation styles are available for our custom form controls, too.
Our example forms show native textual `<input>`s above, but form validation styles are also available for `<textarea>`s and custom form controls.

{% capture example %}
<form class="was-validated">
<div class="mb-3">
<label for="validationTextarea">Textarea</label>
<textarea class="form-control is-invalid" id="validationTextarea" placeholder="Required example textarea" required></textarea>
<div class="invalid-feedback">
Please enter a message in the textarea.
</div>
</div>

<div class="custom-control custom-checkbox mb-3">
<input type="checkbox" class="custom-control-input" id="customControlValidation1" required>
<label class="custom-control-label" for="customControlValidation1">Check this custom checkbox</label>
Expand Down
1 change: 1 addition & 0 deletions docs/4.1/getting-started/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ You can find and customize these variables for key global options in Bootstrap's
| `$enable-grid-classes` | `true` (default) or `false` | Enables the generation of CSS classes for the grid system (e.g., `.container`, `.row`, `.col-md-1`, etc.). |
| `$enable-caret` | `true` (default) or `false` | Enables pseudo element caret on `.dropdown-toggle`. |
| `$enable-print-styles` | `true` (default) or `false` | Enables styles for optimizing printing. |
| `$enable-validation-icons` | `true` (default) or `false` | Enables `background-image` icons within textual inputs and some custom forms for validation states. |

## Color

Expand Down
4 changes: 2 additions & 2 deletions scss/_custom-forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@
line-height: $custom-select-line-height;
color: $custom-select-color;
vertical-align: middle;
background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center;
background-size: $custom-select-bg-size;
background: $custom-select-background;
background-color: $custom-select-bg;
border: $custom-select-border-width solid $custom-select-border-color;
@if $enable-rounded {
border-radius: $custom-select-border-radius;
Expand Down
10 changes: 9 additions & 1 deletion scss/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ $enable-transitions: true !default;
$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS
$enable-grid-classes: true !default;
$enable-print-styles: true !default;

$enable-validation-icons: true !default;

// Spacing
//
Expand Down Expand Up @@ -515,6 +515,8 @@ $custom-select-disabled-bg: $gray-200 !default;
$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions
$custom-select-indicator-color: $gray-800 !default;
$custom-select-indicator: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"), "#", "%23") !default;
$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)

$custom-select-border-width: $input-btn-border-width !default;
$custom-select-border-color: $input-border-color !default;
$custom-select-border-radius: $border-radius !default;
Expand Down Expand Up @@ -574,6 +576,11 @@ $form-feedback-font-size: $small-font-size !default;
$form-feedback-valid-color: theme-color("success") !default;
$form-feedback-invalid-color: theme-color("danger") !default;

$form-feedback-icon-valid-color: $form-feedback-valid-color !default;
$form-feedback-icon-valid: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E"), "#", "%23") !default;
$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;
$form-feedback-icon-invalid: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E"), "#", "%23") !default;


// Dropdowns
//
Expand Down Expand Up @@ -670,6 +677,7 @@ $navbar-light-disabled-color: rgba($black, .3) !default;
$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
$navbar-light-toggler-border-color: rgba($black, .1) !default;


// Pagination

$pagination-padding-y: .5rem !default;
Expand Down
54 changes: 53 additions & 1 deletion scss/mixins/_forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,63 @@
border-radius: .2rem;
}

.form-control,
.form-control {
.was-validated &:#{$state},
&.is-#{$state} {
border-color: $color;

@if $enable-validation-icons {
padding-right: $input-height-inner;
background-repeat: no-repeat;
background-position: center right calc(#{$input-height-inner} / 4);
background-size: calc(#{$input-height-inner} / 2) calc(#{$input-height-inner} / 2);

@if $state == "valid" {
background-image: $form-feedback-icon-valid;
} @else {
background-image: $form-feedback-icon-invalid;
}
}

&:focus {
border-color: $color;
box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
}

~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
}
}

// stylelint-disable selector-no-qualifying-type
textarea.form-control {
.was-validated &:#{$state},
&.is-#{$state} {
@if $enable-validation-icons {
padding-right: $input-height-inner;
background-position: top calc(#{$input-height-inner} / 4) right calc(#{$input-height-inner} / 4);
}
}
}
// stylelint-enable selector-no-qualifying-type

.custom-select {
.was-validated &:#{$state},
&.is-#{$state} {
border-color: $color;

@if $enable-validation-icons {
padding-right: $input-height-inner;

@if $state == "valid" {
background: $custom-select-background, $form-feedback-icon-valid no-repeat center right ($input-height-inner * .9) / calc(#{$input-height-inner} / 2) calc(#{$input-height-inner} / 2);
} @else {
background: $custom-select-background, $form-feedback-icon-invalid no-repeat center right ($input-height-inner * .9) / calc(#{$input-height-inner} / 2) calc(#{$input-height-inner} / 2);
}
}

&:focus {
border-color: $color;
box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
Expand All @@ -68,6 +119,7 @@
}
}


.form-control-file {
.was-validated &:#{$state},
&.is-#{$state} {
Expand Down