From 8e374bd010a6db00acf3cb51b14788d7bf9ba097 Mon Sep 17 00:00:00 2001 From: Chris Rebert Date: Thu, 1 Jan 2015 01:05:01 -0800 Subject: [PATCH 1/4] put all :hover styles within @media (hover: hover) --- scss/_badge.scss | 3 +- scss/_button-group.scss | 4 +- scss/_buttons.scss | 15 +++--- scss/_card.scss | 13 +++-- scss/_carousel.scss | 3 +- scss/_close.scss | 3 +- scss/_custom-forms.scss | 19 ++++---- scss/_dropdown.scss | 14 ++---- scss/_input-group.scss | 4 +- scss/_labels.scss | 3 +- scss/_list-group.scss | 57 +++++++++++----------- scss/_mixins.scss | 1 + scss/_nav.scss | 22 +++------ scss/_navbar.scss | 71 ++++++++++------------------ scss/_normalize.scss | 10 ++-- scss/_pager.scss | 19 +++++--- scss/_pagination.scss | 23 ++++----- scss/_scaffolding.scss | 3 +- scss/_tables.scss | 6 ++- scss/mixins/_background-variant.scss | 6 ++- scss/mixins/_buttons.scss | 18 +++++-- scss/mixins/_hover.scss | 28 +++++++++++ scss/mixins/_label.scss | 3 +- scss/mixins/_list-group.scss | 15 +++--- scss/mixins/_table-row.scss | 26 +++++++--- scss/mixins/_text-emphasis.scss | 6 ++- 26 files changed, 208 insertions(+), 187 deletions(-) create mode 100644 scss/mixins/_hover.scss diff --git a/scss/_badge.scss b/scss/_badge.scss index 2c70b59fc6..b3afccd797 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 839ce25878..6e8ae63ded 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 41485acd3f..5f4b3bc426 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 9ff7850f7d..eda67b8acf 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 692ac938bb..90aee7ad95 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 11815db27f..da86108d6f 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 5b307f1283..b5043b4696 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 8abea3c417..469aa561a0 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 dbc36c08e0..ec6e385e94 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 8503d23291..5c4a29afa1 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 58767105d1..f1af67640d 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 36f52a8932..944ff669c6 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 e989a40c1b..3d27891be7 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 2c12049a01..6907ae7249 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 62a085a484..135fe2a3ad 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 4009c0946e..cb4ccfb354 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 6af0308a7d..55814b94a1 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 038ee020b7..a6abc862d1 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 43f50c5bea..0156b0fccb 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/mixins/_background-variant.scss b/scss/mixins/_background-variant.scss index 4993bd2b80..577f019ca2 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 b043d60de3..f18b9c253c 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 0000000000..4c415e9b44 --- /dev/null +++ b/scss/mixins/_hover.scss @@ -0,0 +1,28 @@ +@mixin hover { + // 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 } + } +} + +@mixin hover-focus { + &:focus { @content } + @include hover { @content } +} + +@mixin plain-hover-focus { + &, + &:focus { + @content + } + @include hover { @content } +} + +@mixin hover-focus-active { + &:focus, + &:active { + @content + } + @include hover { @content } +} diff --git a/scss/mixins/_label.scss b/scss/mixins/_label.scss index eda6dfd29e..4bc48c60dd 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 0683d340c0..1f17729b03 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 136795081e..1a48e92630 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 4424a38d44..ab3869d31e 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%); + } } } From eaaaa005207a7918fdc442939b6756c9ac53eec1 Mon Sep 17 00:00:00 2001 From: Chris Rebert Date: Thu, 1 Jan 2015 01:41:56 -0800 Subject: [PATCH 2/4] Integrate mq4-hover-hover-shim --- Gruntfile.js | 15 ++++++++++++++- js/hover.js | 4 ++++ package.json | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 js/hover.js diff --git a/Gruntfile.js b/Gruntfile.js index a6fe954767..341c36ebda 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/js/hover.js b/js/hover.js new file mode 100644 index 0000000000..50ba777681 --- /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 37e156ab98..5cf0d04ddf 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" }, From fd13e33aa4a662875cf367d8e0f012613cdc8447 Mon Sep 17 00:00:00 2001 From: Chris Rebert Date: Tue, 20 Jan 2015 15:35:28 -0800 Subject: [PATCH 3/4] add $use-hover-media-query to control @media (hover:hover) usage --- scss/_variables.scss | 2 ++ scss/mixins/_hover.scss | 57 +++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/scss/_variables.scss b/scss/_variables.scss index 60fb87015e..2a1f8e25b7 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/_hover.scss b/scss/mixins/_hover.scss index 4c415e9b44..fb5b520165 100644 --- a/scss/mixins/_hover.scss +++ b/scss/mixins/_hover.scss @@ -1,28 +1,59 @@ @mixin hover { - // 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) { + @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 { - &:focus { @content } - @include hover { @content } + @if $use-hover-media-query { + &:focus { @content } + @include hover { @content } + } + @else { + &:focus, + &:hover { + @content + } + } } @mixin plain-hover-focus { - &, - &:focus { - @content + @if $use-hover-media-query { + &, + &:focus { + @content + } + @include hover { @content } + } + @else { + &, + &:focus, + &:hover { + @content + } } - @include hover { @content } } @mixin hover-focus-active { - &:focus, - &:active { - @content + @if $use-hover-media-query { + &:focus, + &:active { + @content + } + @include hover { @content } + } + @else { + &:focus, + &:active, + &:hover { + @content + } } - @include hover { @content } } From 175714d2465acc385d234fd8c9f3d5a84a286ded Mon Sep 17 00:00:00 2001 From: Chris Rebert Date: Wed, 21 Jan 2015 13:12:49 -0800 Subject: [PATCH 4/4] add docs for mq4-hover-hover-shim integration --- docs/getting-started/support.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/getting-started/support.md b/docs/getting-started/support.md index 63667fe85d..6ed11c5e20 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