]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // |
2 | // Forms | |
3 | // -------------------------------------------------- | |
4 | ||
5 | ||
6 | // Normalize non-controls | |
7 | // | |
8 | // Restyle and baseline non-control form elements. | |
9 | ||
10 | fieldset { | |
11 | padding: 0; | |
12 | margin: 0; | |
13 | border: 0; | |
14 | // Chrome and Firefox set a `min-width: min-content;` on fieldsets, | |
15 | // so we reset that to ensure it behaves more like a standard block element. | |
16 | // See https://github.com/twbs/bootstrap/issues/12359. | |
17 | min-width: 0; | |
18 | } | |
19 | ||
20 | legend { | |
21 | display: block; | |
22 | width: 100%; | |
23 | padding: 0; | |
24 | margin-bottom: @line-height-computed; | |
25 | font-size: (@font-size-base * 1.5); | |
26 | line-height: inherit; | |
27 | color: @legend-color; | |
28 | border: 0; | |
29 | border-bottom: 1px solid @legend-border-color; | |
30 | } | |
31 | ||
32 | label { | |
33 | display: inline-block; | |
34 | max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) | |
35 | margin-bottom: 5px; | |
36 | font-weight: bold; | |
37 | } | |
38 | ||
39 | ||
40 | // Normalize form controls | |
41 | // | |
42 | // While most of our form styles require extra classes, some basic normalization | |
43 | // is required to ensure optimum display with or without those classes to better | |
44 | // address browser inconsistencies. | |
45 | ||
46 | // Override content-box in Normalize (* isn't specific enough) | |
47 | input[type="search"] { | |
48 | .box-sizing(border-box); | |
49 | } | |
50 | ||
51 | // Position radios and checkboxes better | |
52 | input[type="radio"], | |
53 | input[type="checkbox"] { | |
54 | margin: 4px 0 0; | |
55 | margin-top: 1px \9; // IE8-9 | |
56 | line-height: normal; | |
57 | } | |
58 | ||
59 | // Set the height of file controls to match text inputs | |
60 | input[type="file"] { | |
61 | display: block; | |
62 | } | |
63 | ||
64 | // Make range inputs behave like textual form controls | |
65 | input[type="range"] { | |
66 | display: block; | |
67 | width: 100%; | |
68 | } | |
69 | ||
70 | // Make multiple select elements height not fixed | |
71 | select[multiple], | |
72 | select[size] { | |
73 | height: auto; | |
74 | } | |
75 | ||
76 | // Focus for file, radio, and checkbox | |
77 | input[type="file"]:focus, | |
78 | input[type="radio"]:focus, | |
79 | input[type="checkbox"]:focus { | |
80 | .tab-focus(); | |
81 | } | |
82 | ||
83 | // Adjust output element | |
84 | output { | |
85 | display: block; | |
86 | padding-top: (@padding-base-vertical + 1); | |
87 | font-size: @font-size-base; | |
88 | line-height: @line-height-base; | |
89 | color: @input-color; | |
90 | } | |
91 | ||
92 | ||
93 | // Common form controls | |
94 | // | |
95 | // Shared size and type resets for form controls. Apply `.form-control` to any | |
96 | // of the following form controls: | |
97 | // | |
98 | // select | |
99 | // textarea | |
100 | // input[type="text"] | |
101 | // input[type="password"] | |
102 | // input[type="datetime"] | |
103 | // input[type="datetime-local"] | |
104 | // input[type="date"] | |
105 | // input[type="month"] | |
106 | // input[type="time"] | |
107 | // input[type="week"] | |
108 | // input[type="number"] | |
109 | // input[type="email"] | |
110 | // input[type="url"] | |
111 | // input[type="search"] | |
112 | // input[type="tel"] | |
113 | // input[type="color"] | |
114 | ||
115 | .form-control { | |
116 | display: block; | |
117 | width: 100%; | |
118 | height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) | |
119 | padding: @padding-base-vertical @padding-base-horizontal; | |
120 | font-size: @font-size-base; | |
121 | line-height: @line-height-base; | |
122 | color: @input-color; | |
123 | background-color: @input-bg; | |
124 | background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 | |
125 | border: 1px solid @input-border; | |
126 | border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS. | |
127 | .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); | |
128 | .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s"); | |
129 | ||
130 | // Customize the `:focus` state to imitate native WebKit styles. | |
131 | .form-control-focus(); | |
132 | ||
133 | // Placeholder | |
134 | .placeholder(); | |
135 | ||
136 | // Disabled and read-only inputs | |
137 | // | |
138 | // HTML5 says that controls under a fieldset > legend:first-child won't be | |
139 | // disabled if the fieldset is disabled. Due to implementation difficulty, we | |
140 | // don't honor that edge case; we style them as disabled anyway. | |
141 | &[disabled], | |
142 | &[readonly], | |
143 | fieldset[disabled] & { | |
144 | background-color: @input-bg-disabled; | |
145 | opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655 | |
146 | } | |
147 | ||
148 | &[disabled], | |
149 | fieldset[disabled] & { | |
150 | cursor: @cursor-disabled; | |
151 | } | |
152 | ||
153 | // Reset height for `textarea`s | |
154 | textarea& { | |
155 | height: auto; | |
156 | } | |
157 | } | |
158 | ||
159 | ||
160 | // Search inputs in iOS | |
161 | // | |
162 | // This overrides the extra rounded corners on search inputs in iOS so that our | |
163 | // `.form-control` class can properly style them. Note that this cannot simply | |
164 | // be added to `.form-control` as it's not specific enough. For details, see | |
165 | // https://github.com/twbs/bootstrap/issues/11586. | |
166 | ||
167 | input[type="search"] { | |
168 | -webkit-appearance: none; | |
169 | } | |
170 | ||
171 | ||
172 | // Special styles for iOS temporal inputs | |
173 | // | |
174 | // In Mobile Safari, setting `display: block` on temporal inputs causes the | |
175 | // text within the input to become vertically misaligned. As a workaround, we | |
176 | // set a pixel line-height that matches the given height of the input, but only | |
177 | // for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848 | |
178 | ||
179 | @media screen and (-webkit-min-device-pixel-ratio: 0) { | |
180 | input[type="date"], | |
181 | input[type="time"], | |
182 | input[type="datetime-local"], | |
183 | input[type="month"] { | |
184 | line-height: @input-height-base; | |
185 | ||
186 | &.input-sm, | |
187 | .input-group-sm & { | |
188 | line-height: @input-height-small; | |
189 | } | |
190 | ||
191 | &.input-lg, | |
192 | .input-group-lg & { | |
193 | line-height: @input-height-large; | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
198 | ||
199 | // Form groups | |
200 | // | |
201 | // Designed to help with the organization and spacing of vertical forms. For | |
202 | // horizontal forms, use the predefined grid classes. | |
203 | ||
204 | .form-group { | |
205 | margin-bottom: @form-group-margin-bottom; | |
206 | } | |
207 | ||
208 | ||
209 | // Checkboxes and radios | |
210 | // | |
211 | // Indent the labels to position radios/checkboxes as hanging controls. | |
212 | ||
213 | .radio, | |
214 | .checkbox { | |
215 | position: relative; | |
216 | display: block; | |
217 | margin-top: 10px; | |
218 | margin-bottom: 10px; | |
219 | ||
220 | label { | |
221 | min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text | |
222 | padding-left: 20px; | |
223 | margin-bottom: 0; | |
224 | font-weight: normal; | |
225 | cursor: pointer; | |
226 | } | |
227 | } | |
228 | .radio input[type="radio"], | |
229 | .radio-inline input[type="radio"], | |
230 | .checkbox input[type="checkbox"], | |
231 | .checkbox-inline input[type="checkbox"] { | |
232 | position: absolute; | |
233 | margin-left: -20px; | |
234 | margin-top: 4px \9; | |
235 | } | |
236 | ||
237 | .radio + .radio, | |
238 | .checkbox + .checkbox { | |
239 | margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing | |
240 | } | |
241 | ||
242 | // Radios and checkboxes on same line | |
243 | .radio-inline, | |
244 | .checkbox-inline { | |
245 | position: relative; | |
246 | display: inline-block; | |
247 | padding-left: 20px; | |
248 | margin-bottom: 0; | |
249 | vertical-align: middle; | |
250 | font-weight: normal; | |
251 | cursor: pointer; | |
252 | } | |
253 | .radio-inline + .radio-inline, | |
254 | .checkbox-inline + .checkbox-inline { | |
255 | margin-top: 0; | |
256 | margin-left: 10px; // space out consecutive inline controls | |
257 | } | |
258 | ||
259 | // Apply same disabled cursor tweak as for inputs | |
260 | // Some special care is needed because <label>s don't inherit their parent's `cursor`. | |
261 | // | |
262 | // Note: Neither radios nor checkboxes can be readonly. | |
263 | input[type="radio"], | |
264 | input[type="checkbox"] { | |
265 | &[disabled], | |
266 | &.disabled, | |
267 | fieldset[disabled] & { | |
268 | cursor: @cursor-disabled; | |
269 | } | |
270 | } | |
271 | // These classes are used directly on <label>s | |
272 | .radio-inline, | |
273 | .checkbox-inline { | |
274 | &.disabled, | |
275 | fieldset[disabled] & { | |
276 | cursor: @cursor-disabled; | |
277 | } | |
278 | } | |
279 | // These classes are used on elements with <label> descendants | |
280 | .radio, | |
281 | .checkbox { | |
282 | &.disabled, | |
283 | fieldset[disabled] & { | |
284 | label { | |
285 | cursor: @cursor-disabled; | |
286 | } | |
287 | } | |
288 | } | |
289 | ||
290 | ||
291 | // Static form control text | |
292 | // | |
293 | // Apply class to a `p` element to make any string of text align with labels in | |
294 | // a horizontal form layout. | |
295 | ||
296 | .form-control-static { | |
297 | // Size it appropriately next to real form controls | |
298 | padding-top: (@padding-base-vertical + 1); | |
299 | padding-bottom: (@padding-base-vertical + 1); | |
300 | // Remove default margin from `p` | |
301 | margin-bottom: 0; | |
302 | min-height: (@line-height-computed + @font-size-base); | |
303 | ||
304 | &.input-lg, | |
305 | &.input-sm { | |
306 | padding-left: 0; | |
307 | padding-right: 0; | |
308 | } | |
309 | } | |
310 | ||
311 | ||
312 | // Form control sizing | |
313 | // | |
314 | // Build on `.form-control` with modifier classes to decrease or increase the | |
315 | // height and font-size of form controls. | |
316 | // | |
317 | // The `.form-group-* form-control` variations are sadly duplicated to avoid the | |
318 | // issue documented in https://github.com/twbs/bootstrap/issues/15074. | |
319 | ||
320 | .input-sm { | |
321 | .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small); | |
322 | } | |
323 | .form-group-sm { | |
324 | .form-control { | |
325 | .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small); | |
326 | } | |
327 | .form-control-static { | |
328 | height: @input-height-small; | |
329 | padding: @padding-small-vertical @padding-small-horizontal; | |
330 | font-size: @font-size-small; | |
331 | line-height: @line-height-small; | |
332 | min-height: (@line-height-computed + @font-size-small); | |
333 | } | |
334 | } | |
335 | ||
336 | .input-lg { | |
337 | .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large); | |
338 | } | |
339 | .form-group-lg { | |
340 | .form-control { | |
341 | .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large); | |
342 | } | |
343 | .form-control-static { | |
344 | height: @input-height-large; | |
345 | padding: @padding-large-vertical @padding-large-horizontal; | |
346 | font-size: @font-size-large; | |
347 | line-height: @line-height-large; | |
348 | min-height: (@line-height-computed + @font-size-large); | |
349 | } | |
350 | } | |
351 | ||
352 | ||
353 | // Form control feedback states | |
354 | // | |
355 | // Apply contextual and semantic states to individual form controls. | |
356 | ||
357 | .has-feedback { | |
358 | // Enable absolute positioning | |
359 | position: relative; | |
360 | ||
361 | // Ensure icons don't overlap text | |
362 | .form-control { | |
363 | padding-right: (@input-height-base * 1.25); | |
364 | } | |
365 | } | |
366 | // Feedback icon (requires .glyphicon classes) | |
367 | .form-control-feedback { | |
368 | position: absolute; | |
369 | top: 0; | |
370 | right: 0; | |
371 | z-index: 2; // Ensure icon is above input groups | |
372 | display: block; | |
373 | width: @input-height-base; | |
374 | height: @input-height-base; | |
375 | line-height: @input-height-base; | |
376 | text-align: center; | |
377 | pointer-events: none; | |
378 | } | |
379 | .input-lg + .form-control-feedback { | |
380 | width: @input-height-large; | |
381 | height: @input-height-large; | |
382 | line-height: @input-height-large; | |
383 | } | |
384 | .input-sm + .form-control-feedback { | |
385 | width: @input-height-small; | |
386 | height: @input-height-small; | |
387 | line-height: @input-height-small; | |
388 | } | |
389 | ||
390 | // Feedback states | |
391 | .has-success { | |
392 | .form-control-validation(@state-success-text; @state-success-text; @state-success-bg); | |
393 | } | |
394 | .has-warning { | |
395 | .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg); | |
396 | } | |
397 | .has-error { | |
398 | .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg); | |
399 | } | |
400 | ||
401 | // Reposition feedback icon if input has visible label above | |
402 | .has-feedback label { | |
403 | ||
404 | & ~ .form-control-feedback { | |
405 | top: (@line-height-computed + 5); // Height of the `label` and its margin | |
406 | } | |
407 | &.sr-only ~ .form-control-feedback { | |
408 | top: 0; | |
409 | } | |
410 | } | |
411 | ||
412 | ||
413 | // Help text | |
414 | // | |
415 | // Apply to any element you wish to create light text for placement immediately | |
416 | // below a form control. Use for general help, formatting, or instructional text. | |
417 | ||
418 | .help-block { | |
419 | display: block; // account for any element using help-block | |
420 | margin-top: 5px; | |
421 | margin-bottom: 10px; | |
422 | color: lighten(@text-color, 25%); // lighten the text some for contrast | |
423 | } | |
424 | ||
425 | ||
426 | // Inline forms | |
427 | // | |
428 | // Make forms appear inline(-block) by adding the `.form-inline` class. Inline | |
429 | // forms begin stacked on extra small (mobile) devices and then go inline when | |
430 | // viewports reach <768px. | |
431 | // | |
432 | // Requires wrapping inputs and labels with `.form-group` for proper display of | |
433 | // default HTML form controls and our custom form controls (e.g., input groups). | |
434 | // | |
435 | // Heads up! This is mixin-ed into `.navbar-form` in navbars.less. | |
436 | ||
437 | .form-inline { | |
438 | ||
439 | // Kick in the inline | |
440 | @media (min-width: @screen-sm-min) { | |
441 | // Inline-block all the things for "inline" | |
442 | .form-group { | |
443 | display: inline-block; | |
444 | margin-bottom: 0; | |
445 | vertical-align: middle; | |
446 | } | |
447 | ||
448 | // In navbar-form, allow folks to *not* use `.form-group` | |
449 | .form-control { | |
450 | display: inline-block; | |
451 | width: auto; // Prevent labels from stacking above inputs in `.form-group` | |
452 | vertical-align: middle; | |
453 | } | |
454 | ||
455 | // Make static controls behave like regular ones | |
456 | .form-control-static { | |
457 | display: inline-block; | |
458 | } | |
459 | ||
460 | .input-group { | |
461 | display: inline-table; | |
462 | vertical-align: middle; | |
463 | ||
464 | .input-group-addon, | |
465 | .input-group-btn, | |
466 | .form-control { | |
467 | width: auto; | |
468 | } | |
469 | } | |
470 | ||
471 | // Input groups need that 100% width though | |
472 | .input-group > .form-control { | |
473 | width: 100%; | |
474 | } | |
475 | ||
476 | .control-label { | |
477 | margin-bottom: 0; | |
478 | vertical-align: middle; | |
479 | } | |
480 | ||
481 | // Remove default margin on radios/checkboxes that were used for stacking, and | |
482 | // then undo the floating of radios and checkboxes to match. | |
483 | .radio, | |
484 | .checkbox { | |
485 | display: inline-block; | |
486 | margin-top: 0; | |
487 | margin-bottom: 0; | |
488 | vertical-align: middle; | |
489 | ||
490 | label { | |
491 | padding-left: 0; | |
492 | } | |
493 | } | |
494 | .radio input[type="radio"], | |
495 | .checkbox input[type="checkbox"] { | |
496 | position: relative; | |
497 | margin-left: 0; | |
498 | } | |
499 | ||
500 | // Re-override the feedback icon. | |
501 | .has-feedback .form-control-feedback { | |
502 | top: 0; | |
503 | } | |
504 | } | |
505 | } | |
506 | ||
507 | ||
508 | // Horizontal forms | |
509 | // | |
510 | // Horizontal forms are built on grid classes and allow you to create forms with | |
511 | // labels on the left and inputs on the right. | |
512 | ||
513 | .form-horizontal { | |
514 | ||
515 | // Consistent vertical alignment of radios and checkboxes | |
516 | // | |
517 | // Labels also get some reset styles, but that is scoped to a media query below. | |
518 | .radio, | |
519 | .checkbox, | |
520 | .radio-inline, | |
521 | .checkbox-inline { | |
522 | margin-top: 0; | |
523 | margin-bottom: 0; | |
524 | padding-top: (@padding-base-vertical + 1); // Default padding plus a border | |
525 | } | |
526 | // Account for padding we're adding to ensure the alignment and of help text | |
527 | // and other content below items | |
528 | .radio, | |
529 | .checkbox { | |
530 | min-height: (@line-height-computed + (@padding-base-vertical + 1)); | |
531 | } | |
532 | ||
533 | // Make form groups behave like rows | |
534 | .form-group { | |
535 | .make-row(); | |
536 | } | |
537 | ||
538 | // Reset spacing and right align labels, but scope to media queries so that | |
539 | // labels on narrow viewports stack the same as a default form example. | |
540 | @media (min-width: @screen-sm-min) { | |
541 | .control-label { | |
542 | text-align: right; | |
543 | margin-bottom: 0; | |
544 | padding-top: (@padding-base-vertical + 1); // Default padding plus a border | |
545 | } | |
546 | } | |
547 | ||
548 | // Validation states | |
549 | // | |
550 | // Reposition the icon because it's now within a grid column and columns have | |
551 | // `position: relative;` on them. Also accounts for the grid gutter padding. | |
552 | .has-feedback .form-control-feedback { | |
553 | right: (@grid-gutter-width / 2); | |
554 | } | |
555 | ||
556 | // Form group sizes | |
557 | // | |
558 | // Quick utility class for applying `.input-lg` and `.input-sm` styles to the | |
559 | // inputs and labels within a `.form-group`. | |
560 | .form-group-lg { | |
561 | @media (min-width: @screen-sm-min) { | |
562 | .control-label { | |
563 | padding-top: ((@padding-large-vertical * @line-height-large) + 1); | |
564 | } | |
565 | } | |
566 | } | |
567 | .form-group-sm { | |
568 | @media (min-width: @screen-sm-min) { | |
569 | .control-label { | |
570 | padding-top: (@padding-small-vertical + 1); | |
571 | } | |
572 | } | |
573 | } | |
574 | } |