aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Otto <[email protected]>2014-12-31 10:39:56 -0800
committerMark Otto <[email protected]>2014-12-31 10:39:56 -0800
commit1a932b7e02ccb091a6e99e74039f3ea949ce459e (patch)
tree66b7012e97657bc5ad5542e59ded8f0064eb36e3
parenta5e127fd168f33c087b645afb456c27c7da2bb6d (diff)
parentb9de4b739200537307112fdc59512a867a3f3774 (diff)
downloadbootstrap-1a932b7e02ccb091a6e99e74039f3ea949ce459e.tar.xz
bootstrap-1a932b7e02ccb091a6e99e74039f3ea949ce459e.zip
Merge branch 'v4' of https://github.com/twbs/derpstrap into v4
-rw-r--r--.gitignore8
-rw-r--r--.travis.yml12
-rw-r--r--Gemfile7
-rw-r--r--Gemfile.lock78
-rw-r--r--Gruntfile.js43
-rw-r--r--dist/css/bootstrap.css118
-rw-r--r--docs/_includes/js/popovers.html20
-rw-r--r--docs/_includes/js/tooltips.html8
-rw-r--r--docs/assets/js/src/application.js1
-rw-r--r--docs/components/card.md2
-rw-r--r--docs/content/tables.md2
-rw-r--r--docs/examples/album/index.html2
-rw-r--r--docs/examples/navbar-top/index.html2
-rw-r--r--docs/examples/navbar/index.html2
-rw-r--r--docs/getting-started/compiling.md18
-rw-r--r--docs/getting-started/quick-start.md2
-rw-r--r--docs/getting-started/third-party-support.md6
-rw-r--r--docs/index.html4
-rw-r--r--docs/javascript/alerts.md2
-rw-r--r--docs/javascript/carousel.md4
-rw-r--r--docs/javascript/overview.md2
-rw-r--r--docs/javascript/popovers.md20
-rw-r--r--grunt/bs-sass-compile/libsass.js26
-rw-r--r--grunt/bs-sass-compile/sass.js30
-rw-r--r--js/.jscsrc1
-rw-r--r--js/popover.js6
-rw-r--r--js/tests/unit/popover.js2
-rw-r--r--js/tests/unit/tooltip.js24
-rw-r--r--js/tooltip.js10
-rw-r--r--package.json17
-rw-r--r--scss/_alert.scss23
-rw-r--r--scss/_forms.scss4
-rw-r--r--scss/_grid.scss57
-rw-r--r--scss/_mixins.scss2
-rw-r--r--scss/_modal.scss4
-rw-r--r--scss/_navbar.scss4
-rw-r--r--scss/_popover.scss116
-rw-r--r--scss/_tooltip.scss120
-rw-r--r--scss/_type.scss2
-rw-r--r--scss/_utilities.scss5
-rw-r--r--scss/_variables.scss50
-rw-r--r--scss/mixins/_breakpoints.scss85
-rw-r--r--scss/mixins/_grid-framework.scss75
-rw-r--r--scss/mixins/_grid.scss27
-rw-r--r--scss/mixins/_media-queries.scss14
-rw-r--r--scss/mixins/_pulls.scss6
-rw-r--r--test-infra/S3Cachefile.json6
-rw-r--r--test-infra/gemfiles/core.gemfile7
-rw-r--r--test-infra/gemfiles/core.gemfile.lock15
49 files changed, 632 insertions, 469 deletions
diff --git a/.gitignore b/.gitignore
index d60e71a5f..042d47047 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,11 @@
# Ignore docs files
_gh_pages
_site
+
+# Ignore ruby files
.ruby-version
-Gemfile.lock
+.bundle
+vendor/cache
# Numerous always-ignore extensions
*.diff
@@ -41,6 +44,9 @@ validation-status.json
# SCSS-Lint
scss-lint-report.xml
+# grunt-contrib-sass cache
+.sass-cache
+
# Folders to ignore
bower_components
node_modules
diff --git a/.travis.yml b/.travis.yml
index 5899bbf0f..bb85115f6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,15 +15,12 @@ before_install:
install:
- npm install -g grunt-cli
- ./test-infra/s3_cache.py download npm-modules
- - if [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py download rubygems; fi
+ - if [ -n "$BUNDLE_GEMFILE" ]; then ./test-infra/s3_cache.py download rubygems; fi
after_script:
- if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ "$TWBS_TEST" = core ]; then ./test-infra/s3_cache.py upload npm-modules; fi
- - if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py upload rubygems; fi
+ - if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ -n "$BUNDLE_GEMFILE" ]; then ./test-infra/s3_cache.py upload rubygems; fi
env:
global:
- - JEKYLL_VERSION="2.5.1"
- - ROUGE_VERSION="1.7.2"
- - SCSS_LINT_VERSION="0.30.0"
- SAUCE_USERNAME="bootstrap"
- secure: "pJkBwnuae9dKU5tEcCqccfS1QQw7/meEcfz63fM7ba7QJNjoA6BaXj08L5Z3Vb5vBmVPwBawxo5Hp0jC0r/Z/O0hGnAmz/Cz09L+cy7dSAZ9x4hvZePSja/UAusaB5ogMoO8l2b773MzgQeSmrLbExr9BWLeqEfjC2hFgdgHLaQ="
- secure: "gqjqISbxBJK6byFbsmr1AyP1qoWH+rap06A2gI7v72+Tn2PU2nYkIMUkCvhZw6K889jv+LhQ/ybcBxDOXHpNCExCnSgB4dcnmYp+9oeNZb37jSP0rQ+Ib4OTLjzc3/FawE/fUq5kukZTC7porzc/k0qJNLAZRx3YLALmK1GIdUY="
@@ -35,8 +32,9 @@ env:
- secure: "PabpUdG2dE40hHUkMCdxk1e9Ak3BOo0h7Y5/uekosLKOz5N60Xmn/ooyrSkvicLthXO4cfONFhO3/xSVRKQOxlUw4on5i0VuNK+QSqxJk0IDaRSZnTCcC8J7083K0YL+FvMdGQwcYwMY9LiwS8aS014IRkSQjsa+mjo3owP+dOU="
- secure: "G4/f4PVyVi9o6UbZMqw9YFmDu7cHqe9iymiXYd1RcnPXwhWAePX12m0PWMhUj5itJ180PTEddVip8PNOgBdqyrDxEPKkcgAW2EElVAPIKJXVfvDW64UjQ0H7NS7XvF7iLQUJp/XfmR7NJ7tT393AQdh8SGmuQpJhgYbwIWbES/k="
matrix:
- - TWBS_TEST=core
- - TWBS_TEST=validate-html
+ - TWBS_TEST=core TWBS_SASS=libsass BUNDLE_GEMFILE=test-infra/gemfiles/core.gemfile
+ - TWBS_TEST=core TWBS_SASS=sass BUNDLE_GEMFILE=test-infra/gemfiles/core.gemfile
+ - TWBS_TEST=validate-html BUNDLE_GEMFILE=Gemfile
- TWBS_TEST=sauce-js-unit
matrix:
fast_finish: true
diff --git a/Gemfile b/Gemfile
index eb9646efe..23068bdfe 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,11 @@
+# Ruby Gems for building and testing Bootstrap
+# Run `grunt update-gemfile-lock` to update to the latest compatible versions
+
source 'https://rubygems.org'
-group :development do
+group :development, :test do
gem 'jekyll', '~> 2.5.2'
gem 'rouge', '~> 1.7.4'
+ gem 'sass', '~> 3.4.9'
+ gem 'scss-lint', '~> 0.31'
end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 000000000..725379399
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,78 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ blankslate (2.1.2.4)
+ celluloid (0.16.0)
+ timers (~> 4.0.0)
+ classifier-reborn (2.0.2)
+ fast-stemmer (~> 1.0)
+ coffee-script (2.3.0)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.8.0)
+ colorator (0.1)
+ execjs (2.2.2)
+ fast-stemmer (1.0.2)
+ ffi (1.9.6)
+ hitimes (1.2.2)
+ jekyll (2.5.2)
+ classifier-reborn (~> 2.0)
+ colorator (~> 0.1)
+ jekyll-coffeescript (~> 1.0)
+ jekyll-gist (~> 1.0)
+ jekyll-paginate (~> 1.0)
+ jekyll-sass-converter (~> 1.0)
+ jekyll-watch (~> 1.1)
+ kramdown (~> 1.3)
+ liquid (~> 2.6.1)
+ mercenary (~> 0.3.3)
+ pygments.rb (~> 0.6.0)
+ redcarpet (~> 3.1)
+ safe_yaml (~> 1.0)
+ toml (~> 0.1.0)
+ jekyll-coffeescript (1.0.1)
+ coffee-script (~> 2.2)
+ jekyll-gist (1.1.0)
+ jekyll-paginate (1.1.0)
+ jekyll-sass-converter (1.3.0)
+ sass (~> 3.2)
+ jekyll-watch (1.2.0)
+ listen (~> 2.7)
+ kramdown (1.5.0)
+ liquid (2.6.1)
+ listen (2.8.4)
+ celluloid (>= 0.15.2)
+ rb-fsevent (>= 0.9.3)
+ rb-inotify (>= 0.9)
+ mercenary (0.3.5)
+ parslet (1.5.0)
+ blankslate (~> 2.0)
+ posix-spawn (0.3.9)
+ pygments.rb (0.6.0)
+ posix-spawn (~> 0.3.6)
+ yajl-ruby (~> 1.1.0)
+ rainbow (2.0.0)
+ rb-fsevent (0.9.4)
+ rb-inotify (0.9.5)
+ ffi (>= 0.5.0)
+ redcarpet (3.2.2)
+ rouge (1.7.4)
+ safe_yaml (1.0.4)
+ sass (3.4.9)
+ scss-lint (0.31.0)
+ rainbow (~> 2.0)
+ sass (~> 3.4.1)
+ timers (4.0.1)
+ hitimes
+ toml (0.1.2)
+ parslet (~> 1.5.0)
+ yajl-ruby (1.1.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ jekyll (~> 2.5.2)
+ rouge (~> 1.7.4)
+ sass (~> 3.4.9)
+ scss-lint (~> 0.31)
diff --git a/Gruntfile.js b/Gruntfile.js
index d09e6f560..582f4ac30 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -17,6 +17,7 @@ module.exports = function (grunt) {
var fs = require('fs');
var path = require('path');
+ var glob = require('glob');
var npmShrinkwrap = require('npm-shrinkwrap');
var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js');
@@ -144,25 +145,6 @@ module.exports = function (grunt) {
files: 'js/tests/index.html'
},
- sass: {
- options: {
- includePaths: ['scss'],
- precision: 6,
- sourceComments: false,
- sourceMap: true
- },
- core: {
- files: {
- 'dist/css/<%= pkg.name %>.css': 'scss/<%= pkg.name %>.scss'
- }
- },
- docs: {
- files: {
- 'docs/assets/css/docs.min.css': 'docs/assets/scss/docs.scss'
- }
- }
- },
-
scsslint: {
scss: ['scss/*.scss', '!scss/_normalize.scss'],
options: {
@@ -342,13 +324,23 @@ module.exports = function (grunt) {
exec: {
npmUpdate: {
command: 'npm update'
+ },
+ bundleUpdate: {
+ command: function () {
+ // Update dev gems and all the test gemsets
+ return 'bundle update && ' + glob.sync('test-infra/gemfiles/*.gemfile').map(function (gemfile) {
+ return 'BUNDLE_GEMFILE=' + gemfile + ' bundle update';
+ }).join(' && ');
+ }
}
}
});
// These plugins provide necessary tasks.
- require('load-grunt-tasks')(grunt, { scope: 'devDependencies' });
+ require('load-grunt-tasks')(grunt, { scope: 'devDependencies',
+ // Exclude Sass compilers. We choose the one to load later on.
+ pattern: ['grunt-*', '!grunt-sass', '!grunt-contrib-sass'] });
require('time-grunt')(grunt);
// Docs HTML validation task
@@ -366,7 +358,8 @@ module.exports = function (grunt) {
// Skip core tests if running a different subset of the test suite
if (runSubset('core') &&
// Skip core tests if this is a Savage build
- process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'test-js', 'docs']);
+ process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') {
+ testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'test-js', 'docs']);
}
// Skip HTML validation if running a different subset of the test suite
if (runSubset('validate-html') &&
@@ -392,7 +385,12 @@ module.exports = function (grunt) {
grunt.registerTask('test-scss', ['scsslint:scss']);
// CSS distribution task.
+ // Supported Compilers: sass (Ruby) and libsass.
+ (function (sassCompilerName) {
+ require('./grunt/bs-sass-compile/' + sassCompilerName + '.js')(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']);
// Full distribution task.
@@ -435,4 +433,7 @@ module.exports = function (grunt) {
done();
});
});
+ // Task for updating the cached RubyGem packages used by the Travis build (which are controlled by test-infra/Gemfile.lock).
+ // This task should be run and the updated file should be committed whenever Bootstrap's RubyGem dependencies change.
+ grunt.registerTask('update-gemfile-lock', ['exec:bundleUpdate']);
};
diff --git a/dist/css/bootstrap.css b/dist/css/bootstrap.css
index fbb56e094..5045aa462 100644
--- a/dist/css/bootstrap.css
+++ b/dist/css/bootstrap.css
@@ -447,7 +447,7 @@ ul ul, ul ol, ol ul, ol ol {
margin-bottom: 0;
}
-.list-unstyled, .nav {
+.list-unstyled, .list-inline, .nav {
padding-left: 0;
list-style: none;
}
@@ -607,7 +607,7 @@ pre code {
}
@media (min-width: 34em) {
.container {
- max-width: 34em;
+ max-width: 34rem;
}
}
@media (min-width: 48em) {
@@ -620,6 +620,11 @@ pre code {
max-width: 60rem;
}
}
+@media (min-width: 75em) {
+ .container {
+ max-width: 72.25rem;
+ }
+}
.container-fluid {
padding-right: .75rem;
@@ -647,7 +652,7 @@ pre code {
clear: both;
}
-.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xl-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xl-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xl-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xl-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xl-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xl-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xl-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xl-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xl-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xl-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xl-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12, .col-xl-12 {
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12 {
position: relative;
min-height: 1px;
padding-right: .75rem;
@@ -1492,7 +1497,7 @@ pre code {
}
}
-@media (min-width: 62em) {
+@media (min-width: 75em) {
.col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12 {
float: left;
}
@@ -2725,7 +2730,7 @@ input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="butto
z-index: 990;
}
-.pull-right > .dropdown-menu, .navbar-right > .dropdown-menu {
+.pull-right > .dropdown-menu {
right: 0;
left: auto;
}
@@ -3485,7 +3490,12 @@ input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="butto
}
@media (min-width: 34em) {
+ .navbar-left {
+ float: left !important;
+ }
+
.navbar-right {
+ float: right !important;
margin-right: -1rem;
}
.navbar-right ~ .navbar-right {
@@ -3990,7 +4000,7 @@ a.label:hover, a.label:focus {
.badge:empty {
display: none;
}
-.badge.pull-left, .badge.navbar-left, .badge.pull-right, .badge.navbar-right {
+.badge.pull-left, .badge.pull-right {
top: .2em;
}
.list-group-item.active > .badge, .nav-pills > .active > a > .badge {
@@ -4322,11 +4332,11 @@ a.badge:hover, a.badge:focus {
display: block;
}
-.media-right, .media > .pull-right, .media > .navbar-right {
+.media-right, .media > .pull-right {
padding-left: 10px;
}
-.media-left, .media > .pull-left, .media > .navbar-left {
+.media-left, .media > .pull-left {
padding-right: 10px;
}
@@ -4705,19 +4715,23 @@ a.list-group-item-state.active, a.list-group-item-state.active:hover, a.list-gro
.tooltip.in {
opacity: .9;
}
-.tooltip.top {
+
+.tooltip-top {
padding: 5px 0;
margin-top: -3px;
}
-.tooltip.right {
+
+.tooltip-right {
padding: 0 5px;
margin-left: 3px;
}
-.tooltip.bottom {
+
+.tooltip-bottom {
padding: 5px 0;
margin-top: 3px;
}
-.tooltip.left {
+
+.tooltip-left {
padding: 0 5px;
margin-left: -3px;
}
@@ -4740,62 +4754,37 @@ a.list-group-item-state.active, a.list-group-item-state.active:hover, a.list-gro
border-style: solid;
}
-.tooltip.top .tooltip-arrow {
+.tooltip-top .tooltip-arrow {
bottom: 0;
left: 50%;
margin-left: -5px;
border-width: 5px 5px 0;
border-top-color: #000;
}
-.tooltip.top-left .tooltip-arrow {
- right: 5px;
- bottom: 0;
- margin-bottom: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000;
-}
-.tooltip.top-right .tooltip-arrow {
- bottom: 0;
- left: 5px;
- margin-bottom: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000;
-}
-.tooltip.right .tooltip-arrow {
+
+.tooltip-right .tooltip-arrow {
top: 50%;
left: 0;
margin-top: -5px;
border-width: 5px 5px 5px 0;
border-right-color: #000;
}
-.tooltip.left .tooltip-arrow {
+
+.tooltip-left .tooltip-arrow {
top: 50%;
right: 0;
margin-top: -5px;
border-width: 5px 0 5px 5px;
border-left-color: #000;
}
-.tooltip.bottom .tooltip-arrow {
+
+.tooltip-bottom .tooltip-arrow {
top: 0;
left: 50%;
margin-left: -5px;
border-width: 0 5px 5px;
border-bottom-color: #000;
}
-.tooltip.bottom-left .tooltip-arrow {
- top: 0;
- right: 5px;
- margin-top: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000;
-}
-.tooltip.bottom-right .tooltip-arrow {
- top: 0;
- left: 5px;
- margin-top: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000;
-}
.popover {
position: absolute;
@@ -4819,16 +4808,20 @@ a.list-group-item-state.active, a.list-group-item-state.active:hover, a.list-gro
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
}
-.popover.top {
+
+.popover-top {
margin-top: -10px;
}
-.popover.right {
+
+.popover-right {
margin-left: 10px;
}
-.popover.bottom {
+
+.popover-bottom {
margin-top: 10px;
}
-.popover.left {
+
+.popover-left {
margin-left: -10px;
}
@@ -4845,7 +4838,7 @@ a.list-group-item-state.active, a.list-group-item-state.active:hover, a.list-gro
padding: 9px 14px;
}
-.popover > .arrow, .popover > .arrow:after {
+.popover-arrow, .popover-arrow:after {
position: absolute;
display: block;
width: 0;
@@ -4854,65 +4847,68 @@ a.list-group-item-state.active, a.list-group-item-state.active:hover, a.list-gro
border-style: solid;
}
-.popover > .arrow {
+.popover-arrow {
border-width: 11px;
}
-.popover > .arrow:after {
+.popover-arrow:after {
content: "";
border-width: 10px;
}
-.popover.top > .arrow {
+.popover-top > .popover-arrow {
bottom: -11px;
left: 50%;
margin-left: -11px;
border-top-color: rgba(0, 0, 0, .25);
border-bottom-width: 0;
}
-.popover.top > .arrow:after {
+.popover-top > .popover-arrow:after {
bottom: 1px;
margin-left: -10px;
content: "";
border-top-color: #fff;
border-bottom-width: 0;
}
-.popover.right > .arrow {
+
+.popover-right > .popover-arrow {
top: 50%;
left: -11px;
margin-top: -11px;
border-right-color: rgba(0, 0, 0, .25);
border-left-width: 0;
}
-.popover.right > .arrow:after {
+.popover-right > .popover-arrow:after {
bottom: -10px;
left: 1px;
content: "";
border-right-color: #fff;
border-left-width: 0;
}
-.popover.bottom > .arrow {
+
+.popover-bottom > .popover-arrow {
top: -11px;
left: 50%;
margin-left: -11px;
border-top-width: 0;
border-bottom-color: rgba(0, 0, 0, .25);
}
-.popover.bottom > .arrow:after {
+.popover-bottom > .popover-arrow:after {
top: 1px;
margin-left: -10px;
content: "";
border-top-width: 0;
border-bottom-color: #fff;
}
-.popover.left > .arrow {
+
+.popover-left > .popover-arrow {
top: 50%;
right: -11px;
margin-top: -11px;
border-right-width: 0;
border-left-color: rgba(0, 0, 0, .25);
}
-.popover.left > .arrow:after {
+.popover-left > .popover-arrow:after {
right: 1px;
bottom: -10px;
content: "";
@@ -5139,11 +5135,11 @@ a.list-group-item-state.active, a.list-group-item-state.active:hover, a.list-gro
margin-left: auto;
}
-.pull-right, .navbar-right {
+.pull-right {
float: right !important;
}
-.pull-left, .navbar-left {
+.pull-left {
float: left !important;
}
diff --git a/docs/_includes/js/popovers.html b/docs/_includes/js/popovers.html
index ab33baccb..4557a44a4 100644
--- a/docs/_includes/js/popovers.html
+++ b/docs/_includes/js/popovers.html
@@ -39,24 +39,24 @@ $(function () {
<h3>Static popover</h3>
<p>Four options are available: top, right, bottom, and left aligned.</p>
<div class="bs-example bs-example-popover">
- <div class="popover top">
- <div class="arrow"></div>
+ <div class="popover popover-top">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover top</h3>
<div class="popover-content">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
</div>
</div>
- <div class="popover right">
- <div class="arrow"></div>
+ <div class="popover popover-right">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover right</h3>
<div class="popover-content">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
</div>
</div>
- <div class="popover bottom">
- <div class="arrow"></div>
+ <div class="popover popover-bottom">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover bottom</h3>
<div class="popover-content">
@@ -64,8 +64,8 @@ $(function () {
</div>
</div>
- <div class="popover left">
- <div class="arrow"></div>
+ <div class="popover popover-left">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover left</h3>
<div class="popover-content">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
@@ -207,12 +207,12 @@ sagittis lacus vel augue laoreet rutrum faucibus.">
<tr>
<td>template</td>
<td>string</td>
- <td><code>'&lt;div class="popover" role="tooltip"&gt;&lt;div class="arrow"&gt;&lt;/div&gt;&lt;h3 class="popover-title"&gt;&lt;/h3&gt;&lt;div class="popover-content"&gt;&lt;/div&gt;&lt;/div&gt;'</code></td>
+ <td><code>'&lt;div class="popover" role="tooltip"&gt;&lt;div class="popover-arrow"&gt;&lt;/div&gt;&lt;h3 class="popover-title"&gt;&lt;/h3&gt;&lt;div class="popover-content"&gt;&lt;/div&gt;&lt;/div&gt;'</code></td>
<td>
<p>Base HTML to use when creating the popover.</p>
<p>The popover's <code>title</code> will be injected into the <code>.popover-title</code>.</p>
<p>The popover's <code>content</code> will be injected into the <code>.popover-content</code>.</p>
- <p><code>.arrow</code> will become the popover's arrow.</p>
+ <p><code>.popover-arrow</code> will become the popover's arrow.</p>
<p>The outermost wrapper element should have the <code>.popover</code> class.</p>
</td>
</tr>
diff --git a/docs/_includes/js/tooltips.html b/docs/_includes/js/tooltips.html
index ae553e0df..b8293c9f5 100644
--- a/docs/_includes/js/tooltips.html
+++ b/docs/_includes/js/tooltips.html
@@ -12,25 +12,25 @@
<h3>Static tooltip</h3>
<p>Four options are available: top, right, bottom, and left aligned.</p>
<div class="bs-example bs-example-tooltip">
- <div class="tooltip left" role="tooltip">
+ <div class="tooltip tooltip-left" role="tooltip">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">
Tooltip on the left
</div>
</div>
- <div class="tooltip top" role="tooltip">
+ <div class="tooltip tooltip-top" role="tooltip">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">
Tooltip on the top
</div>
</div>
- <div class="tooltip bottom" role="tooltip">
+ <div class="tooltip tooltip-bottom" role="tooltip">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">
Tooltip on the bottom
</div>
</div>
- <div class="tooltip right" role="tooltip">
+ <div class="tooltip tooltip-right" role="tooltip">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">
Tooltip on the right
diff --git a/docs/assets/js/src/application.js b/docs/assets/js/src/application.js
index 9c1ec22c4..8dfb82651 100644
--- a/docs/assets/js/src/application.js
+++ b/docs/assets/js/src/application.js
@@ -10,6 +10,7 @@
*/
/* global ZeroClipboard */
+/* global SimpleJekyllSearch */
!function ($) {
'use strict';
diff --git a/docs/components/card.md b/docs/components/card.md
index 237588c55..7e7b4d8ee 100644
--- a/docs/components/card.md
+++ b/docs/components/card.md
@@ -21,7 +21,7 @@ Cards require very little markup, but do require some additional classes to give
### Text alignment
-You can quickly change the text alignment of any card—in it's entirety or specific parts—with our [text align classes]().
+You can quickly change the text alignment of any card—in its entirety or specific parts—with our [text align classes]().
{% example html %}
<div class="card">
diff --git a/docs/content/tables.md b/docs/content/tables.md
index 23e25a215..e4f69b068 100644
--- a/docs/content/tables.md
+++ b/docs/content/tables.md
@@ -3,7 +3,7 @@ layout: page
title: Tables
---
-Due to the widespread use of tables across plugins like calendars and date pickers, we've designed our tables to be **opt-in**. Just add the base class `.table` to any `<table>`.
+Due to the widespread use of tables across third-party widgets like calendars and date pickers, we've designed our tables to be **opt-in**. Just add the base class `.table` to any `<table>`.
## Basic example
diff --git a/docs/examples/album/index.html b/docs/examples/album/index.html
index 6a3c085a8..ac456377b 100644
--- a/docs/examples/album/index.html
+++ b/docs/examples/album/index.html
@@ -50,7 +50,7 @@
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Album example</h1>
- <p class="lead text-muted">Something short and leading about the collection below—it's contents, the creator, etc. Make it short and sweet, but not too short so folks don't simply skip over it entirely.</p>
+ <p class="lead text-muted">Something short and leading about the collection below—its contents, the creator, etc. Make it short and sweet, but not too short so folks don't simply skip over it entirely.</p>
<p>
<a href="#" class="btn btn-primary">Main call to action</a>
<a href="#" class="btn btn-secondary">Secondary action</a>
diff --git a/docs/examples/navbar-top/index.html b/docs/examples/navbar-top/index.html
index 334b8430a..f54f5eafd 100644
--- a/docs/examples/navbar-top/index.html
+++ b/docs/examples/navbar-top/index.html
@@ -37,7 +37,7 @@
<div class="container">
<div class="jumbotron">
<h1>Navbar example</h1>
- <p class="lead">This example is a quick exercise to illustrate how the top-aligned navbar works. As you scroll, this navbar remains in it's original position and moves with the rest of the page.</p>
+ <p class="lead">This example is a quick exercise to illustrate how the top-aligned navbar works. As you scroll, this navbar remains in its original position and moves with the rest of the page.</p>
<a class="btn btn-lg btn-primary" href="../../components/#navbar" role="button">View navbar docs &raquo;</a>
</div>
</div>
diff --git a/docs/examples/navbar/index.html b/docs/examples/navbar/index.html
index d6084e663..fde91fa8f 100644
--- a/docs/examples/navbar/index.html
+++ b/docs/examples/navbar/index.html
@@ -39,7 +39,7 @@
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>Navbar example</h1>
- <p>This example is a quick exercise to illustrate how the default navbar works. It's placed within a <code>.container</code> to limit it's width and will scroll with the rest of the page's content.</p>
+ <p>This example is a quick exercise to illustrate how the default navbar works. It's placed within a <code>.container</code> to limit its width and will scroll with the rest of the page's content.</p>
<p>
<a class="btn btn-lg btn-primary" href="../../components/#navbar" role="button">View navbar docs &raquo;</a>
</p>
diff --git a/docs/getting-started/compiling.md b/docs/getting-started/compiling.md
index 7a12becf7..38aa249d5 100644
--- a/docs/getting-started/compiling.md
+++ b/docs/getting-started/compiling.md
@@ -13,11 +13,15 @@ From the command line:
1. Install `grunt-cli` globally with `npm install -g grunt-cli`.
2. Navigate to the root `/bootstrap` directory, then run `npm install`. npm will look at [package.json](https://github.com/twbs/bootstrap/blob/master/package.json) and automatically install the necessary local dependencies listed there.
+3. [Install Ruby][install-ruby], install [Bundler][gembundler] with `gem install bundler`, and finally run `bundle`. This will install all Ruby dependencies, such as Jekyll and Sass linter.
When completed, you'll be able to run the various Grunt commands provided from the command line.
**Unfamiliar with npm? Don't have node installed?** That's a-okay. npm stands for [node packaged modules](http://npmjs.org/) and is a way to manage development dependencies through node.js. [Download and install node.js](http://nodejs.org/download/) before proceeding.
+[install-ruby]: https://www.ruby-lang.org/en/documentation/installation/
+[gembundler]: http://bundler.io/
+
### Available Grunt commands
#### Build - `grunt`
@@ -35,6 +39,20 @@ Builds and tests CSS, JavaScript, and other assets which are used when running t
#### Watch - `grunt watch`
This is a convenience method for watching just Sass files and automatically building them whenever you save.
+### Use another Sass compiler
+Bootstrap is compiled with [libsass][libsass] by default.
+Use another compiler by setting the `TWBS_SASS` environment variable to:
+
+* `sass` to use [Ruby Sass][ruby-sass] via [grunt-contrib-sass][grunt-contrib-sass].
+* `libsass` (default) to use [libsass][libsass] via [grunt-sass][grunt-sass].
+
+For example, run `TWBS_SASS=sass grunt` to test and build Bootstrap with Ruby Sass.
+
+[ruby-sass]: https://github.com/sass/sass
+[grunt-contrib-sass]: https://github.com/gruntjs/grunt-contrib-sass
+[libsass]: https://github.com/sass/libsass
+[grunt-sass]: https://github.com/sindresorhus/grunt-sass
+
### Troubleshooting dependencies
Should you encounter problems with installing dependencies or running Grunt commands, uninstall all previous dependency versions (global and local). Then, rerun `npm install`.
diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md
index 6b1e68220..8e2f6814d 100644
--- a/docs/getting-started/quick-start.md
+++ b/docs/getting-started/quick-start.md
@@ -22,7 +22,7 @@ Then, add the Bootstrap JavaScript—and jQuery—near the end of your pages. It
Be sure to have your pages set up with the latest design and development standards. That means:
* Using an HTML5 doctype
-* Forcing Internet Explorer to use it's latest rendering mode ([read more]())
+* Forcing Internet Explorer to use its latest rendering mode ([read more]())
* And, utilizing the viewport meta tag.
Put it all together and your pages should look like this:
diff --git a/docs/getting-started/third-party-support.md b/docs/getting-started/third-party-support.md
index c469b644e..ea22cf589 100644
--- a/docs/getting-started/third-party-support.md
+++ b/docs/getting-started/third-party-support.md
@@ -16,7 +16,7 @@ Depending on the context, you may override as-needed (Option 1) or reset the box
*
* Reset individual elements or override regions to avoid conflicts due to
* global box model settings of Bootstrap. Two options, individual overrides and
- * region resets, are available as plain CSS and uncompiled Less formats.
+ * region resets, are available as plain CSS and uncompiled Sass formats.
*/
/* Option 1A: Override a single element's box model via CSS */
@@ -26,7 +26,7 @@ Depending on the context, you may override as-needed (Option 1) or reset the box
box-sizing: content-box;
}
-/* Option 1B: Override a single element's box model by using a Bootstrap Less mixin */
+/* Option 1B: Override a single element's box model by using a Bootstrap Sass mixin */
.element {
.box-sizing(content-box);
}
@@ -41,7 +41,7 @@ Depending on the context, you may override as-needed (Option 1) or reset the box
box-sizing: content-box;
}
-/* Option 2B: Reset an entire region with a custom Less mixin */
+/* Option 2B: Reset an entire region with a custom Sass mixin */
.reset-box-sizing {
&,
*,
diff --git a/docs/index.html b/docs/index.html
index 2ebeb3ff9..d0ae59d72 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -25,9 +25,9 @@ title: Bootstrap &middot; The world's most popular mobile-first and responsive f
<div class="row">
<div class="col-sm-4">
- <img src="assets/img/sass-less.png" alt="Sass and Less support" class="img-responsive">
+ <img src="assets/img/sass-less.png" alt="Sass support" class="img-responsive">
<h3>Preprocessors</h3>
- <p>Bootstrap ships with vanilla CSS, but its source code utilizes the two most popular CSS preprocessors, <a href="../css/#less">Less</a> and <a href="../css/#sass">Sass</a>. Quickly get started with precompiled CSS or build on the source.</p>
+ <p>Bootstrap ships with vanilla CSS, but its source code utilizes <a href="../css/#sass">Sass</a>, a popular CSS preprocessor. Quickly get started with precompiled CSS or build on the source.</p>
</div>
<div class="col-sm-4">
<img src="assets/img/devices.png" alt="Responsive across devices" class="img-responsive">
diff --git a/docs/javascript/alerts.md b/docs/javascript/alerts.md
index bbe2eeab4..8d3df5d2f 100644
--- a/docs/javascript/alerts.md
+++ b/docs/javascript/alerts.md
@@ -22,7 +22,7 @@ When using a `.close` button, it must be the first child of the `.alert-dismissi
{% example html %}
<div class="alert alert-danger alert-dismissible fade in" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
- <h4>Oh snap! You got an error!</h4>
+ <h4 class="alert-heading">Oh snap! You got an error!</h4>
<p>Change this and that and try again. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum.</p>
<p>
<button type="button" class="btn btn-danger">Take this action</button>
diff --git a/docs/javascript/carousel.md b/docs/javascript/carousel.md
index dac8d00d1..d69725a59 100644
--- a/docs/javascript/carousel.md
+++ b/docs/javascript/carousel.md
@@ -37,8 +37,8 @@ A slideshow component for cycling through elements—images or slides of text—
{% endexample %}
<div class="bs-callout bs-callout-warning" id="callout-carousel-transitions">
- <h4>Transition animations not supported in Internet Explorer 8 &amp; 9</h4>
- <p>Bootstrap exclusively uses CSS3 for its animations, but Internet Explorer 8 &amp; 9 don't support the necessary CSS properties. Thus, there are no slide transition animations when using these browsers. We have intentionally decided not to include jQuery-based fallbacks for the transitions.</p>
+ <h4>Transition animations not supported in Internet Explorer 9</h4>
+ <p>Bootstrap exclusively uses CSS3 for its animations, but Internet Explorer 9 doesn't support the necessary CSS properties. Thus, there are no slide transition animations when using that browser. We have intentionally decided not to include jQuery-based fallbacks for the transitions.</p>
</div>
<div class="bs-callout bs-callout-warning" id="callout-carousel-active">
diff --git a/docs/javascript/overview.md b/docs/javascript/overview.md
index 8d22d4020..631ea519c 100644
--- a/docs/javascript/overview.md
+++ b/docs/javascript/overview.md
@@ -81,8 +81,6 @@ $.fn.bootstrapBtn = bootstrapButton // give $().bootstrapBtn the Boot
Bootstrap provides custom events for most plugins' unique actions. Generally, these come in an infinitive and past participle form - where the infinitive (ex. `show`) is triggered at the start of an event, and its past participle form (ex. `shown`) is triggered on the completion of an action.
-As of 3.0.0, all Bootstrap events are namespaced.
-
All infinitive events provide `preventDefault` functionality. This provides the ability to stop the execution of an action before it starts.
{% highlight js %}
diff --git a/docs/javascript/popovers.md b/docs/javascript/popovers.md
index 0844621ba..28cafb1b0 100644
--- a/docs/javascript/popovers.md
+++ b/docs/javascript/popovers.md
@@ -43,24 +43,24 @@ $(function () {
Four options are available: top, right, bottom, and left aligned.
<div class="bs-example bs-example-popover">
- <div class="popover top">
- <div class="arrow"></div>
+ <div class="popover popover-top">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover top</h3>
<div class="popover-content">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
</div>
</div>
- <div class="popover right">
- <div class="arrow"></div>
+ <div class="popover popover-right">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover right</h3>
<div class="popover-content">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
</div>
</div>
- <div class="popover bottom">
- <div class="arrow"></div>
+ <div class="popover popover-bottom">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover bottom</h3>
<div class="popover-content">
@@ -68,8 +68,8 @@ Four options are available: top, right, bottom, and left aligned.
</div>
</div>
- <div class="popover left">
- <div class="arrow"></div>
+ <div class="popover popover-left">
+ <div class="popover-arrow"></div>
<h3 class="popover-title">Popover left</h3>
<div class="popover-content">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
@@ -222,12 +222,12 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
<tr>
<td>template</td>
<td>string</td>
- <td><code>'&lt;div class="popover" role="tooltip"&gt;&lt;div class="arrow"&gt;&lt;/div&gt;&lt;h3 class="popover-title"&gt;&lt;/h3&gt;&lt;div class="popover-content"&gt;&lt;/div&gt;&lt;/div&gt;'</code></td>
+ <td><code>'&lt;div class="popover" role="tooltip"&gt;&lt;div class="popover-arrow"&gt;&lt;/div&gt;&lt;h3 class="popover-title"&gt;&lt;/h3&gt;&lt;div class="popover-content"&gt;&lt;/div&gt;&lt;/div&gt;'</code></td>
<td>
<p>Base HTML to use when creating the popover.</p>
<p>The popover's <code>title</code> will be injected into the <code>.popover-title</code>.</p>
<p>The popover's <code>content</code> will be injected into the <code>.popover-content</code>.</p>
- <p><code>.arrow</code> will become the popover's arrow.</p>
+ <p><code>.popover-arrow</code> will become the popover's arrow.</p>
<p>The outermost wrapper element should have the <code>.popover</code> class.</p>
</td>
</tr>
diff --git a/grunt/bs-sass-compile/libsass.js b/grunt/bs-sass-compile/libsass.js
new file mode 100644
index 000000000..e3d13a989
--- /dev/null
+++ b/grunt/bs-sass-compile/libsass.js
@@ -0,0 +1,26 @@
+// Compile Bootstrap with [libsass][1] using [grunt-sass][2]
+// [1]: https://github.com/sass/libsass
+// [2]: https://github.com/sindresorhus/grunt-sass
+module.exports = function configureLibsass(grunt) {
+ grunt.config.merge({
+ sass: {
+ options: {
+ includePaths: ['scss'],
+ precision: 6,
+ sourceComments: false,
+ sourceMap: true
+ },
+ core: {
+ files: {
+ 'dist/css/<%= pkg.name %>.css': 'scss/<%= pkg.name %>.scss'
+ }
+ },
+ docs: {
+ files: {
+ 'docs/assets/css/docs.min.css': 'docs/assets/scss/docs.scss'
+ }
+ }
+ }
+ });
+ grunt.loadNpmTasks('grunt-sass');
+};
diff --git a/grunt/bs-sass-compile/sass.js b/grunt/bs-sass-compile/sass.js
new file mode 100644
index 000000000..d7743515d
--- /dev/null
+++ b/grunt/bs-sass-compile/sass.js
@@ -0,0 +1,30 @@
+// Compile Bootstrap with [Ruby Sass][1] using [grunt-contrib-sass][2]
+// [1]: https://github.com/sass/sass
+// [2]: https://github.com/gruntjs/grunt-contrib-sass
+module.exports = function configureRubySass(grunt) {
+ var options = {
+ loadPath: ['scss'],
+ precision: 6,
+ sourcemap: 'auto',
+ style: 'expanded',
+ trace: true,
+ bundleExec: true
+ };
+ grunt.config.merge({
+ sass: {
+ core: {
+ options: options,
+ files: {
+ 'dist/css/<%= pkg.name %>.css': 'scss/<%= pkg.name %>.scss'
+ }
+ },
+ docs: {
+ options: options,
+ files: {
+ 'docs/assets/css/docs.min.css': 'docs/assets/scss/docs.scss'
+ }
+ }
+ }
+ });
+ grunt.loadNpmTasks('grunt-contrib-sass');
+};
diff --git a/js/.jscsrc b/js/.jscsrc
index 9612c1683..ac1d73f55 100644
--- a/js/.jscsrc
+++ b/js/.jscsrc
@@ -22,6 +22,7 @@
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"requireSpaceAfterLineComment": true,
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="],
+ "requireSpaceBetweenArguments": true,
"requireSpacesInAnonymousFunctionExpression": { "beforeOpeningCurlyBrace": true, "beforeOpeningRoundBrace": true },
"requireSpacesInConditionalExpression": true,
"requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
diff --git a/js/popover.js b/js/popover.js
index db272bdee..085584fe8 100644
--- a/js/popover.js
+++ b/js/popover.js
@@ -25,7 +25,7 @@
placement: 'right',
trigger: 'click',
content: '',
- template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})
@@ -50,7 +50,7 @@
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
](content)
- $tip.removeClass('fade top bottom left right in')
+ $tip.removeClass('fade popover-top popover-bottom popover-left popover-right in')
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
// this manually by checking the contents.
@@ -72,7 +72,7 @@
}
Popover.prototype.arrow = function () {
- return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+ return (this.$arrow = this.$arrow || this.tip().find('.popover-arrow'))
}
Popover.prototype.tip = function () {
diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js
index 466ebace2..8f59d3483 100644
--- a/js/tests/unit/popover.js
+++ b/js/tests/unit/popover.js
@@ -141,7 +141,7 @@ $(function () {
.bootstrapPopover({
title: 'Test',
content: 'Test',
- template: '<div class="popover foobar"><div class="arrow"></div><div class="inner"><h3 class="title"/><div class="content"><p/></div></div></div>'
+ template: '<div class="popover foobar"><div class="popover-arrow"></div><div class="inner"><h3 class="title"/><div class="content"><p/></div></div></div>'
})
$popover.bootstrapPopover('show')
diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js
index eb578c22a..6232ccdcb 100644
--- a/js/tests/unit/tooltip.js
+++ b/js/tests/unit/tooltip.js
@@ -85,7 +85,7 @@ $(function () {
.bootstrapTooltip({ placement: 'bottom' })
$tooltip.bootstrapTooltip('show')
- ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
+ ok($('.tooltip').is('.fade.tooltip-bottom.in'), 'has correct classes applied')
$tooltip.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed')
@@ -300,8 +300,8 @@ $(function () {
test('should add position class before positioning so that position-specific styles are taken into account', function () {
var styles = '<style>'
- + '.tooltip.right { white-space: nowrap; }'
- + '.tooltip.right .tooltip-inner { max-width: none; }'
+ + '.tooltip.tooltip-right { white-space: nowrap; }'
+ + '.tooltip.tooltip-right .tooltip-inner { max-width: none; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
@@ -384,7 +384,7 @@ $(function () {
.bootstrapTooltip({ placement: 'auto' })
$topTooltip.bootstrapTooltip('show')
- ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned to bottom')
+ ok($('.tooltip').is('.tooltip-bottom'), 'top positioned tooltip is dynamically positioned to bottom')
$topTooltip.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'top positioned tooltip removed from dom')
@@ -394,7 +394,7 @@ $(function () {
.bootstrapTooltip({ placement: 'right auto' })
$rightTooltip.bootstrapTooltip('show')
- ok($('.tooltip').is('.left'), 'right positioned tooltip is dynamically positioned left')
+ ok($('.tooltip').is('.tooltip-left'), 'right positioned tooltip is dynamically positioned left')
$rightTooltip.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'right positioned tooltip removed from dom')
@@ -404,7 +404,7 @@ $(function () {
.bootstrapTooltip({ placement: 'auto left' })
$leftTooltip.bootstrapTooltip('show')
- ok($('.tooltip').is('.right'), 'left positioned tooltip is dynamically positioned right')
+ ok($('.tooltip').is('.tooltip-right'), 'left positioned tooltip is dynamically positioned right')
$leftTooltip.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'left positioned tooltip removed from dom')
@@ -430,7 +430,7 @@ $(function () {
})
$target.bootstrapTooltip('show')
- ok($('.tooltip').is('.top'), 'top positioned tooltip is dynamically positioned to top')
+ ok($('.tooltip').is('.tooltip-top'), 'top positioned tooltip is dynamically positioned to top')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
@@ -455,7 +455,7 @@ $(function () {
})
$target.bootstrapTooltip('show')
- ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned to bottom')
+ ok($('.tooltip').is('.tooltip-bottom'), 'top positioned tooltip is dynamically positioned to bottom')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
@@ -481,7 +481,7 @@ $(function () {
$('#scrollable-div').scrollTop(100)
$target.bootstrapTooltip('show')
- ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
+ ok($('.tooltip').is('.fade.tooltip-top.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
@@ -507,7 +507,7 @@ $(function () {
$('#scrollable-div').scrollTop(200)
$target.bootstrapTooltip('show')
- ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
+ ok($('.tooltip').is('.fade.tooltip-bottom.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
@@ -537,7 +537,7 @@ $(function () {
$('#scrollable-div').scrollTop(200)
$target.bootstrapTooltip('show')
- ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
+ ok($('.tooltip').is('.fade.tooltip-bottom.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
@@ -563,7 +563,7 @@ $(function () {
$('#scrollable-div').scrollTop(400)
$target.bootstrapTooltip('show')
- ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
+ ok($('.tooltip').is('.fade.tooltip-top.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
diff --git a/js/tooltip.js b/js/tooltip.js
index bd376f772..9d3074cc0 100644
--- a/js/tooltip.js
+++ b/js/tooltip.js
@@ -177,7 +177,7 @@
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
- .addClass(placement)
+ .addClass(this.type + '-' + placement)
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
@@ -187,7 +187,7 @@
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
- var orgPlacement = placement
+ var origPlacement = placement
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
@@ -198,8 +198,8 @@
placement
$tip
- .removeClass(orgPlacement)
- .addClass(placement)
+ .removeClass(this.type + '-' + origPlacement)
+ .addClass(this.type + '-' + placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
@@ -283,7 +283,7 @@
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
- $tip.removeClass('fade in top bottom left right')
+ $tip.removeClass('fade in tooltip-top tooltip-bottom tooltip-left tooltip-right')
}
Tooltip.prototype.hide = function (callback) {
diff --git a/package.json b/package.json
index 049eec999..ef03659e8 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
},
"devDependencies": {
"btoa": "~1.1.2",
- "glob": "~4.2.1",
+ "glob": "~4.3.1",
"grunt": "~0.4.5",
"grunt-autoprefixer": "~2.0.0",
"grunt-banner": "~0.2.3",
@@ -42,23 +42,24 @@
"grunt-contrib-copy": "~0.7.0",
"grunt-contrib-csslint": "~0.3.1",
"grunt-contrib-cssmin": "~0.10.0",
- "grunt-contrib-jade": "~0.13.0",
+ "grunt-contrib-jade": "~0.14.0",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-qunit": "~0.5.2",
- "grunt-contrib-uglify": "~0.6.0",
+ "grunt-contrib-sass": "^0.8.1",
+ "grunt-contrib-uglify": "~0.7.0",
"grunt-contrib-watch": "~0.6.1",
"grunt-csscomb": "~3.0.0",
"grunt-exec": "~0.4.6",
"grunt-html-validation": "~0.1.18",
"grunt-jekyll": "~0.4.2",
- "grunt-jscs": "~1.0.0",
+ "grunt-jscs": "~1.1.0",
"grunt-sass": "~0.17.0",
- "grunt-saucelabs": "~8.3.3",
+ "grunt-saucelabs": "~8.4.0",
"grunt-scss-lint": "^0.3.4",
"grunt-sed": "~0.1.1",
- "load-grunt-tasks": "~1.0.0",
- "npm-shrinkwrap": "5.0.0",
- "remarkable": "~1.4.2",
+ "load-grunt-tasks": "~2.0.0",
+ "npm-shrinkwrap": "^200.0.0",
+ "remarkable": "~1.6.0",
"time-grunt": "~1.0.0"
},
"engines": {
diff --git a/scss/_alert.scss b/scss/_alert.scss
index 685ca314b..8ec7d0662 100644
--- a/scss/_alert.scss
+++ b/scss/_alert.scss
@@ -12,17 +12,6 @@
border: 1px solid transparent;
@include border-radius($alert-border-radius);
- // Headings for larger alerts
- h4 {
- margin-top: 0;
- // Specified for the h4 to prevent conflicts of changing $headings-color
- color: inherit;
- }
- // Provide class for links that match alerts
- .alert-link {
- font-weight: $alert-link-font-weight;
- }
-
// Improve alignment and spacing of inner content
> p,
> ul {
@@ -33,6 +22,18 @@
}
}
+// Headings for larger alerts
+.alert-heading {
+ margin-top: 0;
+ // Specified to prevent conflicts of changing $headings-color
+ color: inherit;
+}
+
+// Provide class for links that match alerts
+.alert-link {
+ font-weight: $alert-link-font-weight;
+}
+
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
diff --git a/scss/_forms.scss b/scss/_forms.scss
index 67a4f8020..2d9867d32 100644
--- a/scss/_forms.scss
+++ b/scss/_forms.scss
@@ -540,14 +540,14 @@ input[type="checkbox"] {
// Quick utility class for applying `.input-lg` and `.input-sm` styles to the
// inputs and labels within a `.form-group`.
.form-group-lg {
- @media (min-width: $screen-sm-min) {
+ @include media-sm {
.control-label {
padding-top: $padding-lg-vertical;
}
}
}
.form-group-sm {
- @media (min-width: $screen-sm-min) {
+ @include media-sm {
.control-label {
padding-top: ($padding-sm-vertical + .1);
}
diff --git a/scss/_grid.scss b/scss/_grid.scss
index 6374d77de..1129cff6d 100644
--- a/scss/_grid.scss
+++ b/scss/_grid.scss
@@ -10,14 +10,11 @@
.container {
@include make-container();
- @media (min-width: $screen-sm-min) {
- max-width: $container-sm;
- }
- @media (min-width: $screen-md-min) {
- max-width: $container-md;
- }
- @media (min-width: $screen-lg-min) {
- max-width: $container-lg;
+ // For each breakpoint, define the maximum width of the container in a media query
+ @each $breakpoint, $container-max-width in $container-max-widths {
+ @include media-breakpoint-min($breakpoint) {
+ max-width: $container-max-width;
+ }
}
}
@@ -47,47 +44,3 @@
@include make-grid-columns();
-
-// Extra small grid
-//
-// Columns, offsets, pushes, and pulls for extra small devices like
-// smartphones.
-
-@include make-grid(xs);
-
-
-// Small grid
-//
-// Columns, offsets, pushes, and pulls for the small device range, from phones
-// to tablets.
-
-@include media-sm {
- @include make-grid(sm);
-}
-
-
-// Medium grid
-//
-// Columns, offsets, pushes, and pulls for the desktop device range.
-
-@include media-md {
- @include make-grid(md);
-}
-
-
-// Large grid
-//
-// Columns, offsets, pushes, and pulls for the large desktop device range.
-
-@include media-lg {
- @include make-grid(lg);
-}
-
-
-// Large grid
-//
-// Columns, offsets, pushes, and pulls for the large desktop device range.
-
-@include media-lg {
- @include make-grid(xl);
-}
diff --git a/scss/_mixins.scss b/scss/_mixins.scss
index d9f0e7a4b..801b5c7e9 100644
--- a/scss/_mixins.scss
+++ b/scss/_mixins.scss
@@ -24,6 +24,7 @@
}
// Utilities
+@import "mixins/breakpoints";
@import "mixins/media-queries";
@import "mixins/hide-text";
@import "mixins/image";
@@ -57,3 +58,4 @@
// @import "mixins/navbar-align";
@import "mixins/grid-framework";
@import "mixins/grid";
+@import "mixins/pulls";
diff --git a/scss/_modal.scss b/scss/_modal.scss
index 8fb7d201d..2566c3ef2 100644
--- a/scss/_modal.scss
+++ b/scss/_modal.scss
@@ -126,7 +126,7 @@
}
// Scale up the modal
-@media (min-width: $screen-sm-min) {
+@include media-sm {
// Automatically set modal's width for larger viewports
.modal-dialog {
width: $modal-md;
@@ -140,6 +140,6 @@
.modal-sm { width: $modal-sm; }
}
-@media (min-width: $screen-md-min) {
+@include media-md {
.modal-lg { width: $modal-lg; }
}
diff --git a/scss/_navbar.scss b/scss/_navbar.scss
index d4dcb673f..b163dad9c 100644
--- a/scss/_navbar.scss
+++ b/scss/_navbar.scss
@@ -199,10 +199,10 @@
@include media-sm {
.navbar-left {
- @extend .pull-left;
+ @include pull-left();
}
.navbar-right {
- @extend .pull-right;
+ @include pull-right();
margin-right: -$navbar-padding-horizontal;
~ .navbar-right {
diff --git a/scss/_popover.scss b/scss/_popover.scss
index 63928a4fc..a614518c7 100644
--- a/scss/_popover.scss
+++ b/scss/_popover.scss
@@ -24,14 +24,14 @@
border: 1px solid $popover-border-color;
@include border-radius($border-radius-lg);
@include box-shadow(0 5px 10px rgba(0,0,0,.2));
-
- // Offset the popover to account for the popover arrow
- &.top { margin-top: -$popover-arrow-width; }
- &.right { margin-left: $popover-arrow-width; }
- &.bottom { margin-top: $popover-arrow-width; }
- &.left { margin-left: -$popover-arrow-width; }
}
+// Offset the popover to account for the popover arrow
+.popover-top { margin-top: -$popover-arrow-width; }
+.popover-right { margin-left: $popover-arrow-width; }
+.popover-bottom { margin-top: $popover-arrow-width; }
+.popover-left { margin-left: -$popover-arrow-width; }
+
.popover-title {
padding: 8px 14px;
margin: 0; // reset heading margin
@@ -47,9 +47,9 @@
// Arrows
//
-// .arrow is outer, .arrow:after is inner
+// .popover-arrow is outer, .popover-arrow:after is inner
-.popover > .arrow {
+.popover-arrow {
&,
&:after {
position: absolute;
@@ -60,70 +60,68 @@
border-style: solid;
}
}
-.popover > .arrow {
+.popover-arrow {
border-width: $popover-arrow-outer-width;
}
-.popover > .arrow:after {
+.popover-arrow:after {
content: "";
border-width: $popover-arrow-width;
}
-.popover {
- &.top > .arrow {
- bottom: -$popover-arrow-outer-width;
- left: 50%;
- margin-left: -$popover-arrow-outer-width;
- border-top-color: $popover-arrow-outer-color;
+.popover-top > .popover-arrow {
+ bottom: -$popover-arrow-outer-width;
+ left: 50%;
+ margin-left: -$popover-arrow-outer-width;
+ border-top-color: $popover-arrow-outer-color;
+ border-bottom-width: 0;
+ &:after {
+ bottom: 1px;
+ margin-left: -$popover-arrow-width;
+ content: "";
+ border-top-color: $popover-arrow-color;
border-bottom-width: 0;
- &:after {
- bottom: 1px;
- margin-left: -$popover-arrow-width;
- content: "";
- border-top-color: $popover-arrow-color;
- border-bottom-width: 0;
- }
}
- &.right > .arrow {
- top: 50%;
- left: -$popover-arrow-outer-width;
- margin-top: -$popover-arrow-outer-width;
- border-right-color: $popover-arrow-outer-color;
+}
+.popover-right > .popover-arrow {
+ top: 50%;
+ left: -$popover-arrow-outer-width;
+ margin-top: -$popover-arrow-outer-width;
+ border-right-color: $popover-arrow-outer-color;
+ border-left-width: 0;
+ &:after {
+ bottom: -$popover-arrow-width;
+ left: 1px;
+ content: "";
+ border-right-color: $popover-arrow-color;
border-left-width: 0;
- &:after {
- bottom: -$popover-arrow-width;
- left: 1px;
- content: "";
- border-right-color: $popover-arrow-color;
- border-left-width: 0;
- }
}
- &.bottom > .arrow {
- top: -$popover-arrow-outer-width;
- left: 50%;
- margin-left: -$popover-arrow-outer-width;
+}
+.popover-bottom > .popover-arrow {
+ top: -$popover-arrow-outer-width;
+ left: 50%;
+ margin-left: -$popover-arrow-outer-width;
+ border-top-width: 0;
+ border-bottom-color: $popover-arrow-outer-color;
+ &:after {
+ top: 1px;
+ margin-left: -$popover-arrow-width;
+ content: "";
border-top-width: 0;
- border-bottom-color: $popover-arrow-outer-color;
- &:after {
- top: 1px;
- margin-left: -$popover-arrow-width;
- content: "";
- border-top-width: 0;
- border-bottom-color: $popover-arrow-color;
- }
+ border-bottom-color: $popover-arrow-color;
}
+}
- &.left > .arrow {
- top: 50%;
- right: -$popover-arrow-outer-width;
- margin-top: -$popover-arrow-outer-width;
+.popover-left > .popover-arrow {
+ top: 50%;
+ right: -$popover-arrow-outer-width;
+ margin-top: -$popover-arrow-outer-width;
+ border-right-width: 0;
+ border-left-color: $popover-arrow-outer-color;
+ &:after {
+ right: 1px;
+ bottom: -$popover-arrow-width;
+ content: "";
border-right-width: 0;
- border-left-color: $popover-arrow-outer-color;
- &:after {
- right: 1px;
- bottom: -$popover-arrow-width;
- content: "";
- border-right-width: 0;
- border-left-color: $popover-arrow-color;
- }
+ border-left-color: $popover-arrow-color;
}
}
diff --git a/scss/_tooltip.scss b/scss/_tooltip.scss
index 033c19f3b..49af2b288 100644
--- a/scss/_tooltip.scss
+++ b/scss/_tooltip.scss
@@ -17,26 +17,23 @@
opacity: 0;
&.in { opacity: $tooltip-opacity; }
+}
- &.top {
- padding: $tooltip-arrow-width 0;
- margin-top: -3px;
- }
-
- &.right {
- padding: 0 $tooltip-arrow-width;
- margin-left: 3px;
- }
-
- &.bottom {
- padding: $tooltip-arrow-width 0;
- margin-top: 3px;
- }
-
- &.left {
- padding: 0 $tooltip-arrow-width;
- margin-left: -3px;
- }
+.tooltip-top {
+ padding: $tooltip-arrow-width 0;
+ margin-top: -3px;
+}
+.tooltip-right {
+ padding: 0 $tooltip-arrow-width;
+ margin-left: 3px;
+}
+.tooltip-bottom {
+ padding: $tooltip-arrow-width 0;
+ margin-top: 3px;
+}
+.tooltip-left {
+ padding: 0 $tooltip-arrow-width;
+ margin-left: -3px;
}
// Wrapper for the tooltip content
@@ -58,62 +55,31 @@
border-color: transparent;
border-style: solid;
}
-// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1
-.tooltip {
- &.top .tooltip-arrow {
- bottom: 0;
- left: 50%;
- margin-left: -$tooltip-arrow-width;
- border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
- border-top-color: $tooltip-arrow-color;
- }
- &.top-left .tooltip-arrow {
- right: $tooltip-arrow-width;
- bottom: 0;
- margin-bottom: -$tooltip-arrow-width;
- border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
- border-top-color: $tooltip-arrow-color;
- }
- &.top-right .tooltip-arrow {
- bottom: 0;
- left: $tooltip-arrow-width;
- margin-bottom: -$tooltip-arrow-width;
- border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
- border-top-color: $tooltip-arrow-color;
- }
- &.right .tooltip-arrow {
- top: 50%;
- left: 0;
- margin-top: -$tooltip-arrow-width;
- border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0;
- border-right-color: $tooltip-arrow-color;
- }
- &.left .tooltip-arrow {
- top: 50%;
- right: 0;
- margin-top: -$tooltip-arrow-width;
- border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width;
- border-left-color: $tooltip-arrow-color;
- }
- &.bottom .tooltip-arrow {
- top: 0;
- left: 50%;
- margin-left: -$tooltip-arrow-width;
- border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
- border-bottom-color: $tooltip-arrow-color;
- }
- &.bottom-left .tooltip-arrow {
- top: 0;
- right: $tooltip-arrow-width;
- margin-top: -$tooltip-arrow-width;
- border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
- border-bottom-color: $tooltip-arrow-color;
- }
- &.bottom-right .tooltip-arrow {
- top: 0;
- left: $tooltip-arrow-width;
- margin-top: -$tooltip-arrow-width;
- border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
- border-bottom-color: $tooltip-arrow-color;
- }
+.tooltip-top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -$tooltip-arrow-width;
+ border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
+ border-top-color: $tooltip-arrow-color;
+}
+.tooltip-right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -$tooltip-arrow-width;
+ border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0;
+ border-right-color: $tooltip-arrow-color;
+}
+.tooltip-left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -$tooltip-arrow-width;
+ border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width;
+ border-left-color: $tooltip-arrow-color;
+}
+.tooltip-bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -$tooltip-arrow-width;
+ border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
+ border-bottom-color: $tooltip-arrow-color;
}
diff --git a/scss/_type.scss b/scss/_type.scss
index 395417324..5bbbf5873 100644
--- a/scss/_type.scss
+++ b/scss/_type.scss
@@ -116,7 +116,7 @@ ol {
// Inline turns list items into inline-block
.list-inline {
- @extend list-unstyled();
+ @extend .list-unstyled;
margin-left: -5px;
> li {
diff --git a/scss/_utilities.scss b/scss/_utilities.scss
index aeffdcd78..5e297fc75 100644
--- a/scss/_utilities.scss
+++ b/scss/_utilities.scss
@@ -10,11 +10,12 @@
.center-block {
@include center-block();
}
+
.pull-right {
- float: right !important;
+ @include pull-right();
}
.pull-left {
- float: left !important;
+ @include pull-left();
}
diff --git a/scss/_variables.scss b/scss/_variables.scss
index 242711314..4b515d3a4 100644
--- a/scss/_variables.scss
+++ b/scss/_variables.scss
@@ -272,29 +272,22 @@ $zindex-modal: 1040 !default;
//
//## Define the minimum and maximum dimensions at which your layout will change, adapting to different screen sizes.
-// Extra large screen / wide desktop
-$screen-xl-min: 75em !default;
-
-// Large screen / desktop
-$screen-lg-max: ($screen-xl-min - .1) !default;
-$screen-lg-min: 62em !default;
-
-// Medium screen / tablet
-$screen-md-max: ($screen-lg-min - .1) !default;
-$screen-md-min: 48em !default;
-
-// Small screen / phone
-$screen-sm-max: ($screen-md-min - .1) !default;
-$screen-sm-min: 34em !default;
-
-// Extra small screen / phone
-$screen-xs-max: ($screen-sm-min - .1) !default;
-
-
//== Grid system
//
//## Define your custom responsive grid.
-$grid-breakpoints: (xs sm md lg xl);
+$grid-breakpoints: (
+ // Extra small screen / phone
+ xs: 0,
+ // Small screen / phone
+ sm: 34em,
+ // Medium screen / tablet
+ md: 48em,
+ // Large screen / desktop
+ lg: 62em,
+ // Extra large screen / wide desktop
+ xl: 75em
+) !default;
+
//** Number of columns in the grid.
$grid-columns: 12 !default;
//** Padding between columns. Gets divided in half for the left and right.
@@ -305,17 +298,12 @@ $grid-gutter-width: 1.5rem !default;
//
//## Define the maximum width of `.container` for different screen sizes.
-//** For `$screen-xs-min` and up.
-$container-sm: 34em !default; // 480
-
-//** For `$screen-sm-min` and up.
-$container-md: 45rem !default; // 720
-
-//** For `$screen-md-min` and up.
-$container-lg: 60rem !default; // 960
-
-//** For `$screen-lg-min` and up.
-$container-xl: 72.25rem !default; // 1140
+$container-max-widths: (
+ sm: 34rem, // 480
+ md: 45rem, // 720
+ lg: 60rem, // 960
+ xl: 72.25rem // 1140
+) !default;
//== Navbar
diff --git a/scss/mixins/_breakpoints.scss b/scss/mixins/_breakpoints.scss
new file mode 100644
index 000000000..71a15cd04
--- /dev/null
+++ b/scss/mixins/_breakpoints.scss
@@ -0,0 +1,85 @@
+// Breakpoint viewport sizes and media queries.
+//
+// Breakpoints are defined as a map of (name: minimum width), order from small to large:
+//
+// (xs: 0, sm: 34rem, md: 45rem)
+//
+// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
+
+// Name of the next breakpoint, or null for the last breakpoint.
+//
+// >> breakpoint-next(sm)
+// md
+// >> breakpoint-next(sm, $breakpoints: (xs: 0, sm: 34rem, md: 45rem))
+// md
+// >> breakpoint-next(sm, $breakpoint-names: (xs sm md))
+// md
+@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
+ $n: index($breakpoint-names, $name);
+ @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
+}
+
+// Minimum breakpoint width. Null for the smallest (first) breakpoint.
+//
+// >> breakpoint-min(sm, (xs: 0, sm: 34rem, md: 45rem))
+// 34rem
+@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
+ $min: map-get($breakpoints, $name);
+ @return if($min != 0, $min, null);
+}
+
+// Maximum breakpoint width. Null for the largest (last) breakpoint.
+// The maximum value is calculated as the minimum of the next one less 0.1.
+//
+// >> breakpoint-max(sm, (xs: 0, sm: 34rem, md: 45rem))
+// 44.9rem
+@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
+ $next: breakpoint-next($name, $breakpoints);
+ @return if($next, breakpoint-min($next, $breakpoints) - 0.1, null);
+}
+
+// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
+@mixin media-breakpoint-min($name, $breakpoints: $grid-breakpoints) {
+ $min: breakpoint-min($name, $breakpoints);
+ @if $min {
+ @media (min-width: $min) {
+ @content;
+ }
+ } @else {
+ @content;
+ }
+}
+
+// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
+@mixin media-breakpoint-max($name, $breakpoints: $grid-breakpoints) {
+ $max: breakpoint-max($name, $breakpoints);
+ @if $max {
+ @media (max-width: $max) {
+ @content;
+ }
+ } @else {
+ @content;
+ }
+}
+
+// Media between the breakpoint's minimum and maximum widths.
+// No minimum for the smallest breakpoint, and no maximum for the largest one.
+@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
+ // Nested media query combination does not work in libsass yet
+ // https://github.com/sass/libsass/issues/185
+ // Work around until the issue is resolved:
+ $min: breakpoint-min($name, $breakpoints);
+ $max: breakpoint-max($name, $breakpoints);
+ @if $min and $max {
+ @media (min-width: $min) and (max-width: $max) {
+ @content;
+ }
+ } @else {
+ // One of min or max is a no-op, so this branch is not affected by libsass#185
+ @include media-breakpoint-min($name, $breakpoints) {
+ @include media-breakpoint-max($name, $breakpoints) {
+ @content;
+ }
+ }
+ }
+}
diff --git a/scss/mixins/_grid-framework.scss b/scss/mixins/_grid-framework.scss
index 3eecbae8b..0d346db57 100644
--- a/scss/mixins/_grid-framework.scss
+++ b/scss/mixins/_grid-framework.scss
@@ -3,69 +3,40 @@
// Used only by Bootstrap to generate the correct number of grid classes given
// any value of `$grid-columns`.
-// Common properties for all breakpoints
-@mixin make-grid-columns($columns: $grid-columns, $breakpoints: $grid-breakpoints) {
+@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
+ // Common properties for all breakpoints
%grid-column {
position: relative;
// Prevent columns from collapsing when empty
min-height: 1px;
// Inner gutter via padding
- padding-left: ($grid-gutter-width / 2);
- padding-right: ($grid-gutter-width / 2);
+ padding-left: ($gutter / 2);
+ padding-right: ($gutter / 2);
}
- @for $i from 1 through $columns {
- @each $breakpoint in $breakpoints {
+ @each $breakpoint in map-keys($breakpoints) {
+ @for $i from 1 through $columns {
.col-#{$breakpoint}-#{$i} {
@extend %grid-column;
}
}
- }
-}
-
-// Breakpoint-specific properties
-@mixin make-grid($breakpoint, $columns: $grid-columns) {
- // Work around cross-media @extend (https://github.com/sass/sass/issues/1050)
- %grid-column-float-#{$breakpoint} {
- float: left;
- }
- @for $i from 1 through $columns {
- .col-#{$breakpoint}-#{$i} {
- @extend %grid-column-float-#{$breakpoint};
- @include grid-column-width($i, $columns);
- }
- }
- @each $modifier in (pull, push, offset) {
- @for $i from 0 through $columns {
- .col-#{$breakpoint}-#{$modifier}-#{$i} {
- @include grid-column-modifier($modifier, $i, $columns)
+ @include media-breakpoint-min($breakpoint) {
+ // Work around cross-media @extend (https://github.com/sass/sass/issues/1050)
+ %grid-column-float-#{$breakpoint} {
+ float: left;
+ }
+ @for $i from 1 through $columns {
+ .col-#{$breakpoint}-#{$i} {
+ @extend %grid-column-float-#{$breakpoint};
+ @include make-col-span($i, $columns);
+ }
+ }
+ @each $modifier in (pull, push, offset) {
+ @for $i from 0 through $columns {
+ .col-#{$breakpoint}-#{$modifier}-#{$i} {
+ @include make-col-modifier($modifier, $i, $columns)
+ }
+ }
}
}
}
}
-
-@mixin grid-column-width($index, $columns) {
- width: percentage($index / $columns);
-}
-
-@mixin grid-column-push($index, $columns) {
- left: if($index > 0, percentage($index / $columns), auto);
-}
-
-@mixin grid-column-pull($index, $columns) {
- right: if($index > 0, percentage($index / $columns), auto);
-}
-
-@mixin grid-column-offset($index, $columns) {
- margin-left: percentage($index / $columns);
-}
-
-// Work around the lack of dynamic mixin @include support (https://github.com/sass/sass/issues/626)
-@mixin grid-column-modifier($type, $index, $columns) {
- @if $type == push {
- @include grid-column-push($index, $columns);
- } @else if $type == pull {
- @include grid-column-pull($index, $columns);
- } @else if $type == offset {
- @include grid-column-offset($index, $columns);
- }
-}
diff --git a/scss/mixins/_grid.scss b/scss/mixins/_grid.scss
index aceaeeb4c..29af269aa 100644
--- a/scss/mixins/_grid.scss
+++ b/scss/mixins/_grid.scss
@@ -24,18 +24,29 @@
padding-right: ($gutter / 2);
}
-@mixin make-col-span($columns) {
- width: percentage(($columns / $grid-columns));
+@mixin make-col-span($size, $columns: $grid-columns) {
+ width: percentage($size / $columns);
}
-@mixin make-col-offset($columns) {
- margin-left: percentage(($columns / $grid-columns));
+@mixin make-col-offset($size, $columns: $grid-columns) {
+ margin-left: percentage($size / $columns);
}
-@mixin make-col-push($columns) {
- left: percentage(($columns / $grid-columns));
+@mixin make-col-push($size, $columns: $grid-columns) {
+ left: if($size > 0, percentage($size / $columns), auto);
}
-@mixin make-col-pull($columns) {
- right: percentage(($columns / $grid-columns));
+@mixin make-col-pull($size, $columns: $grid-columns) {
+ right: if($size > 0, percentage($size / $columns), auto);
+}
+
+@mixin make-col-modifier($type, $size, $columns) {
+ // Work around the lack of dynamic mixin @include support (https://github.com/sass/sass/issues/626)
+ @if $type == push {
+ @include make-col-push($size, $columns);
+ } @else if $type == pull {
+ @include make-col-pull($size, $columns);
+ } @else if $type == offset {
+ @include make-col-offset($size, $columns);
+ }
}
diff --git a/scss/mixins/_media-queries.scss b/scss/mixins/_media-queries.scss
index b4e16ed88..28130d2e7 100644
--- a/scss/mixins/_media-queries.scss
+++ b/scss/mixins/_media-queries.scss
@@ -1,25 +1,25 @@
-// Media query mixins
+// Media query mixins for default breakpoints
@mixin media-xs() {
- @media (max-width: $screen-xs-max) { @content }
+ @include media-breakpoint-max(xs) { @content }
}
@mixin media-sm() {
- @media (min-width: $screen-sm-min) { @content }
+ @include media-breakpoint-min(sm) { @content }
}
@mixin media-sm-max() {
- @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { @content }
+ @include media-breakpoint-only(sm) { @content }
}
@mixin media-md() {
- @media (min-width: $screen-md-min) { @content }
+ @include media-breakpoint-min(md) { @content }
}
@mixin media-md-max() {
- @media (min-width: $screen-md-min) and (max-width: $screen-md-max) { @content }
+ @include media-breakpoint-only(md) { @content }
}
@mixin media-lg() {
- @media (min-width: $screen-lg-min) { @content }
+ @include media-breakpoint-min(lg) { @content }
}
diff --git a/scss/mixins/_pulls.scss b/scss/mixins/_pulls.scss
new file mode 100644
index 000000000..6bdff025d
--- /dev/null
+++ b/scss/mixins/_pulls.scss
@@ -0,0 +1,6 @@
+@mixin pull-left {
+ float: left !important;
+}
+@mixin pull-right {
+ float: right !important;
+}
diff --git a/test-infra/S3Cachefile.json b/test-infra/S3Cachefile.json
index 04d809246..90eae796d 100644
--- a/test-infra/S3Cachefile.json
+++ b/test-infra/S3Cachefile.json
@@ -5,8 +5,8 @@
"generate": "./uncached-npm-install.sh"
},
"rubygems": {
- "key": "../pseudo_Gemfile.lock",
- "cache": "$GEMDIR",
- "generate": "gem install -N scss-lint -v $SCSS_LINT_VERSION && gem install -N jekyll -v $JEKYLL_VERSION && gem install -N rouge -v $ROUGE_VERSION"
+ "key": "$BUNDLE_GEMFILE",
+ "cache": "../vendor/cache",
+ "generate": "cd .. ; bundle install --path=\"`pwd`/vendor/cache\""
}
}
diff --git a/test-infra/gemfiles/core.gemfile b/test-infra/gemfiles/core.gemfile
new file mode 100644
index 000000000..6a8372691
--- /dev/null
+++ b/test-infra/gemfiles/core.gemfile
@@ -0,0 +1,7 @@
+# Ruby Gems for the 'core' set of tests
+# Run `grunt update-gemfile-lock` to update to the latest compatible versions
+
+source 'https://rubygems.org'
+
+gem 'sass', '~> 3.4.9'
+gem 'scss-lint', '~> 0.31'
diff --git a/test-infra/gemfiles/core.gemfile.lock b/test-infra/gemfiles/core.gemfile.lock
new file mode 100644
index 000000000..03580d83b
--- /dev/null
+++ b/test-infra/gemfiles/core.gemfile.lock
@@ -0,0 +1,15 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ rainbow (2.0.0)
+ sass (3.4.9)
+ scss-lint (0.31.0)
+ rainbow (~> 2.0)
+ sass (~> 3.4.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ sass (~> 3.4.9)
+ scss-lint (~> 0.31)