1//
2// Forms
3// --------------------------------------------------
4
5
6// GENERAL STYLES
7// --------------
8
9// Make all forms have space below them
10form {
11  margin: 0 0 @baseLineHeight;
12}
13
14fieldset {
15  padding: 0;
16  margin: 0;
17  border: 0;
18}
19
20// Groups of fields with labels on top (legends)
21legend {
22  display: block;
23  width: 100%;
24  padding: 0;
25  margin-bottom: @baseLineHeight;
26  font-size: @baseFontSize * 1.5;
27  line-height: @baseLineHeight * 2;
28  color: @grayDark;
29  border: 0;
30  border-bottom: 1px solid #e5e5e5;
31
32  // Small
33  small {
34    font-size: @baseLineHeight * .75;
35    color: @grayLight;
36  }
37}
38
39// Set font for forms
40label,
41input,
42button,
43select,
44textarea {
45  #font > .shorthand(@baseFontSize,normal,@baseLineHeight); // Set size, weight, line-height here
46}
47input,
48button,
49select,
50textarea {
51  font-family: @baseFontFamily; // And only set font-family here for those that need it (note the missing label element)
52}
53
54// Identify controls by their labels
55label {
56  display: block;
57  margin-bottom: 5px;
58}
59
60// Form controls
61// -------------------------
62
63// Shared size and type resets
64select,
65textarea,
66input[type="text"],
67input[type="password"],
68input[type="datetime"],
69input[type="datetime-local"],
70input[type="date"],
71input[type="month"],
72input[type="time"],
73input[type="week"],
74input[type="number"],
75input[type="email"],
76input[type="url"],
77input[type="search"],
78input[type="tel"],
79input[type="color"],
80.uneditable-input {
81  display: inline-block;
82  height: @baseLineHeight;
83  padding: 4px 6px;
84  margin-bottom: @baseLineHeight / 2;
85  font-size: @baseFontSize;
86  line-height: @baseLineHeight;
87  color: @gray;
88  .border-radius(@inputBorderRadius);
89  vertical-align: middle;
90}
91
92// Reset appearance properties for textual inputs and textarea
93// Declare width for legacy (can't be on input[type=*] selectors or it's too specific)
94input,
95textarea,
96.uneditable-input {
97  width: 206px; // plus 12px padding and 2px border
98}
99// Reset height since textareas have rows
100textarea {
101  height: auto;
102}
103// Everything else
104textarea,
105input[type="text"],
106input[type="password"],
107input[type="datetime"],
108input[type="datetime-local"],
109input[type="date"],
110input[type="month"],
111input[type="time"],
112input[type="week"],
113input[type="number"],
114input[type="email"],
115input[type="url"],
116input[type="search"],
117input[type="tel"],
118input[type="color"],
119.uneditable-input {
120  background-color: @inputBackground;
121  border: 1px solid @inputBorder;
122  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
123  .transition(~"border linear .2s, box-shadow linear .2s");
124
125  // Focus state
126  &:focus {
127    border-color: rgba(82,168,236,.8);
128    outline: 0;
129    outline: thin dotted \9; /* IE6-9 */
130    .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6)");
131  }
132}
133
134// Position radios and checkboxes better
135input[type="radio"],
136input[type="checkbox"] {
137  margin: 4px 0 0;
138  *margin-top: 0; /* IE7 */
139  margin-top: 1px \9; /* IE8-9 */
140  line-height: normal;
141}
142
143// Reset width of input images, buttons, radios, checkboxes
144input[type="file"],
145input[type="image"],
146input[type="submit"],
147input[type="reset"],
148input[type="button"],
149input[type="radio"],
150input[type="checkbox"] {
151  width: auto; // Override of generic input selector
152}
153
154// Set the height of select and file controls to match text inputs
155select,
156input[type="file"] {
157  height: @inputHeight; /* In IE7, the height of the select element cannot be changed by height, only font-size */
158  *margin-top: 4px; /* For IE7, add top margin to align select with labels */
159  line-height: @inputHeight;
160}
161
162// Make select elements obey height by applying a border
163select {
164  width: 220px; // default input width + 10px of padding that doesn't get applied
165  border: 1px solid @inputBorder;
166  background-color: @inputBackground; // Chrome on Linux and Mobile Safari need background-color
167}
168
169// Make multiple select elements height not fixed
170select[multiple],
171select[size] {
172  height: auto;
173}
174
175// Focus for select, file, radio, and checkbox
176select:focus,
177input[type="file"]:focus,
178input[type="radio"]:focus,
179input[type="checkbox"]:focus {
180  .tab-focus();
181}
182
183
184// Uneditable inputs
185// -------------------------
186
187// Make uneditable inputs look inactive
188.uneditable-input,
189.uneditable-textarea {
190  color: @grayLight;
191  background-color: darken(@inputBackground, 1%);
192  border-color: @inputBorder;
193  .box-shadow(inset 0 1px 2px rgba(0,0,0,.025));
194  cursor: not-allowed;
195}
196
197// For text that needs to appear as an input but should not be an input
198.uneditable-input {
199  overflow: hidden; // prevent text from wrapping, but still cut it off like an input does
200  white-space: nowrap;
201}
202
203// Make uneditable textareas behave like a textarea
204.uneditable-textarea {
205  width: auto;
206  height: auto;
207}
208
209
210// Placeholder
211// -------------------------
212
213// Placeholder text gets special styles because when browsers invalidate entire lines if it doesn't understand a selector
214input,
215textarea {
216  .placeholder();
217}
218
219
220// CHECKBOXES & RADIOS
221// -------------------
222
223// Indent the labels to position radios/checkboxes as hanging
224.radio,
225.checkbox {
226  min-height: @baseLineHeight; // clear the floating input if there is no label text
227  padding-left: 20px;
228}
229.radio input[type="radio"],
230.checkbox input[type="checkbox"] {
231  float: left;
232  margin-left: -20px;
233}
234
235// Move the options list down to align with labels
236.controls > .radio:first-child,
237.controls > .checkbox:first-child {
238  padding-top: 5px; // has to be padding because margin collaspes
239}
240
241// Radios and checkboxes on same line
242// TODO v3: Convert .inline to .control-inline
243.radio.inline,
244.checkbox.inline {
245  display: inline-block;
246  padding-top: 5px;
247  margin-bottom: 0;
248  vertical-align: middle;
249}
250.radio.inline + .radio.inline,
251.checkbox.inline + .checkbox.inline {
252  margin-left: 10px; // space out consecutive inline controls
253}
254
255
256
257// INPUT SIZES
258// -----------
259
260// General classes for quick sizes
261.input-mini       { width: 60px; }
262.input-small      { width: 90px; }
263.input-medium     { width: 150px; }
264.input-large      { width: 210px; }
265.input-xlarge     { width: 270px; }
266.input-xxlarge    { width: 530px; }
267
268// Grid style input sizes
269input[class*="span"],
270select[class*="span"],
271textarea[class*="span"],
272.uneditable-input[class*="span"],
273// Redeclare since the fluid row class is more specific
274.row-fluid input[class*="span"],
275.row-fluid select[class*="span"],
276.row-fluid textarea[class*="span"],
277.row-fluid .uneditable-input[class*="span"] {
278  float: none;
279  margin-left: 0;
280}
281// Ensure input-prepend/append never wraps
282.input-append input[class*="span"],
283.input-append .uneditable-input[class*="span"],
284.input-prepend input[class*="span"],
285.input-prepend .uneditable-input[class*="span"],
286.row-fluid input[class*="span"],
287.row-fluid select[class*="span"],
288.row-fluid textarea[class*="span"],
289.row-fluid .uneditable-input[class*="span"],
290.row-fluid .input-prepend [class*="span"],
291.row-fluid .input-append [class*="span"] {
292  display: inline-block;
293}
294
295
296
297// GRID SIZING FOR INPUTS
298// ----------------------
299
300// Grid sizes
301#grid > .input(@gridColumnWidth, @gridGutterWidth);
302
303// Control row for multiple inputs per line
304.controls-row {
305  .clearfix(); // Clear the float from controls
306}
307
308// Float to collapse white-space for proper grid alignment
309.controls-row [class*="span"],
310// Redeclare the fluid grid collapse since we undo the float for inputs
311.row-fluid .controls-row [class*="span"] {
312  float: left;
313}
314// Explicity set top padding on all checkboxes/radios, not just first-child
315.controls-row .checkbox[class*="span"],
316.controls-row .radio[class*="span"] {
317  padding-top: 5px;
318}
319
320
321
322
323// DISABLED STATE
324// --------------
325
326// Disabled and read-only inputs
327input[disabled],
328select[disabled],
329textarea[disabled],
330input[readonly],
331select[readonly],
332textarea[readonly] {
333  cursor: not-allowed;
334  background-color: @inputDisabledBackground;
335}
336// Explicitly reset the colors here
337input[type="radio"][disabled],
338input[type="checkbox"][disabled],
339input[type="radio"][readonly],
340input[type="checkbox"][readonly] {
341  background-color: transparent;
342}
343
344
345
346
347// FORM FIELD FEEDBACK STATES
348// --------------------------
349
350// Warning
351.control-group.warning {
352  .formFieldState(@warningText, @warningText, @warningBackground);
353}
354// Error
355.control-group.error {
356  .formFieldState(@errorText, @errorText, @errorBackground);
357}
358// Success
359.control-group.success {
360  .formFieldState(@successText, @successText, @successBackground);
361}
362// Success
363.control-group.info {
364  .formFieldState(@infoText, @infoText, @infoBackground);
365}
366
367// HTML5 invalid states
368// Shares styles with the .control-group.error above
369input:focus:invalid,
370textarea:focus:invalid,
371select:focus:invalid {
372  color: #b94a48;
373  border-color: #ee5f5b;
374  &:focus {
375    border-color: darken(#ee5f5b, 10%);
376    @shadow: 0 0 6px lighten(#ee5f5b, 20%);
377    .box-shadow(@shadow);
378  }
379}
380
381
382
383// FORM ACTIONS
384// ------------
385
386.form-actions {
387  padding: (@baseLineHeight - 1) 20px @baseLineHeight;
388  margin-top: @baseLineHeight;
389  margin-bottom: @baseLineHeight;
390  background-color: @formActionsBackground;
391  border-top: 1px solid #e5e5e5;
392  .clearfix(); // Adding clearfix to allow for .pull-right button containers
393}
394
395
396
397// HELP TEXT
398// ---------
399
400.help-block,
401.help-inline {
402  color: lighten(@textColor, 15%); // lighten the text some for contrast
403}
404
405.help-block {
406  display: block; // account for any element using help-block
407  margin-bottom: @baseLineHeight / 2;
408}
409
410.help-inline {
411  display: inline-block;
412  .ie7-inline-block();
413  vertical-align: middle;
414  padding-left: 5px;
415}
416
417
418
419// INPUT GROUPS
420// ------------
421
422// Allow us to put symbols and text within the input field for a cleaner look
423.input-append,
424.input-prepend {
425  display: inline-block;
426  margin-bottom: @baseLineHeight / 2;
427  vertical-align: middle;
428  font-size: 0; // white space collapse hack
429  white-space: nowrap; // Prevent span and input from separating
430
431  // Reset the white space collapse hack
432  input,
433  select,
434  .uneditable-input,
435  .dropdown-menu,
436  .popover {
437    font-size: @baseFontSize;
438  }
439
440  input,
441  select,
442  .uneditable-input {
443    position: relative; // placed here by default so that on :focus we can place the input above the .add-on for full border and box-shadow goodness
444    margin-bottom: 0; // prevent bottom margin from screwing up alignment in stacked forms
445    *margin-left: 0;
446    vertical-align: top;
447    .border-radius(0 @inputBorderRadius @inputBorderRadius 0);
448    // Make input on top when focused so blue border and shadow always show
449    &:focus {
450      z-index: 2;
451    }
452  }
453  .add-on {
454    display: inline-block;
455    width: auto;
456    height: @baseLineHeight;
457    min-width: 16px;
458    padding: 4px 5px;
459    font-size: @baseFontSize;
460    font-weight: normal;
461    line-height: @baseLineHeight;
462    text-align: center;
463    text-shadow: 0 1px 0 @white;
464    background-color: @grayLighter;
465    border: 1px solid #ccc;
466  }
467  .add-on,
468  .btn,
469  .btn-group > .dropdown-toggle {
470    vertical-align: top;
471    .border-radius(0);
472  }
473  .active {
474    background-color: lighten(@green, 30);
475    border-color: @green;
476  }
477}
478
479.input-prepend {
480  .add-on,
481  .btn {
482    margin-right: -1px;
483  }
484  .add-on:first-child,
485  .btn:first-child {
486    // FYI, `.btn:first-child` accounts for a button group that's prepended
487    .border-radius(@inputBorderRadius 0 0 @inputBorderRadius);
488  }
489}
490
491.input-append {
492  input,
493  select,
494  .uneditable-input {
495    .border-radius(@inputBorderRadius 0 0 @inputBorderRadius);
496    + .btn-group .btn:last-child {
497      .border-radius(0 @inputBorderRadius @inputBorderRadius 0);
498    }
499  }
500  .add-on,
501  .btn,
502  .btn-group {
503    margin-left: -1px;
504  }
505  .add-on:last-child,
506  .btn:last-child,
507  .btn-group:last-child > .dropdown-toggle {
508    .border-radius(0 @inputBorderRadius @inputBorderRadius 0);
509  }
510}
511
512// Remove all border-radius for inputs with both prepend and append
513.input-prepend.input-append {
514  input,
515  select,
516  .uneditable-input {
517    .border-radius(0);
518    + .btn-group .btn {
519      .border-radius(0 @inputBorderRadius @inputBorderRadius 0);
520    }
521  }
522  .add-on:first-child,
523  .btn:first-child {
524    margin-right: -1px;
525    .border-radius(@inputBorderRadius 0 0 @inputBorderRadius);
526  }
527  .add-on:last-child,
528  .btn:last-child {
529    margin-left: -1px;
530    .border-radius(0 @inputBorderRadius @inputBorderRadius 0);
531  }
532  .btn-group:first-child {
533    margin-left: 0;
534  }
535}
536
537
538
539
540// SEARCH FORM
541// -----------
542
543input.search-query {
544  padding-right: 14px;
545  padding-right: 4px \9;
546  padding-left: 14px;
547  padding-left: 4px \9; /* IE7-8 doesn't have border-radius, so don't indent the padding */
548  margin-bottom: 0; // Remove the default margin on all inputs
549  .border-radius(15px);
550}
551
552/* Allow for input prepend/append in search forms */
553.form-search .input-append .search-query,
554.form-search .input-prepend .search-query {
555  .border-radius(0); // Override due to specificity
556}
557.form-search .input-append .search-query {
558  .border-radius(14px 0 0 14px);
559}
560.form-search .input-append .btn {
561  .border-radius(0 14px 14px 0);
562}
563.form-search .input-prepend .search-query {
564  .border-radius(0 14px 14px 0);
565}
566.form-search .input-prepend .btn {
567  .border-radius(14px 0 0 14px);
568}
569
570
571
572
573// HORIZONTAL & VERTICAL FORMS
574// ---------------------------
575
576// Common properties
577// -----------------
578
579.form-search,
580.form-inline,
581.form-horizontal {
582  input,
583  textarea,
584  select,
585  .help-inline,
586  .uneditable-input,
587  .input-prepend,
588  .input-append {
589    display: inline-block;
590    .ie7-inline-block();
591    margin-bottom: 0;
592    vertical-align: middle;
593  }
594  // Re-hide hidden elements due to specifity
595  .hide {
596    display: none;
597  }
598}
599.form-search label,
600.form-inline label,
601.form-search .btn-group,
602.form-inline .btn-group {
603  display: inline-block;
604}
605// Remove margin for input-prepend/-append
606.form-search .input-append,
607.form-inline .input-append,
608.form-search .input-prepend,
609.form-inline .input-prepend {
610  margin-bottom: 0;
611}
612// Inline checkbox/radio labels (remove padding on left)
613.form-search .radio,
614.form-search .checkbox,
615.form-inline .radio,
616.form-inline .checkbox {
617  padding-left: 0;
618  margin-bottom: 0;
619  vertical-align: middle;
620}
621// Remove float and margin, set to inline-block
622.form-search .radio input[type="radio"],
623.form-search .checkbox input[type="checkbox"],
624.form-inline .radio input[type="radio"],
625.form-inline .checkbox input[type="checkbox"] {
626  float: left;
627  margin-right: 3px;
628  margin-left: 0;
629}
630
631
632// Margin to space out fieldsets
633.control-group {
634  margin-bottom: @baseLineHeight / 2;
635}
636
637// Legend collapses margin, so next element is responsible for spacing
638legend + .control-group {
639  margin-top: @baseLineHeight;
640  -webkit-margin-top-collapse: separate;
641}
642
643// Horizontal-specific styles
644// --------------------------
645
646.form-horizontal {
647  // Increase spacing between groups
648  .control-group {
649    margin-bottom: @baseLineHeight;
650    .clearfix();
651  }
652  // Float the labels left
653  .control-label {
654    float: left;
655    width: @horizontalComponentOffset - 20;
656    padding-top: 5px;
657    text-align: right;
658  }
659  // Move over all input controls and content
660  .controls {
661    // Super jank IE7 fix to ensure the inputs in .input-append and input-prepend
662    // don't inherit the margin of the parent, in this case .controls
663    *display: inline-block;
664    *padding-left: 20px;
665    margin-left: @horizontalComponentOffset;
666    *margin-left: 0;
667    &:first-child {
668      *padding-left: @horizontalComponentOffset;
669    }
670  }
671  // Remove bottom margin on block level help text since that's accounted for on .control-group
672  .help-block {
673    margin-bottom: 0;
674  }
675  // And apply it only to .help-block instances that follow a form control
676  input,
677  select,
678  textarea,
679  .uneditable-input,
680  .input-prepend,
681  .input-append {
682    + .help-block {
683      margin-top: @baseLineHeight / 2;
684    }
685  }
686  // Move over buttons in .form-actions to align with .controls
687  .form-actions {
688    padding-left: @horizontalComponentOffset;
689  }
690}
691