diff --git a/Gruntfile.js b/Gruntfile.js index a6fe95476..341c36ebd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -19,6 +19,7 @@ module.exports = function (grunt) { var path = require('path'); var glob = require('glob'); var npmShrinkwrap = require('npm-shrinkwrap'); + var mq4HoverShim = require('mq4-hover-hover-shim'); var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js'); var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' }); @@ -107,6 +108,8 @@ module.exports = function (grunt) { }, bootstrap: { src: [ + 'js/hover.js', + mq4HoverShim.featureDetector.umdGlobal, 'js/transition.js', 'js/alert.js', 'js/button.js', @@ -153,6 +156,16 @@ module.exports = function (grunt) { } }, + postcss: { + options: { + map: true, + processors: [mq4HoverShim.postprocessorFor({hoverSelectorPrefix: '.bs-true-hover '})] + }, + core: { + src: 'dist/css/<%= pkg.name %>.css' + } + }, + autoprefixer: { options: { browsers: [ @@ -392,7 +405,7 @@ module.exports = function (grunt) { })(process.env.TWBS_SASS || 'libsass'); grunt.registerTask('sass-compile', ['sass:core', 'sass:docs']); - grunt.registerTask('dist-css', ['sass-compile', 'autoprefixer:core', 'usebanner', 'csscomb:dist', 'cssmin:core', 'cssmin:docs']); + grunt.registerTask('dist-css', ['sass-compile', 'postcss:core', 'autoprefixer:core', 'usebanner', 'csscomb:dist', 'cssmin:core', 'cssmin:docs']); // Full distribution task. grunt.registerTask('dist', ['clean:dist', 'dist-css', 'dist-js']); diff --git a/docs/getting-started/support.md b/docs/getting-started/support.md index 63667fe85..6ed11c5e2 100644 --- a/docs/getting-started/support.md +++ b/docs/getting-started/support.md @@ -167,7 +167,9 @@ The `.dropdown-backdrop` element isn't used on iOS in the nav because of the com Page zooming inevitably presents rendering artifacts in some components, both in Bootstrap and the rest of the web. Depending on the issue, we may be able to fix it (search first and then open an issue if need be). However, we tend to ignore these as they often have no direct solution other than hacky workarounds. ### Sticky `:hover`/`:focus` on mobile -Even though real hovering isn't possible on most touchscreens, most mobile browsers emulate hovering support and make `:hover` "sticky". In other words, `:hover` styles start applying after tapping an element and only stop applying after the user taps some other element. This can cause Bootstrap's `:hover` states to become unwantedly "stuck" on such browsers. Some mobile browsers also make `:focus` similarly sticky. There is currently no simple workaround for these issues other than removing such styles entirely. +Even though real hovering isn't possible on most touchscreens, most mobile browsers emulate hovering support and make `:hover` "sticky". In other words, `:hover` styles start applying after tapping an element and only stop applying after the user taps some other element. On mobile-first sites, this behavior is normally undesirable. + +Bootstrap includes a workaround for this, although it is disabled by default. By setting `$use-hover-media-query` to `true` when compiling from Sass, Bootstrap will use [mq4-hover-hover-shim](https://github.com/cvrebert/mq4-hover-hover-shim) to disable `:hover` styles in browsers that emulate hovering, thus preventing sticky `:hover` styles. There are some caveats to this workaround; see the shim's documentation for details. ### Printing diff --git a/js/hover.js b/js/hover.js new file mode 100644 index 000000000..50ba77768 --- /dev/null +++ b/js/hover.js @@ -0,0 +1,4 @@ +$(document).on('mq4hsChange', function (e) { + 'use strict'; + $(document.documentElement).toggleClass('bs-true-hover', e.trueHover); +}); diff --git a/package.json b/package.json index 37e156ab9..5cf0d04dd 100644 --- a/package.json +++ b/package.json @@ -54,12 +54,14 @@ "grunt-html-validation": "~0.1.18", "grunt-jekyll": "~0.4.2", "grunt-jscs": "~1.2.0", + "grunt-postcss": "^0.3.0", "grunt-sass": "~0.17.0", "grunt-saucelabs": "~8.5.0", "grunt-scss-lint": "^0.3.4", "grunt-sed": "~0.1.1", "load-grunt-tasks": "~2.0.0", "markdown-it": "^3.0.4", + "mq4-hover-hover-shim": "0.0.4", "npm-shrinkwrap": "^200.0.0", "time-grunt": "~1.0.0" }, diff --git a/scss/_badge.scss b/scss/_badge.scss index 2c70b59fc..b3afccd79 100644 --- a/scss/_badge.scss +++ b/scss/_badge.scss @@ -47,8 +47,7 @@ // Hover state, but only for links a.badge { - &:hover, - &:focus { + @include hover-focus { color: $badge-link-hover-color; text-decoration: none; cursor: pointer; diff --git a/scss/_button-group.scss b/scss/_button-group.scss index 839ce2587..6e8ae63de 100644 --- a/scss/_button-group.scss +++ b/scss/_button-group.scss @@ -14,12 +14,14 @@ float: left; // Bring the "active" button to the front - &:hover, &:focus, &:active, &.active { z-index: 2; } + @include hover { + z-index: 2; + } } } diff --git a/scss/_buttons.scss b/scss/_buttons.scss index 41485acd3..5f4b3bc42 100644 --- a/scss/_buttons.scss +++ b/scss/_buttons.scss @@ -29,8 +29,9 @@ } } - &:hover, - &:focus, + @include hover-focus { + text-decoration: none; + } &.focus { text-decoration: none; } @@ -94,21 +95,21 @@ @include box-shadow(none); } &, - &:hover, &:focus, &:active { border-color: transparent; } - &:hover, - &:focus { + @include hover { + border-color: transparent; + } + @include hover-focus { color: $link-hover-color; text-decoration: $link-hover-decoration; background-color: transparent; } &:disabled, fieldset[disabled] & { - &:hover, - &:focus { + @include hover-focus { color: $btn-link-disabled-color; text-decoration: none; } diff --git a/scss/_card.scss b/scss/_card.scss index 9ff7850f7..eda67b8ac 100644 --- a/scss/_card.scss +++ b/scss/_card.scss @@ -20,8 +20,10 @@ margin-left: .75rem; } } -.card-link:hover { - text-decoration: none; +.card-link { + @include hover { + text-decoration: none; + } } @@ -89,9 +91,10 @@ .card-blockquote > footer { color: rgba(255,255,255,.65); } - .card-link:hover, - .card-link:focus { - color: #fff; + .card-link { + @include hover-focus { + color: #fff; + } } } diff --git a/scss/_carousel.scss b/scss/_carousel.scss index 692ac938b..90aee7ad9 100644 --- a/scss/_carousel.scss +++ b/scss/_carousel.scss @@ -115,8 +115,7 @@ } // Hover/focus state - &:hover, - &:focus { + @include hover-focus { color: $carousel-control-color; text-decoration: none; outline: 0; diff --git a/scss/_close.scss b/scss/_close.scss index 11815db27..da86108d6 100644 --- a/scss/_close.scss +++ b/scss/_close.scss @@ -12,8 +12,7 @@ text-shadow: $close-text-shadow; opacity: .2; - &:hover, - &:focus { + @include hover-focus { color: $close-color; text-decoration: none; cursor: pointer; diff --git a/scss/_custom-forms.scss b/scss/_custom-forms.scss index 5b307f128..b5043b469 100644 --- a/scss/_custom-forms.scss +++ b/scss/_custom-forms.scss @@ -182,10 +182,11 @@ } // Hover state -// Uncomment if you need it, but be aware of the sticky iOS states. -// .select select:hover { -// background-color: #ddd; -// } +.select select { + @include hover { + background-color: #ddd; + } +} // Media query to target Firefox only @@ -223,11 +224,11 @@ content: ""; background-color: #eee; } - .select select:hover, - .select select:focus, - .select select:active { - color: #555; - background-color: #eee; + .select select { + @include hover-focus-active { + color: #555; + background-color: #eee; + } } } diff --git a/scss/_dropdown.scss b/scss/_dropdown.scss index 8abea3c41..469aa561a 100644 --- a/scss/_dropdown.scss +++ b/scss/_dropdown.scss @@ -67,8 +67,7 @@ // Hover/Focus state .dropdown-menu > li > a { - &:hover, - &:focus { + @include hover-focus { color: $dropdown-link-hover-color; text-decoration: none; background-color: $dropdown-link-hover-bg; @@ -77,9 +76,7 @@ // Active state .dropdown-menu > .active > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $dropdown-link-active-color; text-decoration: none; background-color: $dropdown-link-active-bg; @@ -92,15 +89,12 @@ // Gray out text and ensure the hover/focus state remains gray .dropdown-menu > .disabled > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $dropdown-link-disabled-color; } // Nuke hover/focus effects - &:hover, - &:focus { + @include hover-focus { text-decoration: none; cursor: $cursor-disabled; background-color: transparent; diff --git a/scss/_input-group.scss b/scss/_input-group.scss index dbc36c08e..ec6e385e9 100644 --- a/scss/_input-group.scss +++ b/scss/_input-group.scss @@ -143,9 +143,7 @@ margin-left: -1px; } // Bring the "active" button to the front - &:hover, - &:focus, - &:active { + @include hover-focus-active { z-index: 2; } } diff --git a/scss/_labels.scss b/scss/_labels.scss index 8503d2329..5c4a29afa 100644 --- a/scss/_labels.scss +++ b/scss/_labels.scss @@ -28,8 +28,7 @@ // Add hover effects, but only for links a.label { - &:hover, - &:focus { + @include hover-focus { color: $label-link-hover-color; text-decoration: none; cursor: pointer; diff --git a/scss/_list-group.scss b/scss/_list-group.scss index 58767105d..f1af67640 100644 --- a/scss/_list-group.scss +++ b/scss/_list-group.scss @@ -51,8 +51,7 @@ a.list-group-item { } // Hover state - &:hover, - &:focus { + @include hover-focus { color: $list-group-link-hover-color; text-decoration: none; background-color: $list-group-hover-bg; @@ -61,39 +60,39 @@ a.list-group-item { .list-group-item { // Disabled state - &.disabled, - &.disabled:hover, - &.disabled:focus { - color: $list-group-disabled-color; - cursor: $cursor-disabled; - background-color: $list-group-disabled-bg; + &.disabled { + @include plain-hover-focus { + color: $list-group-disabled-color; + cursor: $cursor-disabled; + background-color: $list-group-disabled-bg; - // Force color to inherit for custom content - .list-group-item-heading { - color: inherit; - } - .list-group-item-text { - color: $list-group-disabled-text-color; + // Force color to inherit for custom content + .list-group-item-heading { + color: inherit; + } + .list-group-item-text { + color: $list-group-disabled-text-color; + } } } // Active class on item itself, not parent - &.active, - &.active:hover, - &.active:focus { - z-index: 2; // Place active items above their siblings for proper border styling - color: $list-group-active-color; - background-color: $list-group-active-bg; - border-color: $list-group-active-border; + &.active { + @include plain-hover-focus { + z-index: 2; // Place active items above their siblings for proper border styling + color: $list-group-active-color; + background-color: $list-group-active-bg; + border-color: $list-group-active-border; - // Force color to inherit for custom content - .list-group-item-heading, - .list-group-item-heading > small, - .list-group-item-heading > .small { - color: inherit; - } - .list-group-item-text { - color: $list-group-active-text-color; + // Force color to inherit for custom content + .list-group-item-heading, + .list-group-item-heading > small, + .list-group-item-heading > .small { + color: inherit; + } + .list-group-item-text { + color: $list-group-active-text-color; + } } } } diff --git a/scss/_mixins.scss b/scss/_mixins.scss index 36f52a893..944ff669c 100644 --- a/scss/_mixins.scss +++ b/scss/_mixins.scss @@ -26,6 +26,7 @@ // Utilities @import "mixins/breakpoints"; @import "mixins/hide-text"; +@import "mixins/hover"; @import "mixins/image"; @import "mixins/label"; @import "mixins/reset-filter"; diff --git a/scss/_nav.scss b/scss/_nav.scss index e989a40c1..3d27891be 100644 --- a/scss/_nav.scss +++ b/scss/_nav.scss @@ -18,8 +18,7 @@ padding: $nav-link-padding; line-height: $line-height-base; - &:hover, - &:focus { + @include hover-focus { text-decoration: none; background-color: $nav-link-hover-bg; } @@ -29,9 +28,7 @@ &.disabled { color: $nav-disabled-link-color; - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $nav-disabled-link-hover-color; cursor: $cursor-disabled; background-color: transparent; @@ -62,8 +59,7 @@ border: 1px solid transparent; @include border-radius($border-radius-base $border-radius-base 0 0); - &:hover, - &:focus { + @include hover-focus { border-color: $nav-tabs-link-hover-border-color $nav-tabs-link-hover-border-color $nav-tabs-border-color; } } @@ -72,9 +68,7 @@ .active > .nav-link, .nav-link.open, .nav-link.active { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $nav-tabs-active-link-hover-color; background-color: $nav-tabs-active-link-hover-bg; border-color: $nav-tabs-active-link-hover-border-color $nav-tabs-active-link-hover-border-color transparent; @@ -83,9 +77,7 @@ .disabled > .nav-link, .nav-link.disabled { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $nav-disabled-link-color; background-color: transparent; border-color: transparent; @@ -116,9 +108,7 @@ .active > .nav-link, .nav-link.open, .nav-link.active { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $component-active-color; cursor: default; background-color: $component-active-bg; diff --git a/scss/_navbar.scss b/scss/_navbar.scss index 2c12049a0..6907ae724 100644 --- a/scss/_navbar.scss +++ b/scss/_navbar.scss @@ -69,9 +69,10 @@ font-size: $font-size-lg; line-height: $line-height-computed; - > a:hover, - > a:focus { - text-decoration: none; + > a { + @include hover-focus { + text-decoration: none; + } } > img { @@ -95,8 +96,7 @@ background: none; border: 0; - &:hover, - &:focus { + @include hover-focus { text-decoration: none; } } @@ -223,8 +223,7 @@ .navbar-brand { color: $navbar-default-brand-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-default-brand-hover-color; background-color: $navbar-default-brand-hover-bg; } @@ -238,24 +237,19 @@ > li > a { color: $navbar-default-link-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-default-link-hover-color; background-color: $navbar-default-link-hover-bg; } } > .active > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $navbar-default-link-active-color; background-color: $navbar-default-link-active-bg; } } > .disabled > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $navbar-default-link-disabled-color; background-color: $navbar-default-link-disabled-bg; } @@ -264,8 +258,7 @@ .navbar-toggle { border-color: $navbar-default-toggle-border-color; - &:hover, - &:focus { + @include hover-focus { background-color: $navbar-default-toggle-hover-bg; } .icon-bar { @@ -282,9 +275,7 @@ .navbar-nav { // Remove background color from open dropdown > .open > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $navbar-default-link-active-color; background-color: $navbar-default-link-active-bg; } @@ -298,21 +289,19 @@ .navbar-link { color: $navbar-default-link-color; - &:hover { + @include hover { color: $navbar-default-link-hover-color; } } .btn-link { color: $navbar-default-link-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-default-link-hover-color; } &:disabled, fieldset[disabled] & { - &:hover, - &:focus { + @include hover-focus { color: $navbar-default-link-disabled-color; } } @@ -330,14 +319,12 @@ .nav-pills > .nav-item > .nav-link { color: $navbar-inverse-link-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-inverse-link-hover-color; } } .nav-pills > .nav-item > .nav-link { - &:hover, - &:focus { + @include hover-focus { color: $navbar-inverse-link-active-color; background-color: $navbar-inverse-link-active-bg; } @@ -351,8 +338,7 @@ .navbar-brand { color: $navbar-inverse-brand-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-inverse-brand-hover-color; background-color: $navbar-inverse-brand-hover-bg; } @@ -366,24 +352,19 @@ > li > a { color: $navbar-inverse-link-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-inverse-link-hover-color; background-color: $navbar-inverse-link-hover-bg; } } > .active > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $navbar-inverse-link-active-color; background-color: $navbar-inverse-link-active-bg; } } > .disabled > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $navbar-inverse-link-disabled-color; background-color: $navbar-inverse-link-disabled-bg; } @@ -398,9 +379,7 @@ // Dropdowns .navbar-nav { > .open > a { - &, - &:hover, - &:focus { + @include plain-hover-focus { color: $navbar-inverse-link-active-color; background-color: $navbar-inverse-link-active-bg; } @@ -409,7 +388,7 @@ .navbar-link { color: $navbar-inverse-link-color; - &:hover { + @include hover { color: $navbar-inverse-link-hover-color; } } @@ -417,15 +396,13 @@ .btn-link { color: $navbar-inverse-link-color; - &:hover, - &:focus { + @include hover-focus { color: $navbar-inverse-link-hover-color; } &:disabled, fieldset[disabled] & { - &:hover, - &:focus { + @include hover-focus { color: $navbar-inverse-link-disabled-color; } } diff --git a/scss/_normalize.scss b/scss/_normalize.scss index 62a085a48..135fe2a3a 100644 --- a/scss/_normalize.scss +++ b/scss/_normalize.scss @@ -94,9 +94,13 @@ a { // Improve readability when focused and also mouse hovered in all browsers. // -a:active, -a:hover { - outline: 0; +a { + &:active { + outline: 0; + } + @include hover { + outline: 0; + } } // Text-level semantics diff --git a/scss/_pager.scss b/scss/_pager.scss index 4009c0946..cb4ccfb35 100644 --- a/scss/_pager.scss +++ b/scss/_pager.scss @@ -22,17 +22,22 @@ border-radius: $pager-border-radius; } - > a:hover, - > a:focus { - text-decoration: none; - background-color: $pager-hover-bg; + > a { + @include hover-focus { + text-decoration: none; + background-color: $pager-hover-bg; + } } } .disabled { - > a, - > a:hover, - > a:focus, + > a { + @include plain-hover-focus { + color: $pager-disabled-color; + cursor: $cursor-disabled; + background-color: $pager-bg; + } + } > span { color: $pager-disabled-color; cursor: $cursor-disabled; diff --git a/scss/_pagination.scss b/scss/_pagination.scss index 6af0308a7..55814b94a 100644 --- a/scss/_pagination.scss +++ b/scss/_pagination.scss @@ -39,8 +39,7 @@ > li > a, > li > span { - &:hover, - &:focus { + @include hover-focus { color: $pagination-hover-color; background-color: $pagination-hover-bg; border-color: $pagination-hover-border; @@ -49,9 +48,7 @@ > .active > a, > .active > span { - &, - &:hover, - &:focus { + @include plain-hover-focus { z-index: 2; color: $pagination-active-color; cursor: default; @@ -62,15 +59,13 @@ > .disabled { > span, - > span:hover, - > span:focus, - > a, - > a:hover, - > a:focus { - color: $pagination-disabled-color; - cursor: $cursor-disabled; - background-color: $pagination-disabled-bg; - border-color: $pagination-disabled-border; + > a { + @include plain-hover-focus { + color: $pagination-disabled-color; + cursor: $cursor-disabled; + background-color: $pagination-disabled-bg; + border-color: $pagination-disabled-border; + } } } } diff --git a/scss/_scaffolding.scss b/scss/_scaffolding.scss index 038ee020b..a6abc862d 100644 --- a/scss/_scaffolding.scss +++ b/scss/_scaffolding.scss @@ -72,8 +72,7 @@ a { color: $link-color; text-decoration: none; - &:hover, - &:focus { + @include hover-focus { color: $link-hover-color; text-decoration: $link-hover-decoration; } diff --git a/scss/_tables.scss b/scss/_tables.scss index 43f50c5be..0156b0fcc 100644 --- a/scss/_tables.scss +++ b/scss/_tables.scss @@ -99,8 +99,10 @@ th { // Placed here since it has to come after the potential zebra striping .table-hover { - tbody tr:hover { - background-color: $table-bg-hover; + tbody tr { + @include hover { + background-color: $table-bg-hover; + } } } diff --git a/scss/_variables.scss b/scss/_variables.scss index 60fb87015..2a1f8e25b 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -50,6 +50,8 @@ $enable-transitions: true !default; $spacer: 1rem !default; $border-width: .075rem !default; +$use-hover-media-query: false !default; + //== Typography // //## Font, line-height, and color for body text, headings, and more. diff --git a/scss/mixins/_background-variant.scss b/scss/mixins/_background-variant.scss index 4993bd2b8..577f019ca 100644 --- a/scss/mixins/_background-variant.scss +++ b/scss/mixins/_background-variant.scss @@ -5,7 +5,9 @@ #{$parent} { background-color: $color; } - a#{$parent}:hover { - background-color: darken($color, 10%); + a#{$parent} { + @include hover { + background-color: darken($color, 10%); + } } } diff --git a/scss/mixins/_buttons.scss b/scss/mixins/_buttons.scss index b043d60de..f18b9c253 100644 --- a/scss/mixins/_buttons.scss +++ b/scss/mixins/_buttons.scss @@ -10,15 +10,22 @@ // $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075); // .box-shadow($shadow); - &:hover, + $active-background: darken($background, 10%); + $active-border: darken($border, 12%); + &:focus, &.focus, &:active, &.active, .open > &.dropdown-toggle { color: $color; - background-color: darken($background, 10%); - border-color: darken($border, 12%); + background-color: $active-background; + border-color: $active-border; + } + @include hover { + color: $color; + background-color: $active-background; + border-color: $active-border; } &:active, &.active, @@ -31,7 +38,6 @@ &:disabled, fieldset[disabled] & { &, - &:hover, &:focus, &.focus, &:active, @@ -39,6 +45,10 @@ background-color: $background; border-color: $border; } + @include hover { + background-color: $background; + border-color: $border; + } } .badge { diff --git a/scss/mixins/_hover.scss b/scss/mixins/_hover.scss new file mode 100644 index 000000000..fb5b52016 --- /dev/null +++ b/scss/mixins/_hover.scss @@ -0,0 +1,59 @@ +@mixin hover { + @if $use-hover-media-query { + // See Media Queries Level 4: http://drafts.csswg.org/mediaqueries/#hover + // Currently shimmed by https://github.com/cvrebert/mq4-hover-hover-shim + @media (hover: hover) { + &:hover { @content } + } + } + @else { + &:hover { @content } + } +} + +@mixin hover-focus { + @if $use-hover-media-query { + &:focus { @content } + @include hover { @content } + } + @else { + &:focus, + &:hover { + @content + } + } +} + +@mixin plain-hover-focus { + @if $use-hover-media-query { + &, + &:focus { + @content + } + @include hover { @content } + } + @else { + &, + &:focus, + &:hover { + @content + } + } +} + +@mixin hover-focus-active { + @if $use-hover-media-query { + &:focus, + &:active { + @content + } + @include hover { @content } + } + @else { + &:focus, + &:active, + &:hover { + @content + } + } +} diff --git a/scss/mixins/_label.scss b/scss/mixins/_label.scss index eda6dfd29..4bc48c60d 100644 --- a/scss/mixins/_label.scss +++ b/scss/mixins/_label.scss @@ -4,8 +4,7 @@ background-color: $color; &[href] { - &:hover, - &:focus { + @include hover-focus { background-color: darken($color, 10%); } } diff --git a/scss/mixins/_list-group.scss b/scss/mixins/_list-group.scss index 0683d340c..1f17729b0 100644 --- a/scss/mixins/_list-group.scss +++ b/scss/mixins/_list-group.scss @@ -13,18 +13,17 @@ color: inherit; } - &:hover, - &:focus { + @include hover-focus { color: $color; background-color: darken($background, 5%); } - &.active, - &.active:hover, - &.active:focus { - color: #fff; - background-color: $color; - border-color: $color; + &.active { + @include plain-hover-focus { + color: #fff; + background-color: $color; + border-color: $color; + } } } } diff --git a/scss/mixins/_table-row.scss b/scss/mixins/_table-row.scss index 136795081..1a48e9263 100644 --- a/scss/mixins/_table-row.scss +++ b/scss/mixins/_table-row.scss @@ -17,12 +17,26 @@ // Hover states for `.table-hover` // Note: this is not available for cells or rows within `thead` or `tfoot`. .table-hover > tbody > tr { - > td.#{$state}:hover, - > th.#{$state}:hover, - &.#{$state}:hover > td, - &:hover > .#{$state}, - &.#{$state}:hover > th { - background-color: darken($background, 5%); + $hover-background: darken($background, 5%); + + > td.#{$state}, + > th.#{$state} { + @include hover { + background-color: $hover-background; + } + } + &.#{$state} { + @include hover { + > td, + > th { + background-color: $hover-background; + } + } + } + @include hover { + > .#{$state} { + background-color: $hover-background; + } } } } diff --git a/scss/mixins/_text-emphasis.scss b/scss/mixins/_text-emphasis.scss index 4424a38d4..ab3869d31 100644 --- a/scss/mixins/_text-emphasis.scss +++ b/scss/mixins/_text-emphasis.scss @@ -4,7 +4,9 @@ #{$parent} { color: $color; } - a#{$parent}:hover { - color: darken($color, 10%); + a#{$parent} { + @include hover { + color: darken($color, 10%); + } } }