parent
e4fd7b0553
commit
91b4865140
@ -1,7 +1,7 @@ |
|||||||
{ |
{ |
||||||
"name": "{{cookiecutter.app_name}}", |
"name": "{{cookiecutter.app_name}}", |
||||||
"dependencies": { |
"dependencies": { |
||||||
"bootstrap": ">=3.1.1", |
"bootstrap": "~3.2.0", |
||||||
"jQuery": ">=1.9.0" |
"jQuery": "~2.1.0" |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,35 +1,47 @@ |
|||||||
{ |
{ |
||||||
"name": "bootstrap", |
"name": "bootstrap", |
||||||
"version": "3.1.1", |
"description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", |
||||||
|
"version": "3.2.0", |
||||||
|
"keywords": [ |
||||||
|
"css", |
||||||
|
"js", |
||||||
|
"less", |
||||||
|
"mobile-first", |
||||||
|
"responsive", |
||||||
|
"front-end", |
||||||
|
"framework", |
||||||
|
"web" |
||||||
|
], |
||||||
|
"homepage": "http://getbootstrap.com", |
||||||
"main": [ |
"main": [ |
||||||
"./dist/css/bootstrap.css", |
"less/bootstrap.less", |
||||||
"./dist/js/bootstrap.js", |
"dist/css/bootstrap.css", |
||||||
"./dist/fonts/glyphicons-halflings-regular.eot", |
"dist/js/bootstrap.js", |
||||||
"./dist/fonts/glyphicons-halflings-regular.svg", |
"dist/fonts/glyphicons-halflings-regular.eot", |
||||||
"./dist/fonts/glyphicons-halflings-regular.ttf", |
"dist/fonts/glyphicons-halflings-regular.svg", |
||||||
"./dist/fonts/glyphicons-halflings-regular.woff" |
"dist/fonts/glyphicons-halflings-regular.ttf", |
||||||
|
"dist/fonts/glyphicons-halflings-regular.woff" |
||||||
], |
], |
||||||
"ignore": [ |
"ignore": [ |
||||||
"**/.*", |
".*", |
||||||
"_config.yml", |
"_config.yml", |
||||||
"CNAME", |
"CNAME", |
||||||
"composer.json", |
"composer.json", |
||||||
"CONTRIBUTING.md", |
"CONTRIBUTING.md", |
||||||
"docs", |
"docs", |
||||||
"js/tests" |
"js/tests", |
||||||
|
"test-infra" |
||||||
], |
], |
||||||
"dependencies": { |
"dependencies": { |
||||||
"jquery": ">= 1.9.0" |
"jquery": ">= 1.9.0" |
||||||
}, |
}, |
||||||
"homepage": "https://github.com/twbs/bootstrap", |
"_release": "3.2.0", |
||||||
"_release": "3.1.1", |
|
||||||
"_resolution": { |
"_resolution": { |
||||||
"type": "version", |
"type": "version", |
||||||
"tag": "v3.1.1", |
"tag": "v3.2.0", |
||||||
"commit": "a365d8689c3f3cee7f1acf86b61270ecca8e106d" |
"commit": "c068162161154a4b85110ea1e7dd3d7897ce2b72" |
||||||
}, |
}, |
||||||
"_source": "git://github.com/twbs/bootstrap.git", |
"_source": "git://github.com/twbs/bootstrap.git", |
||||||
"_target": "~3.1.1", |
"_target": "~3.2.0", |
||||||
"_originalSource": "bootstrap", |
"_originalSource": "bootstrap" |
||||||
"_direct": true |
|
||||||
} |
} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,31 +1,46 @@ |
|||||||
/* global btoa: true */ |
|
||||||
/*! |
/*! |
||||||
* Bootstrap Grunt task for generating raw-files.min.js for the Customizer |
* Bootstrap Grunt task for generating raw-files.min.js for the Customizer |
||||||
* http://getbootstrap.com
|
* http://getbootstrap.com
|
||||||
* Copyright 2014 Twitter, Inc. |
* Copyright 2014 Twitter, Inc. |
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
*/ |
*/ |
||||||
|
|
||||||
|
/* global btoa: true */ |
||||||
|
|
||||||
'use strict'; |
'use strict'; |
||||||
var btoa = require('btoa'); |
|
||||||
var fs = require('fs'); |
var fs = require('fs'); |
||||||
|
var btoa = require('btoa'); |
||||||
|
var glob = require('glob'); |
||||||
|
|
||||||
function getFiles(type) { |
function getFiles(type) { |
||||||
var files = {}; |
var files = {}; |
||||||
fs.readdirSync(type) |
var recursive = (type === 'less'); |
||||||
|
var globExpr = (recursive ? '/**/*' : '/*'); |
||||||
|
glob.sync(type + globExpr) |
||||||
.filter(function (path) { |
.filter(function (path) { |
||||||
return type === 'fonts' ? true : new RegExp('\\.' + type + '$').test(path); |
return type === 'fonts' ? true : new RegExp('\\.' + type + '$').test(path); |
||||||
}) |
}) |
||||||
.forEach(function (path) { |
.forEach(function (fullPath) { |
||||||
var fullPath = type + '/' + path; |
var relativePath = fullPath.replace(/^[^/]+\//, ''); |
||||||
files[path] = (type === 'fonts' ? btoa(fs.readFileSync(fullPath)) : fs.readFileSync(fullPath, 'utf8')); |
files[relativePath] = (type === 'fonts' ? btoa(fs.readFileSync(fullPath)) : fs.readFileSync(fullPath, 'utf8')); |
||||||
}); |
}); |
||||||
return 'var __' + type + ' = ' + JSON.stringify(files) + '\n'; |
return 'var __' + type + ' = ' + JSON.stringify(files) + '\n'; |
||||||
} |
} |
||||||
|
|
||||||
module.exports = function generateRawFilesJs(banner) { |
module.exports = function generateRawFilesJs(grunt, banner) { |
||||||
if (!banner) { |
if (!banner) { |
||||||
banner = ''; |
banner = ''; |
||||||
} |
} |
||||||
var files = banner + getFiles('js') + getFiles('less') + getFiles('fonts'); |
var dirs = ['js', 'less', 'fonts']; |
||||||
fs.writeFileSync('docs/assets/js/raw-files.min.js', files); |
var files = banner + dirs.map(getFiles).reduce(function (combined, file) { |
||||||
|
return combined + file; |
||||||
|
}, ''); |
||||||
|
var rawFilesJs = 'docs/assets/js/raw-files.min.js'; |
||||||
|
try { |
||||||
|
fs.writeFileSync(rawFilesJs, files); |
||||||
|
} |
||||||
|
catch (err) { |
||||||
|
grunt.fail.warn(err); |
||||||
|
} |
||||||
|
grunt.log.writeln('File ' + rawFilesJs.cyan + ' created.'); |
||||||
}; |
}; |
||||||
|
@ -1,28 +0,0 @@ |
|||||||
/*! |
|
||||||
* Bootstrap Grunt task for generating npm-shrinkwrap.canonical.json |
|
||||||
* http://getbootstrap.com
|
|
||||||
* Copyright 2014 Twitter, Inc. |
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
||||||
*/ |
|
||||||
/* |
|
||||||
This Grunt task updates the npm-shrinkwrap.canonical.json file that's used as the key for Bootstrap's npm packages cache. |
|
||||||
This task should be run and the updated file should be committed whenever Bootstrap's dependencies change. |
|
||||||
*/ |
|
||||||
'use strict'; |
|
||||||
var canonicallyJsonStringify = require('canonical-json'); |
|
||||||
var NON_CANONICAL_FILE = 'npm-shrinkwrap.json'; |
|
||||||
var DEST_FILE = 'test-infra/npm-shrinkwrap.canonical.json'; |
|
||||||
|
|
||||||
|
|
||||||
function updateShrinkwrap(grunt) { |
|
||||||
// Assumption: Non-canonical shrinkwrap already generated by prerequisite Grunt task
|
|
||||||
var shrinkwrapData = grunt.file.readJSON(NON_CANONICAL_FILE); |
|
||||||
grunt.log.writeln('Deleting ' + NON_CANONICAL_FILE.cyan + '...'); |
|
||||||
grunt.file.delete(NON_CANONICAL_FILE); |
|
||||||
// Output as Canonical JSON in correct location
|
|
||||||
grunt.file.write(DEST_FILE, canonicallyJsonStringify(shrinkwrapData)); |
|
||||||
grunt.log.writeln('File ' + DEST_FILE.cyan + ' updated.'); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
module.exports = updateShrinkwrap; |
|
@ -1,929 +1,39 @@ |
|||||||
// |
|
||||||
// Mixins |
// Mixins |
||||||
// -------------------------------------------------- |
// -------------------------------------------------- |
||||||
|
|
||||||
|
|
||||||
// Utilities |
// Utilities |
||||||
// ------------------------- |
@import "mixins/hide-text.less"; |
||||||
|
@import "mixins/opacity.less"; |
||||||
// Clearfix |
@import "mixins/image.less"; |
||||||
// Source: http://nicolasgallagher.com/micro-clearfix-hack/ |
@import "mixins/labels.less"; |
||||||
// |
@import "mixins/reset-filter.less"; |
||||||
// For modern browsers |
@import "mixins/resize.less"; |
||||||
// 1. The space content is one way to avoid an Opera bug when the |
@import "mixins/responsive-visibility.less"; |
||||||
// contenteditable attribute is included anywhere else in the document. |
@import "mixins/size.less"; |
||||||
// Otherwise it causes space to appear at the top and bottom of elements |
@import "mixins/tab-focus.less"; |
||||||
// that are clearfixed. |
@import "mixins/text-emphasis.less"; |
||||||
// 2. The use of `table` rather than `block` is only necessary if using |
@import "mixins/text-overflow.less"; |
||||||
// `:before` to contain the top-margins of child elements. |
@import "mixins/vendor-prefixes.less"; |
||||||
.clearfix() { |
|
||||||
&:before, |
// Components |
||||||
&:after { |
@import "mixins/alerts.less"; |
||||||
content: " "; // 1 |
@import "mixins/buttons.less"; |
||||||
display: table; // 2 |
@import "mixins/panels.less"; |
||||||
} |
@import "mixins/pagination.less"; |
||||||
&:after { |
@import "mixins/list-group.less"; |
||||||
clear: both; |
@import "mixins/nav-divider.less"; |
||||||
} |
@import "mixins/forms.less"; |
||||||
} |
@import "mixins/progress-bar.less"; |
||||||
|
@import "mixins/table-row.less"; |
||||||
// WebKit-style focus |
|
||||||
.tab-focus() { |
// Skins |
||||||
// Default |
@import "mixins/background-variant.less"; |
||||||
outline: thin dotted; |
@import "mixins/border-radius.less"; |
||||||
// WebKit |
@import "mixins/gradients.less"; |
||||||
outline: 5px auto -webkit-focus-ring-color; |
|
||||||
outline-offset: -2px; |
// Layout |
||||||
} |
@import "mixins/clearfix.less"; |
||||||
|
@import "mixins/center-block.less"; |
||||||
// Center-align a block level element |
@import "mixins/nav-vertical-align.less"; |
||||||
.center-block() { |
@import "mixins/grid-framework.less"; |
||||||
display: block; |
@import "mixins/grid.less"; |
||||||
margin-left: auto; |
|
||||||
margin-right: auto; |
|
||||||
} |
|
||||||
|
|
||||||
// Sizing shortcuts |
|
||||||
.size(@width; @height) { |
|
||||||
width: @width; |
|
||||||
height: @height; |
|
||||||
} |
|
||||||
.square(@size) { |
|
||||||
.size(@size; @size); |
|
||||||
} |
|
||||||
|
|
||||||
// Placeholder text |
|
||||||
.placeholder(@color: @input-color-placeholder) { |
|
||||||
&::-moz-placeholder { color: @color; // Firefox |
|
||||||
opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526 |
|
||||||
&:-ms-input-placeholder { color: @color; } // Internet Explorer 10+ |
|
||||||
&::-webkit-input-placeholder { color: @color; } // Safari and Chrome |
|
||||||
} |
|
||||||
|
|
||||||
// Text overflow |
|
||||||
// Requires inline-block or block for proper styling |
|
||||||
.text-overflow() { |
|
||||||
overflow: hidden; |
|
||||||
text-overflow: ellipsis; |
|
||||||
white-space: nowrap; |
|
||||||
} |
|
||||||
|
|
||||||
// CSS image replacement |
|
||||||
// |
|
||||||
// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for |
|
||||||
// mixins being reused as classes with the same name, this doesn't hold up. As |
|
||||||
// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note |
|
||||||
// that we cannot chain the mixins together in Less, so they are repeated. |
|
||||||
// |
|
||||||
// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757 |
|
||||||
|
|
||||||
// Deprecated as of v3.0.1 (will be removed in v4) |
|
||||||
.hide-text() { |
|
||||||
font: ~"0/0" a; |
|
||||||
color: transparent; |
|
||||||
text-shadow: none; |
|
||||||
background-color: transparent; |
|
||||||
border: 0; |
|
||||||
} |
|
||||||
// New mixin to use as of v3.0.1 |
|
||||||
.text-hide() { |
|
||||||
.hide-text(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// CSS3 PROPERTIES |
|
||||||
// -------------------------------------------------- |
|
||||||
|
|
||||||
// Single side border-radius |
|
||||||
.border-top-radius(@radius) { |
|
||||||
border-top-right-radius: @radius; |
|
||||||
border-top-left-radius: @radius; |
|
||||||
} |
|
||||||
.border-right-radius(@radius) { |
|
||||||
border-bottom-right-radius: @radius; |
|
||||||
border-top-right-radius: @radius; |
|
||||||
} |
|
||||||
.border-bottom-radius(@radius) { |
|
||||||
border-bottom-right-radius: @radius; |
|
||||||
border-bottom-left-radius: @radius; |
|
||||||
} |
|
||||||
.border-left-radius(@radius) { |
|
||||||
border-bottom-left-radius: @radius; |
|
||||||
border-top-left-radius: @radius; |
|
||||||
} |
|
||||||
|
|
||||||
// Drop shadows |
|
||||||
// |
|
||||||
// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's |
|
||||||
// supported browsers that have box shadow capabilities now support the |
|
||||||
// standard `box-shadow` property. |
|
||||||
.box-shadow(@shadow) { |
|
||||||
-webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1 |
|
||||||
box-shadow: @shadow; |
|
||||||
} |
|
||||||
|
|
||||||
// Transitions |
|
||||||
.transition(@transition) { |
|
||||||
-webkit-transition: @transition; |
|
||||||
transition: @transition; |
|
||||||
} |
|
||||||
.transition-property(@transition-property) { |
|
||||||
-webkit-transition-property: @transition-property; |
|
||||||
transition-property: @transition-property; |
|
||||||
} |
|
||||||
.transition-delay(@transition-delay) { |
|
||||||
-webkit-transition-delay: @transition-delay; |
|
||||||
transition-delay: @transition-delay; |
|
||||||
} |
|
||||||
.transition-duration(@transition-duration) { |
|
||||||
-webkit-transition-duration: @transition-duration; |
|
||||||
transition-duration: @transition-duration; |
|
||||||
} |
|
||||||
.transition-transform(@transition) { |
|
||||||
-webkit-transition: -webkit-transform @transition; |
|
||||||
-moz-transition: -moz-transform @transition; |
|
||||||
-o-transition: -o-transform @transition; |
|
||||||
transition: transform @transition; |
|
||||||
} |
|
||||||
|
|
||||||
// Transformations |
|
||||||
.rotate(@degrees) { |
|
||||||
-webkit-transform: rotate(@degrees); |
|
||||||
-ms-transform: rotate(@degrees); // IE9 only |
|
||||||
transform: rotate(@degrees); |
|
||||||
} |
|
||||||
.scale(@ratio; @ratio-y...) { |
|
||||||
-webkit-transform: scale(@ratio, @ratio-y); |
|
||||||
-ms-transform: scale(@ratio, @ratio-y); // IE9 only |
|
||||||
transform: scale(@ratio, @ratio-y); |
|
||||||
} |
|
||||||
.translate(@x; @y) { |
|
||||||
-webkit-transform: translate(@x, @y); |
|
||||||
-ms-transform: translate(@x, @y); // IE9 only |
|
||||||
transform: translate(@x, @y); |
|
||||||
} |
|
||||||
.skew(@x; @y) { |
|
||||||
-webkit-transform: skew(@x, @y); |
|
||||||
-ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+ |
|
||||||
transform: skew(@x, @y); |
|
||||||
} |
|
||||||
.translate3d(@x; @y; @z) { |
|
||||||
-webkit-transform: translate3d(@x, @y, @z); |
|
||||||
transform: translate3d(@x, @y, @z); |
|
||||||
} |
|
||||||
|
|
||||||
.rotateX(@degrees) { |
|
||||||
-webkit-transform: rotateX(@degrees); |
|
||||||
-ms-transform: rotateX(@degrees); // IE9 only |
|
||||||
transform: rotateX(@degrees); |
|
||||||
} |
|
||||||
.rotateY(@degrees) { |
|
||||||
-webkit-transform: rotateY(@degrees); |
|
||||||
-ms-transform: rotateY(@degrees); // IE9 only |
|
||||||
transform: rotateY(@degrees); |
|
||||||
} |
|
||||||
.perspective(@perspective) { |
|
||||||
-webkit-perspective: @perspective; |
|
||||||
-moz-perspective: @perspective; |
|
||||||
perspective: @perspective; |
|
||||||
} |
|
||||||
.perspective-origin(@perspective) { |
|
||||||
-webkit-perspective-origin: @perspective; |
|
||||||
-moz-perspective-origin: @perspective; |
|
||||||
perspective-origin: @perspective; |
|
||||||
} |
|
||||||
.transform-origin(@origin) { |
|
||||||
-webkit-transform-origin: @origin; |
|
||||||
-moz-transform-origin: @origin; |
|
||||||
-ms-transform-origin: @origin; // IE9 only |
|
||||||
transform-origin: @origin; |
|
||||||
} |
|
||||||
|
|
||||||
// Animations |
|
||||||
.animation(@animation) { |
|
||||||
-webkit-animation: @animation; |
|
||||||
animation: @animation; |
|
||||||
} |
|
||||||
.animation-name(@name) { |
|
||||||
-webkit-animation-name: @name; |
|
||||||
animation-name: @name; |
|
||||||
} |
|
||||||
.animation-duration(@duration) { |
|
||||||
-webkit-animation-duration: @duration; |
|
||||||
animation-duration: @duration; |
|
||||||
} |
|
||||||
.animation-timing-function(@timing-function) { |
|
||||||
-webkit-animation-timing-function: @timing-function; |
|
||||||
animation-timing-function: @timing-function; |
|
||||||
} |
|
||||||
.animation-delay(@delay) { |
|
||||||
-webkit-animation-delay: @delay; |
|
||||||
animation-delay: @delay; |
|
||||||
} |
|
||||||
.animation-iteration-count(@iteration-count) { |
|
||||||
-webkit-animation-iteration-count: @iteration-count; |
|
||||||
animation-iteration-count: @iteration-count; |
|
||||||
} |
|
||||||
.animation-direction(@direction) { |
|
||||||
-webkit-animation-direction: @direction; |
|
||||||
animation-direction: @direction; |
|
||||||
} |
|
||||||
|
|
||||||
// Backface visibility |
|
||||||
// Prevent browsers from flickering when using CSS 3D transforms. |
|
||||||
// Default value is `visible`, but can be changed to `hidden` |
|
||||||
.backface-visibility(@visibility){ |
|
||||||
-webkit-backface-visibility: @visibility; |
|
||||||
-moz-backface-visibility: @visibility; |
|
||||||
backface-visibility: @visibility; |
|
||||||
} |
|
||||||
|
|
||||||
// Box sizing |
|
||||||
.box-sizing(@boxmodel) { |
|
||||||
-webkit-box-sizing: @boxmodel; |
|
||||||
-moz-box-sizing: @boxmodel; |
|
||||||
box-sizing: @boxmodel; |
|
||||||
} |
|
||||||
|
|
||||||
// User select |
|
||||||
// For selecting text on the page |
|
||||||
.user-select(@select) { |
|
||||||
-webkit-user-select: @select; |
|
||||||
-moz-user-select: @select; |
|
||||||
-ms-user-select: @select; // IE10+ |
|
||||||
user-select: @select; |
|
||||||
} |
|
||||||
|
|
||||||
// Resize anything |
|
||||||
.resizable(@direction) { |
|
||||||
resize: @direction; // Options: horizontal, vertical, both |
|
||||||
overflow: auto; // Safari fix |
|
||||||
} |
|
||||||
|
|
||||||
// CSS3 Content Columns |
|
||||||
.content-columns(@column-count; @column-gap: @grid-gutter-width) { |
|
||||||
-webkit-column-count: @column-count; |
|
||||||
-moz-column-count: @column-count; |
|
||||||
column-count: @column-count; |
|
||||||
-webkit-column-gap: @column-gap; |
|
||||||
-moz-column-gap: @column-gap; |
|
||||||
column-gap: @column-gap; |
|
||||||
} |
|
||||||
|
|
||||||
// Optional hyphenation |
|
||||||
.hyphens(@mode: auto) { |
|
||||||
word-wrap: break-word; |
|
||||||
-webkit-hyphens: @mode; |
|
||||||
-moz-hyphens: @mode; |
|
||||||
-ms-hyphens: @mode; // IE10+ |
|
||||||
-o-hyphens: @mode; |
|
||||||
hyphens: @mode; |
|
||||||
} |
|
||||||
|
|
||||||
// Opacity |
|
||||||
.opacity(@opacity) { |
|
||||||
opacity: @opacity; |
|
||||||
// IE8 filter |
|
||||||
@opacity-ie: (@opacity * 100); |
|
||||||
filter: ~"alpha(opacity=@{opacity-ie})"; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// GRADIENTS |
|
||||||
// -------------------------------------------------- |
|
||||||
|
|
||||||
#gradient { |
|
||||||
|
|
||||||
// Horizontal gradient, from left to right |
|
||||||
// |
|
||||||
// Creates two color stops, start and end, by specifying a color and position for each color stop. |
|
||||||
// Color stops are not available in IE9 and below. |
|
||||||
.horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) { |
|
||||||
background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+ |
|
||||||
background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ |
|
||||||
background-repeat: repeat-x; |
|
||||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down |
|
||||||
} |
|
||||||
|
|
||||||
// Vertical gradient, from top to bottom |
|
||||||
// |
|
||||||
// Creates two color stops, start and end, by specifying a color and position for each color stop. |
|
||||||
// Color stops are not available in IE9 and below. |
|
||||||
.vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) { |
|
||||||
background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+ |
|
||||||
background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ |
|
||||||
background-repeat: repeat-x; |
|
||||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down |
|
||||||
} |
|
||||||
|
|
||||||
.directional(@start-color: #555; @end-color: #333; @deg: 45deg) { |
|
||||||
background-repeat: repeat-x; |
|
||||||
background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+ |
|
||||||
background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ |
|
||||||
} |
|
||||||
.horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { |
|
||||||
background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color); |
|
||||||
background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color); |
|
||||||
background-repeat: no-repeat; |
|
||||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback |
|
||||||
} |
|
||||||
.vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { |
|
||||||
background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color); |
|
||||||
background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color); |
|
||||||
background-repeat: no-repeat; |
|
||||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback |
|
||||||
} |
|
||||||
.radial(@inner-color: #555; @outer-color: #333) { |
|
||||||
background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color); |
|
||||||
background-image: radial-gradient(circle, @inner-color, @outer-color); |
|
||||||
background-repeat: no-repeat; |
|
||||||
} |
|
||||||
.striped(@color: rgba(255,255,255,.15); @angle: 45deg) { |
|
||||||
background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); |
|
||||||
background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Reset filters for IE |
|
||||||
// |
|
||||||
// When you need to remove a gradient background, do not forget to use this to reset |
|
||||||
// the IE filter for IE9 and below. |
|
||||||
.reset-filter() { |
|
||||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)")); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Retina images |
|
||||||
// |
|
||||||
// Short retina mixin for setting background-image and -size |
|
||||||
|
|
||||||
.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) { |
|
||||||
background-image: url("@{file-1x}"); |
|
||||||
|
|
||||||
@media |
|
||||||
only screen and (-webkit-min-device-pixel-ratio: 2), |
|
||||||
only screen and ( min--moz-device-pixel-ratio: 2), |
|
||||||
only screen and ( -o-min-device-pixel-ratio: 2/1), |
|
||||||
only screen and ( min-device-pixel-ratio: 2), |
|
||||||
only screen and ( min-resolution: 192dpi), |
|
||||||
only screen and ( min-resolution: 2dppx) { |
|
||||||
background-image: url("@{file-2x}"); |
|
||||||
background-size: @width-1x @height-1x; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Responsive image |
|
||||||
// |
|
||||||
// Keep images from scaling beyond the width of their parents. |
|
||||||
|
|
||||||
.img-responsive(@display: block) { |
|
||||||
display: @display; |
|
||||||
max-width: 100%; // Part 1: Set a maximum relative to the parent |
|
||||||
height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// COMPONENT MIXINS |
|
||||||
// -------------------------------------------------- |
|
||||||
|
|
||||||
// Horizontal dividers |
|
||||||
// ------------------------- |
|
||||||
// Dividers (basically an hr) within dropdowns and nav lists |
|
||||||
.nav-divider(@color: #e5e5e5) { |
|
||||||
height: 1px; |
|
||||||
margin: ((@line-height-computed / 2) - 1) 0; |
|
||||||
overflow: hidden; |
|
||||||
background-color: @color; |
|
||||||
} |
|
||||||
|
|
||||||
// Panels |
|
||||||
// ------------------------- |
|
||||||
.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) { |
|
||||||
border-color: @border; |
|
||||||
|
|
||||||
& > .panel-heading { |
|
||||||
color: @heading-text-color; |
|
||||||
background-color: @heading-bg-color; |
|
||||||
border-color: @heading-border; |
|
||||||
|
|
||||||
+ .panel-collapse .panel-body { |
|
||||||
border-top-color: @border; |
|
||||||
} |
|
||||||
} |
|
||||||
& > .panel-footer { |
|
||||||
+ .panel-collapse .panel-body { |
|
||||||
border-bottom-color: @border; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Alerts |
|
||||||
// ------------------------- |
|
||||||
.alert-variant(@background; @border; @text-color) { |
|
||||||
background-color: @background; |
|
||||||
border-color: @border; |
|
||||||
color: @text-color; |
|
||||||
|
|
||||||
hr { |
|
||||||
border-top-color: darken(@border, 5%); |
|
||||||
} |
|
||||||
.alert-link { |
|
||||||
color: darken(@text-color, 10%); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Tables |
|
||||||
// ------------------------- |
|
||||||
.table-row-variant(@state; @background) { |
|
||||||
// Exact selectors below required to override `.table-striped` and prevent |
|
||||||
// inheritance to nested tables. |
|
||||||
.table > thead > tr, |
|
||||||
.table > tbody > tr, |
|
||||||
.table > tfoot > tr { |
|
||||||
> td.@{state}, |
|
||||||
> th.@{state}, |
|
||||||
&.@{state} > td, |
|
||||||
&.@{state} > th { |
|
||||||
background-color: @background; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// 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, |
|
||||||
&.@{state}:hover > th { |
|
||||||
background-color: darken(@background, 5%); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// List Groups |
|
||||||
// ------------------------- |
|
||||||
.list-group-item-variant(@state; @background; @color) { |
|
||||||
.list-group-item-@{state} { |
|
||||||
color: @color; |
|
||||||
background-color: @background; |
|
||||||
|
|
||||||
a& { |
|
||||||
color: @color; |
|
||||||
|
|
||||||
.list-group-item-heading { color: inherit; } |
|
||||||
|
|
||||||
&:hover, |
|
||||||
&:focus { |
|
||||||
color: @color; |
|
||||||
background-color: darken(@background, 5%); |
|
||||||
} |
|
||||||
&.active, |
|
||||||
&.active:hover, |
|
||||||
&.active:focus { |
|
||||||
color: #fff; |
|
||||||
background-color: @color; |
|
||||||
border-color: @color; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Button variants |
|
||||||
// ------------------------- |
|
||||||
// Easily pump out default styles, as well as :hover, :focus, :active, |
|
||||||
// and disabled options for all buttons |
|
||||||
.button-variant(@color; @background; @border) { |
|
||||||
color: @color; |
|
||||||
background-color: @background; |
|
||||||
border-color: @border; |
|
||||||
|
|
||||||
&:hover, |
|
||||||
&:focus, |
|
||||||
&:active, |
|
||||||
&.active, |
|
||||||
.open .dropdown-toggle& { |
|
||||||
color: @color; |
|
||||||
background-color: darken(@background, 8%); |
|
||||||
border-color: darken(@border, 12%); |
|
||||||
} |
|
||||||
&:active, |
|
||||||
&.active, |
|
||||||
.open .dropdown-toggle& { |
|
||||||
background-image: none; |
|
||||||
} |
|
||||||
&.disabled, |
|
||||||
&[disabled], |
|
||||||
fieldset[disabled] & { |
|
||||||
&, |
|
||||||
&:hover, |
|
||||||
&:focus, |
|
||||||
&:active, |
|
||||||
&.active { |
|
||||||
background-color: @background; |
|
||||||
border-color: @border; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.badge { |
|
||||||
color: @background; |
|
||||||
background-color: @color; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Button sizes |
|
||||||
// ------------------------- |
|
||||||
.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { |
|
||||||
padding: @padding-vertical @padding-horizontal; |
|
||||||
font-size: @font-size; |
|
||||||
line-height: @line-height; |
|
||||||
border-radius: @border-radius; |
|
||||||
} |
|
||||||
|
|
||||||
// Pagination |
|
||||||
// ------------------------- |
|
||||||
.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) { |
|
||||||
> li { |
|
||||||
> a, |
|
||||||
> span { |
|
||||||
padding: @padding-vertical @padding-horizontal; |
|
||||||
font-size: @font-size; |
|
||||||
} |
|
||||||
&:first-child { |
|
||||||
> a, |
|
||||||
> span { |
|
||||||
.border-left-radius(@border-radius); |
|
||||||
} |
|
||||||
} |
|
||||||
&:last-child { |
|
||||||
> a, |
|
||||||
> span { |
|
||||||
.border-right-radius(@border-radius); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Labels |
|
||||||
// ------------------------- |
|
||||||
.label-variant(@color) { |
|
||||||
background-color: @color; |
|
||||||
&[href] { |
|
||||||
&:hover, |
|
||||||
&:focus { |
|
||||||
background-color: darken(@color, 10%); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Contextual backgrounds |
|
||||||
// ------------------------- |
|
||||||
.bg-variant(@color) { |
|
||||||
background-color: @color; |
|
||||||
a&:hover { |
|
||||||
background-color: darken(@color, 10%); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Typography |
|
||||||
// ------------------------- |
|
||||||
.text-emphasis-variant(@color) { |
|
||||||
color: @color; |
|
||||||
a&:hover { |
|
||||||
color: darken(@color, 10%); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Navbar vertical align |
|
||||||
// ------------------------- |
|
||||||
// Vertically center elements in the navbar. |
|
||||||
// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin. |
|
||||||
.navbar-vertical-align(@element-height) { |
|
||||||
margin-top: ((@navbar-height - @element-height) / 2); |
|
||||||
margin-bottom: ((@navbar-height - @element-height) / 2); |
|
||||||
} |
|
||||||
|
|
||||||
// Progress bars |
|
||||||
// ------------------------- |
|
||||||
.progress-bar-variant(@color) { |
|
||||||
background-color: @color; |
|
||||||
.progress-striped & { |
|
||||||
#gradient > .striped(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Responsive utilities |
|
||||||
// ------------------------- |
|
||||||
// More easily include all the states for responsive-utilities.less. |
|
||||||
.responsive-visibility() { |
|
||||||
display: block !important; |
|
||||||
table& { display: table; } |
|
||||||
tr& { display: table-row !important; } |
|
||||||
th&, |
|
||||||
td& { display: table-cell !important; } |
|
||||||
} |
|
||||||
|
|
||||||
.responsive-invisibility() { |
|
||||||
display: none !important; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Grid System |
|
||||||
// ----------- |
|
||||||
|
|
||||||
// Centered container element |
|
||||||
.container-fixed() { |
|
||||||
margin-right: auto; |
|
||||||
margin-left: auto; |
|
||||||
padding-left: (@grid-gutter-width / 2); |
|
||||||
padding-right: (@grid-gutter-width / 2); |
|
||||||
&:extend(.clearfix all); |
|
||||||
} |
|
||||||
|
|
||||||
// Creates a wrapper for a series of columns |
|
||||||
.make-row(@gutter: @grid-gutter-width) { |
|
||||||
margin-left: (@gutter / -2); |
|
||||||
margin-right: (@gutter / -2); |
|
||||||
&:extend(.clearfix all); |
|
||||||
} |
|
||||||
|
|
||||||
// Generate the extra small columns |
|
||||||
.make-xs-column(@columns; @gutter: @grid-gutter-width) { |
|
||||||
position: relative; |
|
||||||
float: left; |
|
||||||
width: percentage((@columns / @grid-columns)); |
|
||||||
min-height: 1px; |
|
||||||
padding-left: (@gutter / 2); |
|
||||||
padding-right: (@gutter / 2); |
|
||||||
} |
|
||||||
.make-xs-column-offset(@columns) { |
|
||||||
@media (min-width: @screen-xs-min) { |
|
||||||
margin-left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-xs-column-push(@columns) { |
|
||||||
@media (min-width: @screen-xs-min) { |
|
||||||
left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-xs-column-pull(@columns) { |
|
||||||
@media (min-width: @screen-xs-min) { |
|
||||||
right: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Generate the small columns |
|
||||||
.make-sm-column(@columns; @gutter: @grid-gutter-width) { |
|
||||||
position: relative; |
|
||||||
min-height: 1px; |
|
||||||
padding-left: (@gutter / 2); |
|
||||||
padding-right: (@gutter / 2); |
|
||||||
|
|
||||||
@media (min-width: @screen-sm-min) { |
|
||||||
float: left; |
|
||||||
width: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-sm-column-offset(@columns) { |
|
||||||
@media (min-width: @screen-sm-min) { |
|
||||||
margin-left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-sm-column-push(@columns) { |
|
||||||
@media (min-width: @screen-sm-min) { |
|
||||||
left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-sm-column-pull(@columns) { |
|
||||||
@media (min-width: @screen-sm-min) { |
|
||||||
right: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Generate the medium columns |
|
||||||
.make-md-column(@columns; @gutter: @grid-gutter-width) { |
|
||||||
position: relative; |
|
||||||
min-height: 1px; |
|
||||||
padding-left: (@gutter / 2); |
|
||||||
padding-right: (@gutter / 2); |
|
||||||
|
|
||||||
@media (min-width: @screen-md-min) { |
|
||||||
float: left; |
|
||||||
width: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-md-column-offset(@columns) { |
|
||||||
@media (min-width: @screen-md-min) { |
|
||||||
margin-left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-md-column-push(@columns) { |
|
||||||
@media (min-width: @screen-md-min) { |
|
||||||
left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-md-column-pull(@columns) { |
|
||||||
@media (min-width: @screen-md-min) { |
|
||||||
right: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Generate the large columns |
|
||||||
.make-lg-column(@columns; @gutter: @grid-gutter-width) { |
|
||||||
position: relative; |
|
||||||
min-height: 1px; |
|
||||||
padding-left: (@gutter / 2); |
|
||||||
padding-right: (@gutter / 2); |
|
||||||
|
|
||||||
@media (min-width: @screen-lg-min) { |
|
||||||
float: left; |
|
||||||
width: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-lg-column-offset(@columns) { |
|
||||||
@media (min-width: @screen-lg-min) { |
|
||||||
margin-left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-lg-column-push(@columns) { |
|
||||||
@media (min-width: @screen-lg-min) { |
|
||||||
left: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.make-lg-column-pull(@columns) { |
|
||||||
@media (min-width: @screen-lg-min) { |
|
||||||
right: percentage((@columns / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Framework grid generation |
|
||||||
// |
|
||||||
// Used only by Bootstrap to generate the correct number of grid classes given |
|
||||||
// any value of `@grid-columns`. |
|
||||||
|
|
||||||
.make-grid-columns() { |
|
||||||
// Common styles for all sizes of grid columns, widths 1-12 |
|
||||||
.col(@index) when (@index = 1) { // initial |
|
||||||
@item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; |
|
||||||
.col((@index + 1), @item); |
|
||||||
} |
|
||||||
.col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo |
|
||||||
@item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; |
|
||||||
.col((@index + 1), ~"@{list}, @{item}"); |
|
||||||
} |
|
||||||
.col(@index, @list) when (@index > @grid-columns) { // terminal |
|
||||||
@{list} { |
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
.col(1); // kickstart it |
|
||||||
} |
|
||||||
|
|
||||||
.float-grid-columns(@class) { |
|
||||||
.col(@index) when (@index = 1) { // initial |
|
||||||
@item: ~".col-@{class}-@{index}"; |
|
||||||
.col((@index + 1), @item); |
|
||||||
} |
|
||||||
.col(@index, @list) when (@index =< @grid-columns) { // general |
|
||||||
@item: ~".col-@{class}-@{index}"; |
|
||||||
.col((@index + 1), ~"@{list}, @{item}"); |
|
||||||
} |
|
||||||
.col(@index, @list) when (@index > @grid-columns) { // terminal |
|
||||||
@{list} { |
|
||||||
float: left; |
|
||||||
} |
|
||||||
} |
|
||||||
.col(1); // kickstart it |
|
||||||
} |
|
||||||
|
|
||||||
.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) { |
|
||||||
.col-@{class}-@{index} { |
|
||||||
width: percentage((@index / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.calc-grid-column(@index, @class, @type) when (@type = push) { |
|
||||||
.col-@{class}-push-@{index} { |
|
||||||
left: percentage((@index / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.calc-grid-column(@index, @class, @type) when (@type = pull) { |
|
||||||
.col-@{class}-pull-@{index} { |
|
||||||
right: percentage((@index / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
.calc-grid-column(@index, @class, @type) when (@type = offset) { |
|
||||||
.col-@{class}-offset-@{index} { |
|
||||||
margin-left: percentage((@index / @grid-columns)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Basic looping in LESS |
|
||||||
.loop-grid-columns(@index, @class, @type) when (@index >= 0) { |
|
||||||
.calc-grid-column(@index, @class, @type); |
|
||||||
// next iteration |
|
||||||
.loop-grid-columns((@index - 1), @class, @type); |
|
||||||
} |
|
||||||
|
|
||||||
// Create grid for specific class |
|
||||||
.make-grid(@class) { |
|
||||||
.float-grid-columns(@class); |
|
||||||
.loop-grid-columns(@grid-columns, @class, width); |
|
||||||
.loop-grid-columns(@grid-columns, @class, pull); |
|
||||||
.loop-grid-columns(@grid-columns, @class, push); |
|
||||||
.loop-grid-columns(@grid-columns, @class, offset); |
|
||||||
} |
|
||||||
|
|
||||||
// Form validation states |
|
||||||
// |
|
||||||
// Used in forms.less to generate the form validation CSS for warnings, errors, |
|
||||||
// and successes. |
|
||||||
|
|
||||||
.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) { |
|
||||||
// Color the label and help text |
|
||||||
.help-block, |
|
||||||
.control-label, |
|
||||||
.radio, |
|
||||||
.checkbox, |
|
||||||
.radio-inline, |
|
||||||
.checkbox-inline { |
|
||||||
color: @text-color; |
|
||||||
} |
|
||||||
// Set the border and box shadow on specific inputs to match |
|
||||||
.form-control { |
|
||||||
border-color: @border-color; |
|
||||||
.box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work |
|
||||||
&:focus { |
|
||||||
border-color: darken(@border-color, 10%); |
|
||||||
@shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%); |
|
||||||
.box-shadow(@shadow); |
|
||||||
} |
|
||||||
} |
|
||||||
// Set validation states also for addons |
|
||||||
.input-group-addon { |
|
||||||
color: @text-color; |
|
||||||
border-color: @border-color; |
|
||||||
background-color: @background-color; |
|
||||||
} |
|
||||||
// Optional feedback icon |
|
||||||
.form-control-feedback { |
|
||||||
color: @text-color; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Form control focus state |
|
||||||
// |
|
||||||
// Generate a customized focus state and for any input with the specified color, |
|
||||||
// which defaults to the `@input-focus-border` variable. |
|
||||||
// |
|
||||||
// We highly encourage you to not customize the default value, but instead use |
|
||||||
// this to tweak colors on an as-needed basis. This aesthetic change is based on |
|
||||||
// WebKit's default styles, but applicable to a wider range of browsers. Its |
|
||||||
// usability and accessibility should be taken into account with any change. |
|
||||||
// |
|
||||||
// Example usage: change the default blue border and shadow to white for better |
|
||||||
// contrast against a dark gray background. |
|
||||||
|
|
||||||
.form-control-focus(@color: @input-border-focus) { |
|
||||||
@color-rgba: rgba(red(@color), green(@color), blue(@color), .6); |
|
||||||
&:focus { |
|
||||||
border-color: @color; |
|
||||||
outline: 0; |
|
||||||
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Form control sizing |
|
||||||
// |
|
||||||
// Relative text size, padding, and border-radii changes for form controls. For |
|
||||||
// horizontal sizing, wrap controls in the predefined grid classes. `<select>` |
|
||||||
// element gets special love because it's special, and that's a fact! |
|
||||||
|
|
||||||
.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { |
|
||||||
height: @input-height; |
|
||||||
padding: @padding-vertical @padding-horizontal; |
|
||||||
font-size: @font-size; |
|
||||||
line-height: @line-height; |
|
||||||
border-radius: @border-radius; |
|
||||||
|
|
||||||
select& { |
|
||||||
height: @input-height; |
|
||||||
line-height: @input-height; |
|
||||||
} |
|
||||||
|
|
||||||
textarea&, |
|
||||||
select[multiple]& { |
|
||||||
height: auto; |
|
||||||
} |
|
||||||
} |
|
||||||
|
@ -0,0 +1,14 @@ |
|||||||
|
// Alerts |
||||||
|
|
||||||
|
.alert-variant(@background; @border; @text-color) { |
||||||
|
background-color: @background; |
||||||
|
border-color: @border; |
||||||
|
color: @text-color; |
||||||
|
|
||||||
|
hr { |
||||||
|
border-top-color: darken(@border, 5%); |
||||||
|
} |
||||||
|
.alert-link { |
||||||
|
color: darken(@text-color, 10%); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
// Contextual backgrounds |
||||||
|
|
||||||
|
.bg-variant(@color) { |
||||||
|
background-color: @color; |
||||||
|
a&:hover { |
||||||
|
background-color: darken(@color, 10%); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
// Single side border-radius |
||||||
|
|
||||||
|
.border-top-radius(@radius) { |
||||||
|
border-top-right-radius: @radius; |
||||||
|
border-top-left-radius: @radius; |
||||||
|
} |
||||||
|
.border-right-radius(@radius) { |
||||||
|
border-bottom-right-radius: @radius; |
||||||
|
border-top-right-radius: @radius; |
||||||
|
} |
||||||
|
.border-bottom-radius(@radius) { |
||||||
|
border-bottom-right-radius: @radius; |
||||||
|
border-bottom-left-radius: @radius; |
||||||
|
} |
||||||
|
.border-left-radius(@radius) { |
||||||
|
border-bottom-left-radius: @radius; |
||||||
|
border-top-left-radius: @radius; |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
// Button variants |
||||||
|
// |
||||||
|
// Easily pump out default styles, as well as :hover, :focus, :active, |
||||||
|
// and disabled options for all buttons |
||||||
|
|
||||||
|
.button-variant(@color; @background; @border) { |
||||||
|
color: @color; |
||||||
|
background-color: @background; |
||||||
|
border-color: @border; |
||||||
|
|
||||||
|
&:hover, |
||||||
|
&:focus, |
||||||
|
&:active, |
||||||
|
&.active, |
||||||
|
.open > .dropdown-toggle& { |
||||||
|
color: @color; |
||||||
|
background-color: darken(@background, 10%); |
||||||
|
border-color: darken(@border, 12%); |
||||||
|
} |
||||||
|
&:active, |
||||||
|
&.active, |
||||||
|
.open > .dropdown-toggle& { |
||||||
|
background-image: none; |
||||||
|
} |
||||||
|
&.disabled, |
||||||
|
&[disabled], |
||||||
|
fieldset[disabled] & { |
||||||
|
&, |
||||||
|
&:hover, |
||||||
|
&:focus, |
||||||
|
&:active, |
||||||
|
&.active { |
||||||
|
background-color: @background; |
||||||
|
border-color: @border; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.badge { |
||||||
|
color: @background; |
||||||
|
background-color: @color; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Button sizes |
||||||
|
.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { |
||||||
|
padding: @padding-vertical @padding-horizontal; |
||||||
|
font-size: @font-size; |
||||||
|
line-height: @line-height; |
||||||
|
border-radius: @border-radius; |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
// Center-align a block level element |
||||||
|
|
||||||
|
.center-block() { |
||||||
|
display: block; |
||||||
|
margin-left: auto; |
||||||
|
margin-right: auto; |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
// Clearfix |
||||||
|
// |
||||||
|
// For modern browsers |
||||||
|
// 1. The space content is one way to avoid an Opera bug when the |
||||||
|
// contenteditable attribute is included anywhere else in the document. |
||||||
|
// Otherwise it causes space to appear at the top and bottom of elements |
||||||
|
// that are clearfixed. |
||||||
|
// 2. The use of `table` rather than `block` is only necessary if using |
||||||
|
// `:before` to contain the top-margins of child elements. |
||||||
|
// |
||||||
|
// Source: http://nicolasgallagher.com/micro-clearfix-hack/ |
||||||
|
|
||||||
|
.clearfix() { |
||||||
|
&:before, |
||||||
|
&:after { |
||||||
|
content: " "; // 1 |
||||||
|
display: table; // 2 |
||||||
|
} |
||||||
|
&:after { |
||||||
|
clear: both; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
// Form validation states |
||||||
|
// |
||||||
|
// Used in forms.less to generate the form validation CSS for warnings, errors, |
||||||
|
// and successes. |
||||||
|
|
||||||
|
.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) { |
||||||
|
// Color the label and help text |
||||||
|
.help-block, |
||||||
|
.control-label, |
||||||
|
.radio, |
||||||
|
.checkbox, |
||||||
|
.radio-inline, |
||||||
|
.checkbox-inline { |
||||||
|
color: @text-color; |
||||||
|
} |
||||||
|
// Set the border and box shadow on specific inputs to match |
||||||
|
.form-control { |
||||||
|
border-color: @border-color; |
||||||
|
.box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work |
||||||
|
&:focus { |
||||||
|
border-color: darken(@border-color, 10%); |
||||||
|
@shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%); |
||||||
|
.box-shadow(@shadow); |
||||||
|
} |
||||||
|
} |
||||||
|
// Set validation states also for addons |
||||||
|
.input-group-addon { |
||||||
|
color: @text-color; |
||||||
|
border-color: @border-color; |
||||||
|
background-color: @background-color; |
||||||
|
} |
||||||
|
// Optional feedback icon |
||||||
|
.form-control-feedback { |
||||||
|
color: @text-color; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Form control focus state |
||||||
|
// |
||||||
|
// Generate a customized focus state and for any input with the specified color, |
||||||
|
// which defaults to the `@input-border-focus` variable. |
||||||
|
// |
||||||
|
// We highly encourage you to not customize the default value, but instead use |
||||||
|
// this to tweak colors on an as-needed basis. This aesthetic change is based on |
||||||
|
// WebKit's default styles, but applicable to a wider range of browsers. Its |
||||||
|
// usability and accessibility should be taken into account with any change. |
||||||
|
// |
||||||
|
// Example usage: change the default blue border and shadow to white for better |
||||||
|
// contrast against a dark gray background. |
||||||
|
.form-control-focus(@color: @input-border-focus) { |
||||||
|
@color-rgba: rgba(red(@color), green(@color), blue(@color), .6); |
||||||
|
&:focus { |
||||||
|
border-color: @color; |
||||||
|
outline: 0; |
||||||
|
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Form control sizing |
||||||
|
// |
||||||
|
// Relative text size, padding, and border-radii changes for form controls. For |
||||||
|
// horizontal sizing, wrap controls in the predefined grid classes. `<select>` |
||||||
|
// element gets special love because it's special, and that's a fact! |
||||||
|
.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { |
||||||
|
height: @input-height; |
||||||
|
padding: @padding-vertical @padding-horizontal; |
||||||
|
font-size: @font-size; |
||||||
|
line-height: @line-height; |
||||||
|
border-radius: @border-radius; |
||||||
|
|
||||||
|
select& { |
||||||
|
height: @input-height; |
||||||
|
line-height: @input-height; |
||||||
|
} |
||||||
|
|
||||||
|
textarea&, |
||||||
|
select[multiple]& { |
||||||
|
height: auto; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
// Gradients |
||||||
|
|
||||||
|
#gradient { |
||||||
|
|
||||||
|
// Horizontal gradient, from left to right |
||||||
|
// |
||||||
|
// Creates two color stops, start and end, by specifying a color and position for each color stop. |
||||||
|
// Color stops are not available in IE9 and below. |
||||||
|
.horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) { |
||||||
|
background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+ |
||||||
|
background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12 |
||||||
|
background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ |
||||||
|
background-repeat: repeat-x; |
||||||
|
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down |
||||||
|
} |
||||||
|
|
||||||
|
// Vertical gradient, from top to bottom |
||||||
|
// |
||||||
|
// Creates two color stops, start and end, by specifying a color and position for each color stop. |
||||||
|
// Color stops are not available in IE9 and below. |
||||||
|
.vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) { |
||||||
|
background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+ |
||||||
|
background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12 |
||||||
|
background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ |
||||||
|
background-repeat: repeat-x; |
||||||
|
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down |
||||||
|
} |
||||||
|
|
||||||
|
.directional(@start-color: #555; @end-color: #333; @deg: 45deg) { |
||||||
|
background-repeat: repeat-x; |
||||||
|
background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+ |
||||||
|
background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12 |
||||||
|
background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ |
||||||
|
} |
||||||
|
.horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { |
||||||
|
background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color); |
||||||
|
background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color); |
||||||
|
background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color); |
||||||
|
background-repeat: no-repeat; |
||||||
|
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback |
||||||
|
} |
||||||
|
.vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { |
||||||
|
background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color); |
||||||
|
background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color); |
||||||
|
background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color); |
||||||
|
background-repeat: no-repeat; |
||||||
|
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback |
||||||
|
} |
||||||
|
.radial(@inner-color: #555; @outer-color: #333) { |
||||||
|
background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color); |
||||||
|
background-image: radial-gradient(circle, @inner-color, @outer-color); |
||||||
|
background-repeat: no-repeat; |
||||||
|
} |
||||||
|
.striped(@color: rgba(255,255,255,.15); @angle: 45deg) { |
||||||
|
background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); |
||||||
|
background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); |
||||||
|
background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,91 @@ |
|||||||
|
// Framework grid generation |
||||||
|
// |
||||||
|
// Used only by Bootstrap to generate the correct number of grid classes given |
||||||
|
// any value of `@grid-columns`. |
||||||
|
|
||||||
|
.make-grid-columns() { |
||||||
|
// Common styles for all sizes of grid columns, widths 1-12 |
||||||
|
.col(@index) when (@index = 1) { // initial |
||||||
|
@item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; |
||||||
|
.col((@index + 1), @item); |
||||||
|
} |
||||||
|
.col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo |
||||||
|
@item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; |
||||||
|
.col((@index + 1), ~"@{list}, @{item}"); |
||||||
|
} |
||||||
|
.col(@index, @list) when (@index > @grid-columns) { // terminal |
||||||
|
@{list} { |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
.col(1); // kickstart it |
||||||
|
} |
||||||
|
|
||||||
|
.float-grid-columns(@class) { |
||||||
|
.col(@index) when (@index = 1) { // initial |
||||||
|
@item: ~".col-@{class}-@{index}"; |
||||||
|
.col((@index + 1), @item); |
||||||
|
} |
||||||
|
.col(@index, @list) when (@index =< @grid-columns) { // general |
||||||
|
@item: ~".col-@{class}-@{index}"; |
||||||
|
.col((@index + 1), ~"@{list}, @{item}"); |
||||||
|
} |
||||||
|
.col(@index, @list) when (@index > @grid-columns) { // terminal |
||||||
|
@{list} { |
||||||
|
float: left; |
||||||
|
} |
||||||
|
} |
||||||
|
.col(1); // kickstart it |
||||||
|
} |
||||||
|
|
||||||
|
.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) { |
||||||
|
.col-@{class}-@{index} { |
||||||
|
width: percentage((@index / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) { |
||||||
|
.col-@{class}-push-@{index} { |
||||||
|
left: percentage((@index / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) { |
||||||
|
.col-@{class}-push-0 { |
||||||
|
left: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) { |
||||||
|
.col-@{class}-pull-@{index} { |
||||||
|
right: percentage((@index / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) { |
||||||
|
.col-@{class}-pull-0 { |
||||||
|
right: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
.calc-grid-column(@index, @class, @type) when (@type = offset) { |
||||||
|
.col-@{class}-offset-@{index} { |
||||||
|
margin-left: percentage((@index / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Basic looping in LESS |
||||||
|
.loop-grid-columns(@index, @class, @type) when (@index >= 0) { |
||||||
|
.calc-grid-column(@index, @class, @type); |
||||||
|
// next iteration |
||||||
|
.loop-grid-columns((@index - 1), @class, @type); |
||||||
|
} |
||||||
|
|
||||||
|
// Create grid for specific class |
||||||
|
.make-grid(@class) { |
||||||
|
.float-grid-columns(@class); |
||||||
|
.loop-grid-columns(@grid-columns, @class, width); |
||||||
|
.loop-grid-columns(@grid-columns, @class, pull); |
||||||
|
.loop-grid-columns(@grid-columns, @class, push); |
||||||
|
.loop-grid-columns(@grid-columns, @class, offset); |
||||||
|
} |
@ -0,0 +1,122 @@ |
|||||||
|
// Grid system |
||||||
|
// |
||||||
|
// Generate semantic grid columns with these mixins. |
||||||
|
|
||||||
|
// Centered container element |
||||||
|
.container-fixed(@gutter: @grid-gutter-width) { |
||||||
|
margin-right: auto; |
||||||
|
margin-left: auto; |
||||||
|
padding-left: (@gutter / 2); |
||||||
|
padding-right: (@gutter / 2); |
||||||
|
&:extend(.clearfix all); |
||||||
|
} |
||||||
|
|
||||||
|
// Creates a wrapper for a series of columns |
||||||
|
.make-row(@gutter: @grid-gutter-width) { |
||||||
|
margin-left: (@gutter / -2); |
||||||
|
margin-right: (@gutter / -2); |
||||||
|
&:extend(.clearfix all); |
||||||
|
} |
||||||
|
|
||||||
|
// Generate the extra small columns |
||||||
|
.make-xs-column(@columns; @gutter: @grid-gutter-width) { |
||||||
|
position: relative; |
||||||
|
float: left; |
||||||
|
width: percentage((@columns / @grid-columns)); |
||||||
|
min-height: 1px; |
||||||
|
padding-left: (@gutter / 2); |
||||||
|
padding-right: (@gutter / 2); |
||||||
|
} |
||||||
|
.make-xs-column-offset(@columns) { |
||||||
|
margin-left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
.make-xs-column-push(@columns) { |
||||||
|
left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
.make-xs-column-pull(@columns) { |
||||||
|
right: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
|
||||||
|
// Generate the small columns |
||||||
|
.make-sm-column(@columns; @gutter: @grid-gutter-width) { |
||||||
|
position: relative; |
||||||
|
min-height: 1px; |
||||||
|
padding-left: (@gutter / 2); |
||||||
|
padding-right: (@gutter / 2); |
||||||
|
|
||||||
|
@media (min-width: @screen-sm-min) { |
||||||
|
float: left; |
||||||
|
width: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-sm-column-offset(@columns) { |
||||||
|
@media (min-width: @screen-sm-min) { |
||||||
|
margin-left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-sm-column-push(@columns) { |
||||||
|
@media (min-width: @screen-sm-min) { |
||||||
|
left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-sm-column-pull(@columns) { |
||||||
|
@media (min-width: @screen-sm-min) { |
||||||
|
right: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Generate the medium columns |
||||||
|
.make-md-column(@columns; @gutter: @grid-gutter-width) { |
||||||
|
position: relative; |
||||||
|
min-height: 1px; |
||||||
|
padding-left: (@gutter / 2); |
||||||
|
padding-right: (@gutter / 2); |
||||||
|
|
||||||
|
@media (min-width: @screen-md-min) { |
||||||
|
float: left; |
||||||
|
width: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-md-column-offset(@columns) { |
||||||
|
@media (min-width: @screen-md-min) { |
||||||
|
margin-left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-md-column-push(@columns) { |
||||||
|
@media (min-width: @screen-md-min) { |
||||||
|
left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-md-column-pull(@columns) { |
||||||
|
@media (min-width: @screen-md-min) { |
||||||
|
right: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Generate the large columns |
||||||
|
.make-lg-column(@columns; @gutter: @grid-gutter-width) { |
||||||
|
position: relative; |
||||||
|
min-height: 1px; |
||||||
|
padding-left: (@gutter / 2); |
||||||
|
padding-right: (@gutter / 2); |
||||||
|
|
||||||
|
@media (min-width: @screen-lg-min) { |
||||||
|
float: left; |
||||||
|
width: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-lg-column-offset(@columns) { |
||||||
|
@media (min-width: @screen-lg-min) { |
||||||
|
margin-left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-lg-column-push(@columns) { |
||||||
|
@media (min-width: @screen-lg-min) { |
||||||
|
left: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
||||||
|
.make-lg-column-pull(@columns) { |
||||||
|
@media (min-width: @screen-lg-min) { |
||||||
|
right: percentage((@columns / @grid-columns)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
// CSS image replacement |
||||||
|
// |
||||||
|
// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for |
||||||
|
// mixins being reused as classes with the same name, this doesn't hold up. As |
||||||
|
// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. |
||||||
|
// |
||||||
|
// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757 |
||||||
|
|
||||||
|
// Deprecated as of v3.0.1 (will be removed in v4) |
||||||
|
.hide-text() { |
||||||
|
font: ~"0/0" a; |
||||||
|
color: transparent; |
||||||
|
text-shadow: none; |
||||||
|
background-color: transparent; |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
|
||||||
|
// New mixin to use as of v3.0.1 |
||||||
|
.text-hide() { |
||||||
|
.hide-text(); |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// Image Mixins |
||||||
|
// - Responsive image |
||||||
|
// - Retina image |
||||||
|
|
||||||
|
|
||||||
|
// Responsive image |
||||||
|
// |
||||||
|
// Keep images from scaling beyond the width of their parents. |
||||||
|
.img-responsive(@display: block) { |
||||||
|
display: @display; |
||||||
|
width: 100% \9; // Force IE10 and below to size SVG images correctly |
||||||
|
max-width: 100%; // Part 1: Set a maximum relative to the parent |
||||||
|
height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Retina image |
||||||
|
// |
||||||
|
// Short retina mixin for setting background-image and -size. Note that the |
||||||
|
// spelling of `min--moz-device-pixel-ratio` is intentional. |
||||||
|
.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) { |
||||||
|
background-image: url("@{file-1x}"); |
||||||
|
|
||||||
|
@media |
||||||
|
only screen and (-webkit-min-device-pixel-ratio: 2), |
||||||
|
only screen and ( min--moz-device-pixel-ratio: 2), |
||||||
|
only screen and ( -o-min-device-pixel-ratio: 2/1), |
||||||
|
only screen and ( min-device-pixel-ratio: 2), |
||||||
|
only screen and ( min-resolution: 192dpi), |
||||||
|
only screen and ( min-resolution: 2dppx) { |
||||||
|
background-image: url("@{file-2x}"); |
||||||
|
background-size: @width-1x @height-1x; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
// Labels |
||||||
|
|
||||||
|
.label-variant(@color) { |
||||||
|
background-color: @color; |
||||||
|
|
||||||
|
&[href] { |
||||||
|
&:hover, |
||||||
|
&:focus { |
||||||
|
background-color: darken(@color, 10%); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
// List Groups |
||||||
|
|
||||||
|
.list-group-item-variant(@state; @background; @color) { |
||||||
|
.list-group-item-@{state} { |
||||||
|
color: @color; |
||||||
|
background-color: @background; |
||||||
|
|
||||||
|
a& { |
||||||
|
color: @color; |
||||||
|
|
||||||
|
.list-group-item-heading { |
||||||
|
color: inherit; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover, |
||||||
|
&:focus { |
||||||
|
color: @color; |
||||||
|
background-color: darken(@background, 5%); |
||||||
|
} |
||||||
|
&.active, |
||||||
|
&.active:hover, |
||||||
|
&.active:focus { |
||||||
|
color: #fff; |
||||||
|
background-color: @color; |
||||||
|
border-color: @color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
// Horizontal dividers |
||||||
|
// |
||||||
|
// Dividers (basically an hr) within dropdowns and nav lists |
||||||
|
|
||||||
|
.nav-divider(@color: #e5e5e5) { |
||||||
|
height: 1px; |
||||||
|
margin: ((@line-height-computed / 2) - 1) 0; |
||||||
|
overflow: hidden; |
||||||
|
background-color: @color; |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
// Navbar vertical align |
||||||
|
// |
||||||
|
// Vertically center elements in the navbar. |
||||||
|
// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin. |
||||||
|
|
||||||
|
.navbar-vertical-align(@element-height) { |
||||||
|
margin-top: ((@navbar-height - @element-height) / 2); |
||||||
|
margin-bottom: ((@navbar-height - @element-height) / 2); |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
// Opacity |
||||||
|
|
||||||
|
.opacity(@opacity) { |
||||||
|
opacity: @opacity; |
||||||
|
// IE8 filter |
||||||
|
@opacity-ie: (@opacity * 100); |
||||||
|
filter: ~"alpha(opacity=@{opacity-ie})"; |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
// Pagination |
||||||
|
|
||||||
|
.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) { |
||||||
|
> li { |
||||||
|
> a, |
||||||
|
> span { |
||||||
|
padding: @padding-vertical @padding-horizontal; |
||||||
|
font-size: @font-size; |
||||||
|
} |
||||||
|
&:first-child { |
||||||
|
> a, |
||||||
|
> span { |
||||||
|
.border-left-radius(@border-radius); |
||||||
|
} |
||||||
|
} |
||||||
|
&:last-child { |
||||||
|
> a, |
||||||
|
> span { |
||||||
|
.border-right-radius(@border-radius); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
// Panels |
||||||
|
|
||||||
|
.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) { |
||||||
|
border-color: @border; |
||||||
|
|
||||||
|
& > .panel-heading { |
||||||
|
color: @heading-text-color; |
||||||
|
background-color: @heading-bg-color; |
||||||
|
border-color: @heading-border; |
||||||
|
|
||||||
|
+ .panel-collapse > .panel-body { |
||||||
|
border-top-color: @border; |
||||||
|
} |
||||||
|
.badge { |
||||||
|
color: @heading-bg-color; |
||||||
|
background-color: @heading-text-color; |
||||||
|
} |
||||||
|
} |
||||||
|
& > .panel-footer { |
||||||
|
+ .panel-collapse > .panel-body { |
||||||
|
border-bottom-color: @border; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
// Progress bars |
||||||
|
|
||||||
|
.progress-bar-variant(@color) { |
||||||
|
background-color: @color; |
||||||
|
|
||||||
|
// Deprecated parent class requirement as of v3.2.0 |
||||||
|
.progress-striped & { |
||||||
|
#gradient > .striped(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
// Reset filters for IE |
||||||
|
// |
||||||
|
// When you need to remove a gradient background, do not forget to use this to reset |
||||||
|
// the IE filter for IE9 and below. |
||||||
|
|
||||||
|
.reset-filter() { |
||||||
|
filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)")); |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
// Resize anything |
||||||
|
|
||||||
|
.resizable(@direction) { |
||||||
|
resize: @direction; // Options: horizontal, vertical, both |
||||||
|
overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible` |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
// Responsive utilities |
||||||
|
|
||||||
|
// |
||||||
|
// More easily include all the states for responsive-utilities.less. |
||||||
|
.responsive-visibility() { |
||||||
|
display: block !important; |
||||||
|
table& { display: table; } |
||||||
|
tr& { display: table-row !important; } |
||||||
|
th&, |
||||||
|
td& { display: table-cell !important; } |
||||||
|
} |
||||||
|
|
||||||
|
.responsive-invisibility() { |
||||||
|
display: none !important; |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
// Sizing shortcuts |
||||||
|
|
||||||
|
.size(@width; @height) { |
||||||
|
width: @width; |
||||||
|
height: @height; |
||||||
|
} |
||||||
|
|
||||||
|
.square(@size) { |
||||||
|
.size(@size; @size); |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
// WebKit-style focus |
||||||
|
|
||||||
|
.tab-focus() { |
||||||
|
// Default |
||||||
|
outline: thin dotted; |
||||||
|
// WebKit |
||||||
|
outline: 5px auto -webkit-focus-ring-color; |
||||||
|
outline-offset: -2px; |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
// Tables |
||||||
|
|
||||||
|
.table-row-variant(@state; @background) { |
||||||
|
// Exact selectors below required to override `.table-striped` and prevent |
||||||
|
// inheritance to nested tables. |
||||||
|
.table > thead > tr, |
||||||
|
.table > tbody > tr, |
||||||
|
.table > tfoot > tr { |
||||||
|
> td.@{state}, |
||||||
|
> th.@{state}, |
||||||
|
&.@{state} > td, |
||||||
|
&.@{state} > th { |
||||||
|
background-color: @background; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 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%); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
// Typography |
||||||
|
|
||||||
|
.text-emphasis-variant(@color) { |
||||||
|
color: @color; |
||||||
|
a&:hover { |
||||||
|
color: darken(@color, 10%); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
// Text overflow |
||||||
|
// Requires inline-block or block for proper styling |
||||||
|
|
||||||
|
.text-overflow() { |
||||||
|
overflow: hidden; |
||||||
|
text-overflow: ellipsis; |
||||||
|
white-space: nowrap; |
||||||
|
} |
@ -0,0 +1,224 @@ |
|||||||
|
// Vendor Prefixes |
||||||
|
// |
||||||
|
// All vendor mixins are deprecated as of v3.2.0 due to the introduction of |
||||||
|
// Autoprefixer in our Gruntfile. They will be removed in v4. |
||||||
|
|
||||||
|
// - Animations |
||||||
|
// - Backface visibility |
||||||
|
// - Box shadow |
||||||
|
// - Box sizing |
||||||
|
// - Content columns |
||||||
|
// - Hyphens |
||||||
|
// - Placeholder text |
||||||
|
// - Transformations |
||||||
|
// - Transitions |
||||||
|
// - User Select |
||||||
|
|
||||||
|
|
||||||
|
// Animations |
||||||
|
.animation(@animation) { |
||||||
|
-webkit-animation: @animation; |
||||||
|
-o-animation: @animation; |
||||||
|
animation: @animation; |
||||||
|
} |
||||||
|
.animation-name(@name) { |
||||||
|
-webkit-animation-name: @name; |
||||||
|
animation-name: @name; |
||||||
|
} |
||||||
|
.animation-duration(@duration) { |
||||||
|
-webkit-animation-duration: @duration; |
||||||
|
animation-duration: @duration; |
||||||
|
} |
||||||
|
.animation-timing-function(@timing-function) { |
||||||
|
-webkit-animation-timing-function: @timing-function; |
||||||
|
animation-timing-function: @timing-function; |
||||||
|
} |
||||||
|
.animation-delay(@delay) { |
||||||
|
-webkit-animation-delay: @delay; |
||||||
|
animation-delay: @delay; |
||||||
|
} |
||||||
|
.animation-iteration-count(@iteration-count) { |
||||||
|
-webkit-animation-iteration-count: @iteration-count; |
||||||
|
animation-iteration-count: @iteration-count; |
||||||
|
} |
||||||
|
.animation-direction(@direction) { |
||||||
|
-webkit-animation-direction: @direction; |
||||||
|
animation-direction: @direction; |
||||||
|
} |
||||||
|
.animation-fill-mode(@fill-mode) { |
||||||
|
-webkit-animation-fill-mode: @fill-mode; |
||||||
|
animation-fill-mode: @fill-mode; |
||||||
|
} |
||||||
|
|
||||||
|
// Backface visibility |
||||||
|
// Prevent browsers from flickering when using CSS 3D transforms. |
||||||
|
// Default value is `visible`, but can be changed to `hidden` |
||||||
|
|
||||||
|
.backface-visibility(@visibility){ |
||||||
|
-webkit-backface-visibility: @visibility; |
||||||
|
-moz-backface-visibility: @visibility; |
||||||
|
backface-visibility: @visibility; |
||||||
|
} |
||||||
|
|
||||||
|
// Drop shadows |
||||||
|
// |
||||||
|
// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's |
||||||
|
// supported browsers that have box shadow capabilities now support it. |
||||||
|
|
||||||
|
.box-shadow(@shadow) { |
||||||
|
-webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1 |
||||||
|
box-shadow: @shadow; |
||||||
|
} |
||||||
|
|
||||||
|
// Box sizing |
||||||
|
.box-sizing(@boxmodel) { |
||||||
|
-webkit-box-sizing: @boxmodel; |
||||||
|
-moz-box-sizing: @boxmodel; |
||||||
|
box-sizing: @boxmodel; |
||||||
|
} |
||||||
|
|
||||||
|
// CSS3 Content Columns |
||||||
|
.content-columns(@column-count; @column-gap: @grid-gutter-width) { |
||||||
|
-webkit-column-count: @column-count; |
||||||
|
-moz-column-count: @column-count; |
||||||
|
column-count: @column-count; |
||||||
|
-webkit-column-gap: @column-gap; |
||||||
|
-moz-column-gap: @column-gap; |
||||||
|
column-gap: @column-gap; |
||||||
|
} |
||||||
|
|
||||||
|
// Optional hyphenation |
||||||
|
.hyphens(@mode: auto) { |
||||||
|
word-wrap: break-word; |
||||||
|
-webkit-hyphens: @mode; |
||||||
|
-moz-hyphens: @mode; |
||||||
|
-ms-hyphens: @mode; // IE10+ |
||||||
|
-o-hyphens: @mode; |
||||||
|
hyphens: @mode; |
||||||
|
} |
||||||
|
|
||||||
|
// Placeholder text |
||||||
|
.placeholder(@color: @input-color-placeholder) { |
||||||
|
&::-moz-placeholder { color: @color; // Firefox |
||||||
|
opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526 |
||||||
|
&:-ms-input-placeholder { color: @color; } // Internet Explorer 10+ |
||||||
|
&::-webkit-input-placeholder { color: @color; } // Safari and Chrome |
||||||
|
} |
||||||
|
|
||||||
|
// Transformations |
||||||
|
.scale(@ratio) { |
||||||
|
-webkit-transform: scale(@ratio); |
||||||
|
-ms-transform: scale(@ratio); // IE9 only |
||||||
|
-o-transform: scale(@ratio); |
||||||
|
transform: scale(@ratio); |
||||||
|
} |
||||||
|
.scale(@ratioX; @ratioY) { |
||||||
|
-webkit-transform: scale(@ratioX, @ratioY); |
||||||
|
-ms-transform: scale(@ratioX, @ratioY); // IE9 only |
||||||
|
-o-transform: scale(@ratioX, @ratioY); |
||||||
|
transform: scale(@ratioX, @ratioY); |
||||||
|
} |
||||||
|
.scaleX(@ratio) { |
||||||
|
-webkit-transform: scaleX(@ratio); |
||||||
|
-ms-transform: scaleX(@ratio); // IE9 only |
||||||
|
-o-transform: scaleX(@ratio); |
||||||
|
transform: scaleX(@ratio); |
||||||
|
} |
||||||
|
.scaleY(@ratio) { |
||||||
|
-webkit-transform: scaleY(@ratio); |
||||||
|
-ms-transform: scaleY(@ratio); // IE9 only |
||||||
|
-o-transform: scaleY(@ratio); |
||||||
|
transform: scaleY(@ratio); |
||||||
|
} |
||||||
|
.skew(@x; @y) { |
||||||
|
-webkit-transform: skewX(@x) skewY(@y); |
||||||
|
-ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+ |
||||||
|
-o-transform: skewX(@x) skewY(@y); |
||||||
|
transform: skewX(@x) skewY(@y); |
||||||
|
} |
||||||
|
.translate(@x; @y) { |
||||||
|
-webkit-transform: translate(@x, @y); |
||||||
|
-ms-transform: translate(@x, @y); // IE9 only |
||||||
|
-o-transform: translate(@x, @y); |
||||||
|
transform: translate(@x, @y); |
||||||
|
} |
||||||
|
.translate3d(@x; @y; @z) { |
||||||
|
-webkit-transform: translate3d(@x, @y, @z); |
||||||
|
transform: translate3d(@x, @y, @z); |
||||||
|
} |
||||||
|
.rotate(@degrees) { |
||||||
|
-webkit-transform: rotate(@degrees); |
||||||
|
-ms-transform: rotate(@degrees); // IE9 only |
||||||
|
-o-transform: rotate(@degrees); |
||||||
|
transform: rotate(@degrees); |
||||||
|
} |
||||||
|
.rotateX(@degrees) { |
||||||
|
-webkit-transform: rotateX(@degrees); |
||||||
|
-ms-transform: rotateX(@degrees); // IE9 only |
||||||
|
-o-transform: rotateX(@degrees); |
||||||
|
transform: rotateX(@degrees); |
||||||
|
} |
||||||
|
.rotateY(@degrees) { |
||||||
|
-webkit-transform: rotateY(@degrees); |
||||||
|
-ms-transform: rotateY(@degrees); // IE9 only |
||||||
|
-o-transform: rotateY(@degrees); |
||||||
|
transform: rotateY(@degrees); |
||||||
|
} |
||||||
|
.perspective(@perspective) { |
||||||
|
-webkit-perspective: @perspective; |
||||||
|
-moz-perspective: @perspective; |
||||||
|
perspective: @perspective; |
||||||
|
} |
||||||
|
.perspective-origin(@perspective) { |
||||||
|
-webkit-perspective-origin: @perspective; |
||||||
|
-moz-perspective-origin: @perspective; |
||||||
|
perspective-origin: @perspective; |
||||||
|
} |
||||||
|
.transform-origin(@origin) { |
||||||
|
-webkit-transform-origin: @origin; |
||||||
|
-moz-transform-origin: @origin; |
||||||
|
-ms-transform-origin: @origin; // IE9 only |
||||||
|
transform-origin: @origin; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Transitions |
||||||
|
|
||||||
|
.transition(@transition) { |
||||||
|
-webkit-transition: @transition; |
||||||
|
-o-transition: @transition; |
||||||
|
transition: @transition; |
||||||
|
} |
||||||
|
.transition-property(@transition-property) { |
||||||
|
-webkit-transition-property: @transition-property; |
||||||
|
transition-property: @transition-property; |
||||||
|
} |
||||||
|
.transition-delay(@transition-delay) { |
||||||
|
-webkit-transition-delay: @transition-delay; |
||||||
|
transition-delay: @transition-delay; |
||||||
|
} |
||||||
|
.transition-duration(@transition-duration) { |
||||||
|
-webkit-transition-duration: @transition-duration; |
||||||
|
transition-duration: @transition-duration; |
||||||
|
} |
||||||
|
.transition-timing-function(@timing-function) { |
||||||
|
-webkit-transition-timing-function: @timing-function; |
||||||
|
transition-timing-function: @timing-function; |
||||||
|
} |
||||||
|
.transition-transform(@transition) { |
||||||
|
-webkit-transition: -webkit-transform @transition; |
||||||
|
-moz-transition: -moz-transform @transition; |
||||||
|
-o-transition: -o-transform @transition; |
||||||
|
transition: transform @transition; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// User select |
||||||
|
// For selecting text on the page |
||||||
|
|
||||||
|
.user-select(@select) { |
||||||
|
-webkit-user-select: @select; |
||||||
|
-moz-user-select: @select; |
||||||
|
-ms-user-select: @select; // IE10+ |
||||||
|
user-select: @select; |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// Embeds responsive |
||||||
|
// |
||||||
|
// Credit: Nicolas Gallagher and SUIT CSS. |
||||||
|
|
||||||
|
.embed-responsive { |
||||||
|
position: relative; |
||||||
|
display: block; |
||||||
|
height: 0; |
||||||
|
padding: 0; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
.embed-responsive-item, |
||||||
|
iframe, |
||||||
|
embed, |
||||||
|
object { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
bottom: 0; |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Modifier class for 16:9 aspect ratio |
||||||
|
&.embed-responsive-16by9 { |
||||||
|
padding-bottom: 56.25%; |
||||||
|
} |
||||||
|
|
||||||
|
// Modifier class for 4:3 aspect ratio |
||||||
|
&.embed-responsive-4by3 { |
||||||
|
padding-bottom: 75%; |
||||||
|
} |
||||||
|
} |
@ -1,100 +0,0 @@ |
|||||||
## What does `s3_cache.py` do? |
|
||||||
|
|
||||||
### In general |
|
||||||
`s3_cache.py` maintains a cache, stored in an Amazon S3 (Simple Storage Service) bucket, of a given directory whose contents are considered non-critical and are completely & solely determined by (and should be able to be regenerated from) a single given file. |
|
||||||
|
|
||||||
The SHA-256 hash of the single file is used as the key for the cache. The directory is stored as a gzipped tarball. |
|
||||||
|
|
||||||
All the tarballs are stored in S3's Reduced Redundancy Storage (RRS) storage class, since this is cheaper and the data is non-critical. |
|
||||||
|
|
||||||
`s3_cache.py` itself never deletes cache entries; deletion should either be done manually or using automatic S3 lifecycle rules on the bucket. |
|
||||||
|
|
||||||
Similar to git, `s3_cache.py` makes the assumption that [SHA-256 will effectively never have a collision](http://stackoverflow.com/questions/4014090/is-it-safe-to-ignore-the-possibility-of-sha-collisions-in-practice). |
|
||||||
|
|
||||||
|
|
||||||
### For Bootstrap specifically |
|
||||||
`s3_cache.py` is used to cache the npm packages that our Grunt tasks depend on and the RubyGems that Jekyll depends on. (Jekyll is needed to compile our docs to HTML so that we can run them thru an HTML5 validator.) |
|
||||||
|
|
||||||
For npm, the `node_modules` directory is cached based on our `npm-shrinkwrap.canonical.json` file. |
|
||||||
|
|
||||||
For RubyGems, the `gemdir` of the current RVM-selected Ruby is cached based on the `pseudo_Gemfile.lock` file generated by our Travis build script. |
|
||||||
`pseudo_Gemfile.lock` contains the versions of Ruby and Jekyll that we're using (read our `.travis.yml` for details). |
|
||||||
|
|
||||||
|
|
||||||
## Why is `s3_cache.py` necessary? |
|
||||||
`s3_cache.py` is used to speed up Bootstrap's Travis builds. Installing npm packages and RubyGems used to take up a significant fraction of our total build times. Also, at the time that `s3_cache.py` was written, npm was occasionally unreliable. |
|
||||||
|
|
||||||
Travis does offer built-in caching on their paid plans, but this do-it-ourselves S3 solution is significantly cheaper since we only need caching and not Travis' other paid features. |
|
||||||
|
|
||||||
|
|
||||||
## Setup |
|
||||||
|
|
||||||
### Overview |
|
||||||
1. Create an Amazon Web Services (AWS) account. |
|
||||||
2. Create an Identity & Access Management (IAM) user, and note their credentials. |
|
||||||
3. Create an S3 bucket. |
|
||||||
4. Set permissions on the bucket to grant the user read+write access. |
|
||||||
5. Set the user credentials as secure Travis environment variables. |
|
||||||
|
|
||||||
### In detail |
|
||||||
1. Create an AWS account. |
|
||||||
2. Login to the [AWS Management Console](https://console.aws.amazon.com). |
|
||||||
3. Go to the IAM Management Console. |
|
||||||
4. Create a new user (named e.g. `travis-ci`) and generate an access key for them. Note both the Access Key ID and the Secret Access Key. |
|
||||||
5. Note the user's ARN (Amazon Resource Name), which can be found in the "Summary" tab of the user browser. This will be of the form: `arn:aws:iam::XXXXXXXXXXXXXX:user/the-username-goes-here` |
|
||||||
6. Note the user's access key, which can be found in the "Security Credentials" tab of the user browser. |
|
||||||
7. Go to the S3 Management Console. |
|
||||||
8. Create a new bucket. For a non-publicly-accessible bucket (like Bootstrap uses), it's recommended that the bucket name be random to increase security. On most *nix machines, you can easily generate a random UUID to use as the bucket name using Python: |
|
||||||
|
|
||||||
```bash |
|
||||||
python -c "import uuid; print(uuid.uuid4())" |
|
||||||
``` |
|
||||||
|
|
||||||
9. Determine and note what your bucket's ARN is. The ARN for an S3 bucket is of the form: `arn:aws:s3:::the-bucket-name-goes-here` |
|
||||||
10. In the bucket's Properties pane, in the "Permissions" section, click the "Edit bucket policy" button. |
|
||||||
11. Input and submit an IAM Policy that grants the user at least read+write rights to the bucket. AWS has a policy generator and some examples to help with crafting the policy. Here's the policy that Bootstrap uses, with the sensitive bits censored: |
|
||||||
|
|
||||||
```json |
|
||||||
{ |
|
||||||
"Version": "2012-10-17", |
|
||||||
"Id": "PolicyTravisReadWriteNoAdmin", |
|
||||||
"Statement": [ |
|
||||||
{ |
|
||||||
"Sid": "StmtXXXXXXXXXXXXXX", |
|
||||||
"Effect": "Allow", |
|
||||||
"Principal": { |
|
||||||
"AWS": "arn:aws:iam::XXXXXXXXXXXXXX:user/travis-ci" |
|
||||||
}, |
|
||||||
"Action": [ |
|
||||||
"s3:AbortMultipartUpload", |
|
||||||
"s3:GetObjectVersion", |
|
||||||
"s3:ListBucket", |
|
||||||
"s3:DeleteObject", |
|
||||||
"s3:DeleteObjectVersion", |
|
||||||
"s3:GetObject", |
|
||||||
"s3:PutObject" |
|
||||||
], |
|
||||||
"Resource": [ |
|
||||||
"arn:aws:s3:::XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", |
|
||||||
"arn:aws:s3:::XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/*" |
|
||||||
] |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
12. If you want deletion from the cache to be done automatically based on age (like Bootstrap does): In the bucket's Properties pane, in the "Lifecycle" section, add a rule to expire/delete files based on creation date. |
|
||||||
13. Install the [`travis` RubyGem](https://github.com/travis-ci/travis): `gem install travis` |
|
||||||
14. Encrypt the environment variables: |
|
||||||
|
|
||||||
```bash |
|
||||||
travis encrypt --repo twbs/bootstrap "AWS_ACCESS_KEY_ID=XXX" |
|
||||||
travis encrypt --repo twbs/bootstrap "AWS_SECRET_ACCESS_KEY=XXX" |
|
||||||
travis encrypt --repo twbs/bootstrap "TWBS_S3_BUCKET=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" |
|
||||||
``` |
|
||||||
|
|
||||||
14. Add the resulting secure environment variables to `.travis.yml`. |
|
||||||
|
|
||||||
|
|
||||||
## Usage |
|
||||||
Read `s3_cache.py`'s source code and Bootstrap's `.travis.yml` for how to invoke and make use of `s3_cache.py`. |
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@ |
|||||||
boto==2.20.0 |
|
@ -1,107 +0,0 @@ |
|||||||
#!/usr/bin/env python2.7 |
|
||||||
from __future__ import absolute_import, unicode_literals, print_function, division |
|
||||||
|
|
||||||
from sys import argv |
|
||||||
from os import environ, stat, remove as _delete_file |
|
||||||
from os.path import isfile, dirname, basename, abspath |
|
||||||
from hashlib import sha256 |
|
||||||
from subprocess import check_call as run |
|
||||||
|
|
||||||
from boto.s3.connection import S3Connection |
|
||||||
from boto.s3.key import Key |
|
||||||
from boto.exception import S3ResponseError |
|
||||||
|
|
||||||
|
|
||||||
NEED_TO_UPLOAD_MARKER = '.need-to-upload' |
|
||||||
BYTES_PER_MB = 1024 * 1024 |
|
||||||
try: |
|
||||||
BUCKET_NAME = environ['TWBS_S3_BUCKET'] |
|
||||||
except KeyError: |
|
||||||
raise SystemExit("TWBS_S3_BUCKET environment variable not set!") |
|
||||||
|
|
||||||
|
|
||||||
def _sha256_of_file(filename): |
|
||||||
hasher = sha256() |
|
||||||
with open(filename, 'rb') as input_file: |
|
||||||
hasher.update(input_file.read()) |
|
||||||
file_hash = hasher.hexdigest() |
|
||||||
print('sha256({}) = {}'.format(filename, file_hash)) |
|
||||||
return file_hash |
|
||||||
|
|
||||||
|
|
||||||
def _delete_file_quietly(filename): |
|
||||||
try: |
|
||||||
_delete_file(filename) |
|
||||||
except (OSError, IOError): |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
def _tarball_size(directory): |
|
||||||
kib = stat(_tarball_filename_for(directory)).st_size // BYTES_PER_MB |
|
||||||
return "{} MiB".format(kib) |
|
||||||
|
|
||||||
|
|
||||||
def _tarball_filename_for(directory): |
|
||||||
return abspath('./{}.tar.gz'.format(basename(directory))) |
|
||||||
|
|
||||||
|
|
||||||
def _create_tarball(directory): |
|
||||||
print("Creating tarball of {}...".format(directory)) |
|
||||||
run(['tar', '-czf', _tarball_filename_for(directory), '-C', dirname(directory), basename(directory)]) |
|
||||||
|
|
||||||
|
|
||||||
def _extract_tarball(directory): |
|
||||||
print("Extracting tarball of {}...".format(directory)) |
|
||||||
run(['tar', '-xzf', _tarball_filename_for(directory), '-C', dirname(directory)]) |
|
||||||
|
|
||||||
|
|
||||||
def download(directory): |
|
||||||
_delete_file_quietly(NEED_TO_UPLOAD_MARKER) |
|
||||||
try: |
|
||||||
print("Downloading {} tarball from S3...".format(friendly_name)) |
|
||||||
key.get_contents_to_filename(_tarball_filename_for(directory)) |
|
||||||
except S3ResponseError as err: |
|
||||||
open(NEED_TO_UPLOAD_MARKER, 'a').close() |
|
||||||
print(err) |
|
||||||
raise SystemExit("Cached {} download failed!".format(friendly_name)) |
|
||||||
print("Downloaded {}.".format(_tarball_size(directory))) |
|
||||||
_extract_tarball(directory) |
|
||||||
print("{} successfully installed from cache.".format(friendly_name)) |
|
||||||
|
|
||||||
|
|
||||||
def upload(directory): |
|
||||||
_create_tarball(directory) |
|
||||||
print("Uploading {} tarball to S3... ({})".format(friendly_name, _tarball_size(directory))) |
|
||||||
key.set_contents_from_filename(_tarball_filename_for(directory)) |
|
||||||
print("{} cache successfully updated.".format(friendly_name)) |
|
||||||
_delete_file_quietly(NEED_TO_UPLOAD_MARKER) |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
# Uses environment variables: |
|
||||||
# AWS_ACCESS_KEY_ID -- AWS Access Key ID |
|
||||||
# AWS_SECRET_ACCESS_KEY -- AWS Secret Access Key |
|
||||||
argv.pop(0) |
|
||||||
if len(argv) != 4: |
|
||||||
raise SystemExit("USAGE: s3_cache.py <download | upload> <friendly name> <dependencies file> <directory>") |
|
||||||
mode, friendly_name, dependencies_file, directory = argv |
|
||||||
|
|
||||||
conn = S3Connection() |
|
||||||
bucket = conn.lookup(BUCKET_NAME, validate=False) |
|
||||||
if bucket is None: |
|
||||||
raise SystemExit("Could not access bucket!") |
|
||||||
|
|
||||||
dependencies_file_hash = _sha256_of_file(dependencies_file) |
|
||||||
|
|
||||||
key = Key(bucket, dependencies_file_hash) |
|
||||||
key.storage_class = 'REDUCED_REDUNDANCY' |
|
||||||
|
|
||||||
if mode == 'download': |
|
||||||
download(directory) |
|
||||||
elif mode == 'upload': |
|
||||||
if isfile(NEED_TO_UPLOAD_MARKER): # FIXME |
|
||||||
upload(directory) |
|
||||||
else: |
|
||||||
print("No need to upload anything.") |
|
||||||
else: |
|
||||||
raise SystemExit("Unrecognized mode {!r}".format(mode)) |
|
@ -1,4 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
cp test-infra/npm-shrinkwrap.canonical.json npm-shrinkwrap.json |
|
||||||
npm install |
|
||||||
rm npm-shrinkwrap.json |
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue