From 06641ca0b3fe28021907f30c6f297d40f789f2fa Mon Sep 17 00:00:00 2001 From: Mark Otto Date: Thu, 19 Oct 2017 09:03:33 -0700 Subject: [PATCH] Gradients and shadows (#24429) * Update the form focus mixin to use a manual `$enable-shadows` check so we can always ensure a focus state for accessibility and consistency * - Add new `$input-btn-focus-width` and `$input-btn-focus-color` variables. - Replace separate `$btn-focus-box-shadow` and `$input-focus-box-shadow` variables with unified `$input-btn-focus-box-shadow` to match our combined variables approach elsewhere. * Put new focus width var to use in buttons mixins * use new button input-box shadow var * Add a new mixin for quickly adding linear gradient to components when $enable-gradients is set to true * use correct var * fix focus shadows in button mixins * Add opt-in gradients to alerts, buttons, carousel, custom radios and checkboxes, custom file input, and dropdown items * Generate .bg-gradient- utilities * add headings to colors page and document bg-gradient utils * update the button color for active status, check with yiq as it's done for basic state and hover state --- docs/4.0/utilities/colors.md | 13 +++++++++++++ scss/_buttons.scss | 4 ++-- scss/_carousel.scss | 6 ++++++ scss/_custom-forms.scss | 6 +++--- scss/_dropdown.scss | 4 ++-- scss/_variables.scss | 8 +++++--- scss/mixins/_alert.scss | 2 +- scss/mixins/_background-variant.scss | 6 ++++++ scss/mixins/_buttons.scss | 25 ++++++++++++++++++------- scss/mixins/_forms.scss | 7 ++++++- scss/mixins/_gradients.scss | 8 ++++++++ scss/utilities/_background.scss | 6 ++++++ 12 files changed, 76 insertions(+), 19 deletions(-) diff --git a/docs/4.0/utilities/colors.md b/docs/4.0/utilities/colors.md index 13c0adc8a1..cf9de15328 100644 --- a/docs/4.0/utilities/colors.md +++ b/docs/4.0/utilities/colors.md @@ -6,6 +6,8 @@ group: utilities toc: true --- +## Color + {% example html %} {% for color in site.data.theme-colors %}

.text-{{ color.name }}

{% endfor %} @@ -22,6 +24,8 @@ Contextual text classes also work well on anchors with the provided hover and fo

White link

{% endexample %} +## Background color + Similar to the contextual text color classes, easily set the background of an element to any contextual class. Anchor components will darken on hover, just like the text classes. Background utilities **do not set `color`**, so in some cases you'll want to use `.text-*` utilities. {% example html %} @@ -30,6 +34,15 @@ Similar to the contextual text color classes, easily set the background of an el
.bg-white
{% endexample %} +## Background gradient + +When `$enable-shadows` is set to true, you'll be able to use `.bg-gradient-` utility classes. **By default, `$enable-shadows` is disabled and the example below is intentionally broken.** This is done for easier customization from moment you start using Bootstrap. [Learn about our Sass options]({{ site.baseurl }}/docs/{{ site.docs_version }}/getting-started/theming/#sass-options) to enable these classes and more. + +{% example html %} +{% for color in site.data.theme-colors %} +
.bg-gradient-{{ color.name }}
{% endfor %} +{% endexample %} + {% callout info %} #### Dealing with specificity diff --git a/scss/_buttons.scss b/scss/_buttons.scss index 72fc5f3406..7cd27830b5 100644 --- a/scss/_buttons.scss +++ b/scss/_buttons.scss @@ -22,7 +22,7 @@ &:focus, &.focus { outline: 0; - box-shadow: $btn-focus-box-shadow; + box-shadow: $input-btn-focus-box-shadow; } // Disabled comes first so active can properly restyle @@ -35,7 +35,7 @@ &:not([disabled]):not(.disabled):active, &:not([disabled]):not(.disabled).active { background-image: none; - @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow); + @include box-shadow($input-btn-focus-box-shadow, $btn-active-box-shadow); } } diff --git a/scss/_carousel.scss b/scss/_carousel.scss index 8aa14ace79..c3c207387c 100644 --- a/scss/_carousel.scss +++ b/scss/_carousel.scss @@ -90,9 +90,15 @@ } .carousel-control-prev { left: 0; + @if $enable-gradients { + background: linear-gradient(90deg, rgba(0,0,0,.25), rgba(0,0,0,.001)); + } } .carousel-control-next { right: 0; + @if $enable-gradients { + background: linear-gradient(270deg, rgba(0,0,0,.25), rgba(0,0,0,.001)); + } } // Icons for within diff --git a/scss/_custom-forms.scss b/scss/_custom-forms.scss index 41dae4d760..a521dbdc94 100644 --- a/scss/_custom-forms.scss +++ b/scss/_custom-forms.scss @@ -22,7 +22,7 @@ &:checked ~ .custom-control-indicator { color: $custom-control-indicator-checked-color; - background-color: $custom-control-indicator-checked-bg; + @include gradient-bg($custom-control-indicator-checked-bg); @include box-shadow($custom-control-indicator-checked-box-shadow); } @@ -33,7 +33,7 @@ &:active ~ .custom-control-indicator { color: $custom-control-indicator-active-color; - background-color: $custom-control-indicator-active-bg; + @include gradient-bg($custom-control-indicator-active-bg); @include box-shadow($custom-control-indicator-active-box-shadow); } @@ -244,7 +244,7 @@ padding: $custom-file-padding-y $custom-file-padding-x; line-height: $custom-file-line-height; color: $custom-file-button-color; - background-color: $custom-file-button-bg; + @include gradient-bg($custom-file-button-bg); border: $custom-file-border-width solid $custom-file-border-color; @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0); } diff --git a/scss/_dropdown.scss b/scss/_dropdown.scss index 1782d5b9f1..daa867a573 100644 --- a/scss/_dropdown.scss +++ b/scss/_dropdown.scss @@ -67,14 +67,14 @@ @include hover-focus { color: $dropdown-link-hover-color; text-decoration: none; - background-color: $dropdown-link-hover-bg; + @include gradient-bg($dropdown-link-hover-bg); } &.active, &:active { color: $dropdown-link-active-color; text-decoration: none; - background-color: $dropdown-link-active-bg; + @include gradient-bg($dropdown-link-active-bg); } &.disabled, diff --git a/scss/_variables.scss b/scss/_variables.scss index d59b26abf0..0615f35d41 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -314,6 +314,10 @@ $input-btn-padding-y: .375rem !default; $input-btn-padding-x: .75rem !default; $input-btn-line-height: $line-height-base !default; +$input-btn-focus-width: .2rem !default; +$input-btn-focus-color: rgba(theme-color("primary"), .25) !default; +$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default; + $input-btn-padding-y-sm: .25rem !default; $input-btn-padding-x-sm: .5rem !default; $input-btn-line-height-sm: $line-height-sm !default; @@ -324,7 +328,6 @@ $input-btn-line-height-lg: $line-height-lg !default; $btn-font-weight: $font-weight-normal !default; $btn-box-shadow: inset 0 1px 0 rgba($white,.15), 0 1px 1px rgba($black,.075) !default; -$btn-focus-box-shadow: 0 0 0 3px rgba(theme-color("primary"), .25) !default; $btn-active-box-shadow: inset 0 3px 5px rgba($black,.125) !default; $btn-link-disabled-color: $gray-600 !default; @@ -355,7 +358,6 @@ $input-border-radius-sm: $border-radius-sm !default; $input-focus-bg: $input-bg !default; $input-focus-border-color: lighten(theme-color("primary"), 25%) !default; -$input-focus-box-shadow: $input-box-shadow, $btn-focus-box-shadow !default; $input-focus-color: $input-color !default; $input-placeholder-color: $gray-600 !default; @@ -404,7 +406,7 @@ $custom-control-indicator-checked-color: $white !default; $custom-control-indicator-checked-bg: theme-color("primary") !default; $custom-control-indicator-checked-box-shadow: none !default; -$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, 0 0 0 3px theme-color("primary") !default; +$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default; $custom-control-indicator-active-color: $white !default; $custom-control-indicator-active-bg: lighten(theme-color("primary"), 35%) !default; diff --git a/scss/mixins/_alert.scss b/scss/mixins/_alert.scss index d938e89722..db5a7eb454 100644 --- a/scss/mixins/_alert.scss +++ b/scss/mixins/_alert.scss @@ -1,6 +1,6 @@ @mixin alert-variant($background, $border, $color) { color: $color; - background-color: $background; + @include gradient-bg($background); border-color: $border; hr { diff --git a/scss/mixins/_background-variant.scss b/scss/mixins/_background-variant.scss index 5860d7384c..7d1bc975c1 100644 --- a/scss/mixins/_background-variant.scss +++ b/scss/mixins/_background-variant.scss @@ -12,3 +12,9 @@ } } } + +@mixin bg-gradient-variant($parent, $color) { + #{$parent} { + background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important; + } +} diff --git a/scss/mixins/_buttons.scss b/scss/mixins/_buttons.scss index 798bfe89e9..9e06261396 100644 --- a/scss/mixins/_buttons.scss +++ b/scss/mixins/_buttons.scss @@ -5,13 +5,13 @@ @mixin button-variant($background, $border, $hover-background: darken($background, 7.5%), $hover-border: darken($border, 10%), $active-background: darken($background, 10%), $active-border: darken($border, 12.5%)) { color: color-yiq($background); - background-color: $background; + @include gradient-bg($background); border-color: $border; @include box-shadow($btn-box-shadow); @include hover { color: color-yiq($hover-background); - background-color: $hover-background; + @include gradient-bg($hover-background); border-color: $hover-border; } @@ -19,9 +19,9 @@ &.focus { // Avoid using mixin so we can pass custom focus shadow properly @if $enable-shadows { - box-shadow: $btn-box-shadow, 0 0 0 3px rgba($border, .5); + box-shadow: $btn-box-shadow, 0 0 0 $input-btn-focus-width rgba($border, .5); } @else { - box-shadow: 0 0 0 3px rgba($border, .5); + box-shadow: 0 0 0 $input-btn-focus-width rgba($border, .5); } } @@ -35,10 +35,19 @@ &:not([disabled]):not(.disabled):active, &:not([disabled]):not(.disabled).active, .show > &.dropdown-toggle { + color: color-yiq($active-background); background-color: $active-background; - background-image: none; // Remove the gradient for the pressed/active state + @if $enable-gradients { + background-image: none; // Remove the gradient for the pressed/active state + } border-color: $active-border; - @include box-shadow($btn-active-box-shadow); + + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: $btn-active-box-shadow, 0 0 0 $input-btn-focus-width rgba($border, .5); + } @else { + box-shadow: 0 0 0 $input-btn-focus-width rgba($border, .5); + } } } @@ -56,7 +65,7 @@ &:focus, &.focus { - box-shadow: 0 0 0 3px rgba($color, .5); + box-shadow: 0 0 0 $input-btn-focus-width rgba($color, .5); } &.disabled, @@ -71,6 +80,8 @@ color: $color-hover; background-color: $color; border-color: $color; + // Avoid using mixin so we can pass custom focus shadow properly + box-shadow: 0 0 0 $input-btn-focus-width rgba($color, .5); } } diff --git a/scss/mixins/_forms.scss b/scss/mixins/_forms.scss index 6403f469d9..19d52807e8 100644 --- a/scss/mixins/_forms.scss +++ b/scss/mixins/_forms.scss @@ -16,7 +16,12 @@ background-color: $input-focus-bg; border-color: $input-focus-border-color; outline: none; - @include box-shadow($input-focus-box-shadow); + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: $input-box-shadow, $input-btn-focus-box-shadow; + } @else { + box-shadow: $input-btn-focus-box-shadow; + } } } diff --git a/scss/mixins/_gradients.scss b/scss/mixins/_gradients.scss index bad79f9617..ecd01f7291 100644 --- a/scss/mixins/_gradients.scss +++ b/scss/mixins/_gradients.scss @@ -1,5 +1,13 @@ // Gradients +@mixin gradient-bg($color) { + @if $enable-gradients { + background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x; + } @else { + background-color: $color; + } +} + // Horizontal gradient, from left to right // // Creates two color stops, start and end, by specifying a color and position for each color stop. diff --git a/scss/utilities/_background.scss b/scss/utilities/_background.scss index 3d2e07d699..1f18b2f3f3 100644 --- a/scss/utilities/_background.scss +++ b/scss/utilities/_background.scss @@ -4,6 +4,12 @@ @include bg-variant(".bg-#{$color}", $value); } +@if $enable-gradients { + @each $color, $value in $theme-colors { + @include bg-gradient-variant(".bg-gradient-#{$color}", $value); + } +} + .bg-white { background-color: $white !important; }