_custom-forms.scss 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. // Embedded icons from Open Iconic.
  2. // Released under MIT and copyright 2014 Waybury.
  3. // https://useiconic.com/open
  4. // Checkboxes and radios
  5. //
  6. // Base class takes care of all the key behavioral aspects.
  7. .custom-control {
  8. position: relative;
  9. display: block;
  10. min-height: $font-size-base * $line-height-base;
  11. padding-left: $custom-control-gutter + $custom-control-indicator-size;
  12. }
  13. .custom-control-inline {
  14. display: inline-flex;
  15. margin-right: $custom-control-spacer-x;
  16. }
  17. .custom-control-input {
  18. position: absolute;
  19. z-index: -1; // Put the input behind the label so it doesn't overlay text
  20. opacity: 0;
  21. &:checked ~ .custom-control-label::before {
  22. color: $custom-control-indicator-checked-color;
  23. border-color: $custom-control-indicator-checked-border-color;
  24. @include gradient-bg($custom-control-indicator-checked-bg);
  25. @include box-shadow($custom-control-indicator-checked-box-shadow);
  26. }
  27. &:focus ~ .custom-control-label::before {
  28. // the mixin is not used here to make sure there is feedback
  29. @if $enable-shadows {
  30. box-shadow: $input-box-shadow, $input-focus-box-shadow;
  31. } @else {
  32. box-shadow: $custom-control-indicator-focus-box-shadow;
  33. }
  34. }
  35. &:focus:not(:checked) ~ .custom-control-label::before {
  36. border-color: $custom-control-indicator-focus-border-color;
  37. }
  38. &:not(:disabled):active ~ .custom-control-label::before {
  39. color: $custom-control-indicator-active-color;
  40. background-color: $custom-control-indicator-active-bg;
  41. border-color: $custom-control-indicator-active-border-color;
  42. @include box-shadow($custom-control-indicator-active-box-shadow);
  43. }
  44. &:disabled {
  45. ~ .custom-control-label {
  46. color: $custom-control-label-disabled-color;
  47. &::before {
  48. background-color: $custom-control-indicator-disabled-bg;
  49. }
  50. }
  51. }
  52. }
  53. // Custom control indicators
  54. //
  55. // Build the custom controls out of pseudo-elements.
  56. .custom-control-label {
  57. position: relative;
  58. margin-bottom: 0;
  59. vertical-align: top;
  60. // Background-color and (when enabled) gradient
  61. &::before {
  62. position: absolute;
  63. top: ($font-size-base * $line-height-base - $custom-control-indicator-size) / 2;
  64. left: -($custom-control-gutter + $custom-control-indicator-size);
  65. display: block;
  66. width: $custom-control-indicator-size;
  67. height: $custom-control-indicator-size;
  68. pointer-events: none;
  69. content: "";
  70. background-color: $custom-control-indicator-bg;
  71. border: $custom-control-indicator-border-color solid $custom-control-indicator-border-width;
  72. @include box-shadow($custom-control-indicator-box-shadow);
  73. }
  74. // Foreground (icon)
  75. &::after {
  76. position: absolute;
  77. top: ($font-size-base * $line-height-base - $custom-control-indicator-size) / 2;
  78. left: -($custom-control-gutter + $custom-control-indicator-size);
  79. display: block;
  80. width: $custom-control-indicator-size;
  81. height: $custom-control-indicator-size;
  82. content: "";
  83. background: no-repeat 50% / #{$custom-control-indicator-bg-size};
  84. }
  85. }
  86. // Checkboxes
  87. //
  88. // Tweak just a few things for checkboxes.
  89. .custom-checkbox {
  90. .custom-control-label::before {
  91. @include border-radius($custom-checkbox-indicator-border-radius);
  92. }
  93. .custom-control-input:checked ~ .custom-control-label {
  94. &::after {
  95. background-image: $custom-checkbox-indicator-icon-checked;
  96. }
  97. }
  98. .custom-control-input:indeterminate ~ .custom-control-label {
  99. &::before {
  100. border-color: $custom-checkbox-indicator-indeterminate-border-color;
  101. @include gradient-bg($custom-checkbox-indicator-indeterminate-bg);
  102. @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow);
  103. }
  104. &::after {
  105. background-image: $custom-checkbox-indicator-icon-indeterminate;
  106. }
  107. }
  108. .custom-control-input:disabled {
  109. &:checked ~ .custom-control-label::before {
  110. background-color: $custom-control-indicator-checked-disabled-bg;
  111. }
  112. &:indeterminate ~ .custom-control-label::before {
  113. background-color: $custom-control-indicator-checked-disabled-bg;
  114. }
  115. }
  116. }
  117. // Radios
  118. //
  119. // Tweak just a few things for radios.
  120. .custom-radio {
  121. .custom-control-label::before {
  122. // stylelint-disable-next-line property-blacklist
  123. border-radius: $custom-radio-indicator-border-radius;
  124. }
  125. .custom-control-input:checked ~ .custom-control-label {
  126. &::after {
  127. background-image: $custom-radio-indicator-icon-checked;
  128. }
  129. }
  130. .custom-control-input:disabled {
  131. &:checked ~ .custom-control-label::before {
  132. background-color: $custom-control-indicator-checked-disabled-bg;
  133. }
  134. }
  135. }
  136. // switches
  137. //
  138. // Tweak a few things for switches
  139. .custom-switch {
  140. padding-left: $custom-switch-width + $custom-control-gutter;
  141. .custom-control-label {
  142. &::before {
  143. left: -($custom-switch-width + $custom-control-gutter);
  144. width: $custom-switch-width;
  145. pointer-events: all;
  146. // stylelint-disable-next-line property-blacklist
  147. border-radius: $custom-switch-indicator-border-radius;
  148. }
  149. &::after {
  150. top: calc(#{(($font-size-base * $line-height-base - $custom-control-indicator-size) / 2)} + #{$custom-control-indicator-border-width * 2});
  151. left: calc(#{-($custom-switch-width + $custom-control-gutter)} + #{$custom-control-indicator-border-width * 2});
  152. width: $custom-switch-indicator-size;
  153. height: $custom-switch-indicator-size;
  154. background-color: $custom-control-indicator-border-color;
  155. // stylelint-disable-next-line property-blacklist
  156. border-radius: $custom-switch-indicator-border-radius;
  157. @include transition(transform .15s ease-in-out, $custom-forms-transition);
  158. }
  159. }
  160. .custom-control-input:checked ~ .custom-control-label {
  161. &::after {
  162. background-color: $custom-control-indicator-bg;
  163. transform: translateX($custom-switch-width - $custom-control-indicator-size);
  164. }
  165. }
  166. .custom-control-input:disabled {
  167. &:checked ~ .custom-control-label::before {
  168. background-color: $custom-control-indicator-checked-disabled-bg;
  169. }
  170. }
  171. }
  172. // Select
  173. //
  174. // Replaces the browser default select with a custom one, mostly pulled from
  175. // https://primer.github.io/.
  176. //
  177. .custom-select {
  178. display: inline-block;
  179. width: 100%;
  180. height: $custom-select-height;
  181. padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x;
  182. font-family: $custom-select-font-family;
  183. @include font-size($custom-select-font-size);
  184. font-weight: $custom-select-font-weight;
  185. line-height: $custom-select-line-height;
  186. color: $custom-select-color;
  187. vertical-align: middle;
  188. background: $custom-select-background;
  189. background-color: $custom-select-bg;
  190. border: $custom-select-border-width solid $custom-select-border-color;
  191. @include border-radius($custom-select-border-radius, 0);
  192. @include box-shadow($custom-select-box-shadow);
  193. appearance: none;
  194. &:focus {
  195. border-color: $custom-select-focus-border-color;
  196. outline: 0;
  197. @if $enable-shadows {
  198. box-shadow: $custom-select-box-shadow, $custom-select-focus-box-shadow;
  199. } @else {
  200. box-shadow: $custom-select-focus-box-shadow;
  201. }
  202. &::-ms-value {
  203. // For visual consistency with other platforms/browsers,
  204. // suppress the default white text on blue background highlight given to
  205. // the selected option text when the (still closed) <select> receives focus
  206. // in IE and (under certain conditions) Edge.
  207. // See https://github.com/twbs/bootstrap/issues/19398.
  208. color: $input-color;
  209. background-color: $input-bg;
  210. }
  211. }
  212. &[multiple],
  213. &[size]:not([size="1"]) {
  214. height: auto;
  215. padding-right: $custom-select-padding-x;
  216. background-image: none;
  217. }
  218. &:disabled {
  219. color: $custom-select-disabled-color;
  220. background-color: $custom-select-disabled-bg;
  221. }
  222. // Hides the default caret in IE11
  223. &::-ms-expand {
  224. display: none;
  225. }
  226. }
  227. .custom-select-sm {
  228. height: $custom-select-height-sm;
  229. padding-top: $custom-select-padding-y-sm;
  230. padding-bottom: $custom-select-padding-y-sm;
  231. padding-left: $custom-select-padding-x-sm;
  232. @include font-size($custom-select-font-size-sm);
  233. }
  234. .custom-select-lg {
  235. height: $custom-select-height-lg;
  236. padding-top: $custom-select-padding-y-lg;
  237. padding-bottom: $custom-select-padding-y-lg;
  238. padding-left: $custom-select-padding-x-lg;
  239. @include font-size($custom-select-font-size-lg);
  240. }
  241. // File
  242. //
  243. // Custom file input.
  244. .custom-file {
  245. position: relative;
  246. display: inline-block;
  247. width: 100%;
  248. height: $custom-file-height;
  249. margin-bottom: 0;
  250. }
  251. .custom-file-input {
  252. position: relative;
  253. z-index: 2;
  254. width: 100%;
  255. height: $custom-file-height;
  256. margin: 0;
  257. opacity: 0;
  258. &:focus ~ .custom-file-label {
  259. border-color: $custom-file-focus-border-color;
  260. box-shadow: $custom-file-focus-box-shadow;
  261. }
  262. &:disabled ~ .custom-file-label {
  263. background-color: $custom-file-disabled-bg;
  264. }
  265. @each $lang, $value in $custom-file-text {
  266. &:lang(#{$lang}) ~ .custom-file-label::after {
  267. content: $value;
  268. }
  269. }
  270. ~ .custom-file-label[data-browse]::after {
  271. content: attr(data-browse);
  272. }
  273. }
  274. .custom-file-label {
  275. position: absolute;
  276. top: 0;
  277. right: 0;
  278. left: 0;
  279. z-index: 1;
  280. height: $custom-file-height;
  281. padding: $custom-file-padding-y $custom-file-padding-x;
  282. font-family: $custom-file-font-family;
  283. font-weight: $custom-file-font-weight;
  284. line-height: $custom-file-line-height;
  285. color: $custom-file-color;
  286. background-color: $custom-file-bg;
  287. border: $custom-file-border-width solid $custom-file-border-color;
  288. @include border-radius($custom-file-border-radius);
  289. @include box-shadow($custom-file-box-shadow);
  290. &::after {
  291. position: absolute;
  292. top: 0;
  293. right: 0;
  294. bottom: 0;
  295. z-index: 3;
  296. display: block;
  297. height: $custom-file-height-inner;
  298. padding: $custom-file-padding-y $custom-file-padding-x;
  299. line-height: $custom-file-line-height;
  300. color: $custom-file-button-color;
  301. content: "Browse";
  302. @include gradient-bg($custom-file-button-bg);
  303. border-left: inherit;
  304. @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);
  305. }
  306. }
  307. // Range
  308. //
  309. // Style range inputs the same across browsers. Vendor-specific rules for pseudo
  310. // elements cannot be mixed. As such, there are no shared styles for focus or
  311. // active states on prefixed selectors.
  312. .custom-range {
  313. width: 100%;
  314. height: calc(#{$custom-range-thumb-height} + #{$custom-range-thumb-focus-box-shadow-width * 2});
  315. padding: 0; // Need to reset padding
  316. background-color: transparent;
  317. appearance: none;
  318. &:focus {
  319. outline: none;
  320. // Pseudo-elements must be split across multiple rulesets to have an effect.
  321. // No box-shadow() mixin for focus accessibility.
  322. &::-webkit-slider-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }
  323. &::-moz-range-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }
  324. &::-ms-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }
  325. }
  326. &::-moz-focus-outer {
  327. border: 0;
  328. }
  329. &::-webkit-slider-thumb {
  330. width: $custom-range-thumb-width;
  331. height: $custom-range-thumb-height;
  332. margin-top: ($custom-range-track-height - $custom-range-thumb-height) / 2; // Webkit specific
  333. @include gradient-bg($custom-range-thumb-bg);
  334. border: $custom-range-thumb-border;
  335. @include border-radius($custom-range-thumb-border-radius);
  336. @include box-shadow($custom-range-thumb-box-shadow);
  337. @include transition($custom-forms-transition);
  338. appearance: none;
  339. &:active {
  340. @include gradient-bg($custom-range-thumb-active-bg);
  341. }
  342. }
  343. &::-webkit-slider-runnable-track {
  344. width: $custom-range-track-width;
  345. height: $custom-range-track-height;
  346. color: transparent; // Why?
  347. cursor: $custom-range-track-cursor;
  348. background-color: $custom-range-track-bg;
  349. border-color: transparent;
  350. @include border-radius($custom-range-track-border-radius);
  351. @include box-shadow($custom-range-track-box-shadow);
  352. }
  353. &::-moz-range-thumb {
  354. width: $custom-range-thumb-width;
  355. height: $custom-range-thumb-height;
  356. @include gradient-bg($custom-range-thumb-bg);
  357. border: $custom-range-thumb-border;
  358. @include border-radius($custom-range-thumb-border-radius);
  359. @include box-shadow($custom-range-thumb-box-shadow);
  360. @include transition($custom-forms-transition);
  361. appearance: none;
  362. &:active {
  363. @include gradient-bg($custom-range-thumb-active-bg);
  364. }
  365. }
  366. &::-moz-range-track {
  367. width: $custom-range-track-width;
  368. height: $custom-range-track-height;
  369. color: transparent;
  370. cursor: $custom-range-track-cursor;
  371. background-color: $custom-range-track-bg;
  372. border-color: transparent; // Firefox specific?
  373. @include border-radius($custom-range-track-border-radius);
  374. @include box-shadow($custom-range-track-box-shadow);
  375. }
  376. &::-ms-thumb {
  377. width: $custom-range-thumb-width;
  378. height: $custom-range-thumb-height;
  379. margin-top: 0; // Edge specific
  380. margin-right: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.
  381. margin-left: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.
  382. @include gradient-bg($custom-range-thumb-bg);
  383. border: $custom-range-thumb-border;
  384. @include border-radius($custom-range-thumb-border-radius);
  385. @include box-shadow($custom-range-thumb-box-shadow);
  386. @include transition($custom-forms-transition);
  387. appearance: none;
  388. &:active {
  389. @include gradient-bg($custom-range-thumb-active-bg);
  390. }
  391. }
  392. &::-ms-track {
  393. width: $custom-range-track-width;
  394. height: $custom-range-track-height;
  395. color: transparent;
  396. cursor: $custom-range-track-cursor;
  397. background-color: transparent;
  398. border-color: transparent;
  399. border-width: $custom-range-thumb-height / 2;
  400. @include box-shadow($custom-range-track-box-shadow);
  401. }
  402. &::-ms-fill-lower {
  403. background-color: $custom-range-track-bg;
  404. @include border-radius($custom-range-track-border-radius);
  405. }
  406. &::-ms-fill-upper {
  407. margin-right: 15px; // arbitrary?
  408. background-color: $custom-range-track-bg;
  409. @include border-radius($custom-range-track-border-radius);
  410. }
  411. &:disabled {
  412. &::-webkit-slider-thumb {
  413. background-color: $custom-range-thumb-disabled-bg;
  414. }
  415. &::-webkit-slider-runnable-track {
  416. cursor: default;
  417. }
  418. &::-moz-range-thumb {
  419. background-color: $custom-range-thumb-disabled-bg;
  420. }
  421. &::-moz-range-track {
  422. cursor: default;
  423. }
  424. &::-ms-thumb {
  425. background-color: $custom-range-thumb-disabled-bg;
  426. }
  427. }
  428. }
  429. .custom-control-label::before,
  430. .custom-file-label,
  431. .custom-select {
  432. @include transition($custom-forms-transition);
  433. }