forms.less 14 KB
Newer Older
1
2
3
//
// Forms
// --------------------------------------------------
4

5

Mark Otto's avatar
Mark Otto committed
6
7
8
// Normalize non-controls
//
// Restyle and baseline non-control form elements.
9
10
11
12
13

fieldset {
  padding: 0;
  margin: 0;
  border: 0;
14
  // Chrome and Firefox set a `min-width: min-content;` on fieldsets,
15
16
17
  // so we reset that to ensure it behaves more like a standard block element.
  // See https://github.com/twbs/bootstrap/issues/12359.
  min-width: 0;
18
}
19

20
21
22
legend {
  display: block;
  width: 100%;
23
  padding: 0;
Mark Otto's avatar
Mark Otto committed
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;
Chris Rebert's avatar
Chris Rebert committed
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

Mark Otto's avatar
Mark Otto committed
40
// Normalize form controls
41
42
43
44
//
// While most of our form styles require extra classes, some basic normalization
// is required to ensure optimum display with or without those classes to better
// address browser inconsistencies.
45

46
47
48
49
50
// Override content-box in Normalize (* isn't specific enough)
input[type="search"] {
  .box-sizing(border-box);
}

Mark Otto's avatar
Mark Otto committed
51
// Position radios and checkboxes better
52
53
input[type="radio"],
input[type="checkbox"] {
54
  margin: 4px 0 0;
Chris Rebert's avatar
Chris Rebert committed
55
  margin-top: 1px \9; // IE8-9
Mark Otto's avatar
Mark Otto committed
56
  line-height: normal;
57
}
Mark Otto's avatar
Mark Otto committed
58

59
// Set the height of file controls to match text inputs
60
input[type="file"] {
61
  display: block;
Mark Otto's avatar
Mark Otto committed
62
}
63

64
65
66
67
68
69
// Make range inputs behave like textual form controls
input[type="range"] {
  display: block;
  width: 100%;
}

Mark Otto's avatar
Mark Otto committed
70
// Make multiple select elements height not fixed
71
72
select[multiple],
select[size] {
Mark Otto's avatar
Mark Otto committed
73
  height: auto;
Mark Otto's avatar
Mark Otto committed
74
75
}

76
// Focus for file, radio, and checkbox
77
78
79
80
81
input[type="file"]:focus,
input[type="radio"]:focus,
input[type="checkbox"]:focus {
  .tab-focus();
}
82

83
84
85
86
87
88
89
90
// Adjust output element
output {
  display: block;
  padding-top: (@padding-base-vertical + 1);
  font-size: @font-size-base;
  line-height: @line-height-base;
  color: @input-color;
}
91

92

Mark Otto's avatar
Mark Otto committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Common form controls
//
// Shared size and type resets for form controls. Apply `.form-control` to any
// of the following form controls:
//
// select
// textarea
// input[type="text"]
// input[type="password"]
// input[type="datetime"]
// input[type="datetime-local"]
// input[type="date"]
// input[type="month"]
// input[type="time"]
// input[type="week"]
// input[type="number"]
// input[type="email"]
// input[type="url"]
// input[type="search"]
// input[type="tel"]
// input[type="color"]

.form-control {
  display: block;
  width: 100%;
  height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)
  padding: @padding-base-vertical @padding-base-horizontal;
  font-size: @font-size-base;
  line-height: @line-height-base;
122
  color: @input-color;
Mark Otto's avatar
Mark Otto committed
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
Mark Otto's avatar
Mark Otto committed
125
126
127
128
129
  border: 1px solid @input-border;
  border-radius: @input-border-radius;
  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
  .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s");

130
131
  // Customize the `:focus` state to imitate native WebKit styles.
  .form-control-focus();
Mark Otto's avatar
Mark Otto committed
132

133
134
135
  // Placeholder
  .placeholder();

Mark Otto's avatar
Mark Otto committed
136
  // Disabled and read-only inputs
137
138
139
140
  //
  // HTML5 says that controls under a fieldset > legend:first-child won't be
  // disabled if the fieldset is disabled. Due to implementation difficulty, we
  // don't honor that edge case; we style them as disabled anyway.
Mark Otto's avatar
Mark Otto committed
141
142
143
  &[disabled],
  &[readonly],
  fieldset[disabled] & {
144
    cursor: @cursor-disabled;
Mark Otto's avatar
Mark Otto committed
145
    background-color: @input-bg-disabled;
146
    opacity: 1; // iOS fix for unreadable disabled content
Mark Otto's avatar
Mark Otto committed
147
148
149
150
151
152
153
154
  }

  // Reset height for `textarea`s
  textarea& {
    height: auto;
  }
}

155
156
157
158
159
160
161
162
163
164
165
166
167

// Search inputs in iOS
//
// This overrides the extra rounded corners on search inputs in iOS so that our
// `.form-control` class can properly style them. Note that this cannot simply
// be added to `.form-control` as it's not specific enough. For details, see
// https://github.com/twbs/bootstrap/issues/11586.

input[type="search"] {
  -webkit-appearance: none;
}


168
// Special styles for iOS temporal inputs
169
//
170
// In Mobile Safari, setting `display: block` on temporal inputs causes the
Mark Otto's avatar
Mark Otto committed
171
172
// text within the input to become vertically misaligned. As a workaround, we
// set a pixel line-height that matches the given height of the input, but only
173
// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
174

Mark Otto's avatar
Mark Otto committed
175
@media screen and (-webkit-min-device-pixel-ratio: 0) {
Mark Otto's avatar
Mark Otto committed
176
177
178
179
180
181
182
183
184
185
  input[type="date"],
  input[type="time"],
  input[type="datetime-local"],
  input[type="month"] {
    line-height: @input-height-base;
  }
  input[type="date"].input-sm,
  input[type="time"].input-sm,
  input[type="datetime-local"].input-sm,
  input[type="month"].input-sm {
186
187
    line-height: @input-height-small;
  }
Mark Otto's avatar
Mark Otto committed
188
189
190
191
  input[type="date"].input-lg,
  input[type="time"].input-lg,
  input[type="datetime-local"].input-lg,
  input[type="month"].input-lg {
192
    line-height: @input-height-large;
193
194
195
  }
}

Mark Otto's avatar
Mark Otto committed
196
197
198
199
200
201
202
203
204
205
206
207
208
209

// Form groups
//
// Designed to help with the organization and spacing of vertical forms. For
// horizontal forms, use the predefined grid classes.

.form-group {
  margin-bottom: 15px;
}


// Checkboxes and radios
//
// Indent the labels to position radios/checkboxes as hanging controls.
210
211
212

.radio,
.checkbox {
213
  position: relative;
214
  display: block;
Mark Otto's avatar
Mark Otto committed
215
216
  margin-top: 10px;
  margin-bottom: 10px;
Mark Otto's avatar
Mark Otto committed
217

Mark Otto's avatar
Mark Otto committed
218
  label {
219
    min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text
220
221
    padding-left: 20px;
    margin-bottom: 0;
Mark Otto's avatar
Mark Otto committed
222
    font-weight: normal;
223
    cursor: pointer;
Mark Otto's avatar
Mark Otto committed
224
  }
225
}
226
.radio input[type="radio"],
Mark Otto's avatar
Mark Otto committed
227
228
229
.radio-inline input[type="radio"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
230
  position: absolute;
231
  margin-left: -20px;
232
  margin-top: 4px \9;
233
}
234

Mark Otto's avatar
Mark Otto committed
235
236
.radio + .radio,
.checkbox + .checkbox {
Mark Otto's avatar
Mark Otto committed
237
  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing
Mark Otto's avatar
Mark Otto committed
238
}
239

240
// Radios and checkboxes on same line
Mark Otto's avatar
Mark Otto committed
241
242
.radio-inline,
.checkbox-inline {
243
  display: inline-block;
Mark Otto's avatar
Mark Otto committed
244
  padding-left: 20px;
245
  margin-bottom: 0;
246
  vertical-align: middle;
Mark Otto's avatar
Mark Otto committed
247
  font-weight: normal;
248
  cursor: pointer;
249
}
Mark Otto's avatar
Mark Otto committed
250
251
252
.radio-inline + .radio-inline,
.checkbox-inline + .checkbox-inline {
  margin-top: 0;
253
  margin-left: 10px; // space out consecutive inline controls
254
255
}

256
// Apply same disabled cursor tweak as for inputs
257
// Some special care is needed because <label>s don't inherit their parent's `cursor`.
258
//
259
// Note: Neither radios nor checkboxes can be readonly.
260
input[type="radio"],
261
262
263
264
input[type="checkbox"] {
  &[disabled],
  &.disabled,
  fieldset[disabled] & {
265
    cursor: @cursor-disabled;
266
267
268
  }
}
// These classes are used directly on <label>s
269
270
.radio-inline,
.checkbox-inline {
271
  &.disabled,
272
  fieldset[disabled] & {
273
    cursor: @cursor-disabled;
274
275
  }
}
276
277
278
279
280
281
// These classes are used on elements with <label> descendants
.radio,
.checkbox {
  &.disabled,
  fieldset[disabled] & {
    label {
282
      cursor: @cursor-disabled;
283
284
285
    }
  }
}
286

Mark Otto's avatar
Mark Otto committed
287

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
// Static form control text
//
// Apply class to a `p` element to make any string of text align with labels in
// a horizontal form layout.

.form-control-static {
  // Size it appropriately next to real form controls
  padding-top: (@padding-base-vertical + 1);
  padding-bottom: (@padding-base-vertical + 1);
  // Remove default margin from `p`
  margin-bottom: 0;

  &.input-lg,
  &.input-sm {
    padding-left: 0;
    padding-right: 0;
  }
}


Mark Otto's avatar
Mark Otto committed
308
// Form control sizing
Mark Otto's avatar
Mark Otto committed
309
310
311
//
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.
312
313
314
//
// The `.form-group-* form-control` variations are sadly duplicated to avoid the
// issue documented in https://github.com/twbs/bootstrap/issues/15074.
Mark Otto's avatar
Mark Otto committed
315

316
.input-sm {
317
  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);
318
}
319
320
321
322
323
.form-group-sm {
  .form-control {
    .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);
  }
}
324

325
.input-lg {
326
  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);
327
}
328
329
330
331
332
.form-group-lg {
  .form-control {
    .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);
  }
}
333

Mark Otto's avatar
Mark Otto committed
334

Mark Otto's avatar
Mark Otto committed
335
336
337
// Form control feedback states
//
// Apply contextual and semantic states to individual form controls.
338

339
340
341
342
343
344
345
346
.has-feedback {
  // Enable absolute positioning
  position: relative;

  // Ensure icons don't overlap text
  .form-control {
    padding-right: (@input-height-base * 1.25);
  }
347
348
349
350
}
// Feedback icon (requires .glyphicon classes)
.form-control-feedback {
  position: absolute;
351
  top: 0;
352
  right: 0;
353
  z-index: 2; // Ensure icon is above input groups
354
355
356
357
358
  display: block;
  width: @input-height-base;
  height: @input-height-base;
  line-height: @input-height-base;
  text-align: center;
Kyle's avatar
Kyle committed
359
  pointer-events: none;
360
361
362
363
364
365
366
367
368
369
}
.input-lg + .form-control-feedback {
  width: @input-height-large;
  height: @input-height-large;
  line-height: @input-height-large;
}
.input-sm + .form-control-feedback {
  width: @input-height-small;
  height: @input-height-small;
  line-height: @input-height-small;
370
371
372
}

// Feedback states
373
374
375
.has-success {
  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);
}
376
.has-warning {
377
  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);
378
}
379
.has-error {
380
  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
381
}
382

383
384
// Reposition feedback icon if input has visible label above
.has-feedback label {
Mark Otto's avatar
Mark Otto committed
385

386
387
388
389
390
391
  & ~ .form-control-feedback {
     top: (@line-height-computed + 5); // Height of the `label` and its margin
  }
  &.sr-only ~ .form-control-feedback {
     top: 0;
  }
392
393
394
}


Mark Otto's avatar
Mark Otto committed
395
396
397
398
// Help text
//
// Apply to any element you wish to create light text for placement immediately
// below a form control. Use for general help, formatting, or instructional text.
399

400
.help-block {
401
  display: block; // account for any element using help-block
Mark Otto's avatar
Mark Otto committed
402
403
404
  margin-top: 5px;
  margin-bottom: 10px;
  color: lighten(@text-color, 25%); // lighten the text some for contrast
Jacob Thornton's avatar
Jacob Thornton committed
405
}
406
407
408
409


// Inline forms
//
410
411
412
413
414
415
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
// forms begin stacked on extra small (mobile) devices and then go inline when
// viewports reach <768px.
//
// Requires wrapping inputs and labels with `.form-group` for proper display of
// default HTML form controls and our custom form controls (e.g., input groups).
416
417
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
418
419

.form-inline {
420

421
  // Kick in the inline
422
  @media (min-width: @screen-sm-min) {
423
    // Inline-block all the things for "inline"
424
    .form-group {
425
426
427
428
      display: inline-block;
      margin-bottom: 0;
      vertical-align: middle;
    }
429
430
431
432

    // In navbar-form, allow folks to *not* use `.form-group`
    .form-control {
      display: inline-block;
433
      width: auto; // Prevent labels from stacking above inputs in `.form-group`
434
      vertical-align: middle;
435
    }
Mark Otto's avatar
Mark Otto committed
436

437
438
439
440
441
    // Make static controls behave like regular ones
    .form-control-static {
      display: inline-block;
    }

Mark Otto's avatar
Mark Otto committed
442
443
444
445
446
447
448
449
450
451
452
    .input-group {
      display: inline-table;
      vertical-align: middle;

      .input-group-addon,
      .input-group-btn,
      .form-control {
        width: auto;
      }
    }

453
454
455
456
    // Input groups need that 100% width though
    .input-group > .form-control {
      width: 100%;
    }
457

458
459
460
    .control-label {
      margin-bottom: 0;
      vertical-align: middle;
461
462
    }

463
    // Remove default margin on radios/checkboxes that were used for stacking, and
464
    // then undo the floating of radios and checkboxes to match.
465
466
467
468
469
    .radio,
    .checkbox {
      display: inline-block;
      margin-top: 0;
      margin-bottom: 0;
470
      vertical-align: middle;
471
472
473
474

      label {
        padding-left: 0;
      }
475
476
477
    }
    .radio input[type="radio"],
    .checkbox input[type="checkbox"] {
478
      position: relative;
479
480
      margin-left: 0;
    }
481

Mark Otto's avatar
Mark Otto committed
482
    // Re-override the feedback icon.
483
484
485
    .has-feedback .form-control-feedback {
      top: 0;
    }
486
487
488
489
490
491
492
493
494
495
  }
}


// Horizontal forms
//
// Horizontal forms are built on grid classes and allow you to create forms with
// labels on the left and inputs on the right.

.form-horizontal {
496

497
498
  // Consistent vertical alignment of radios and checkboxes
  //
499
  // Labels also get some reset styles, but that is scoped to a media query below.
500
501
502
503
504
505
506
507
  .radio,
  .checkbox,
  .radio-inline,
  .checkbox-inline {
    margin-top: 0;
    margin-bottom: 0;
    padding-top: (@padding-base-vertical + 1); // Default padding plus a border
  }
508
509
510
511
  // Account for padding we're adding to ensure the alignment and of help text
  // and other content below items
  .radio,
  .checkbox {
512
    min-height: (@line-height-computed + (@padding-base-vertical + 1));
513
  }
514
515

  // Make form groups behave like rows
516
517
518
519
  .form-group {
    .make-row();
  }

520
521
  // Reset spacing and right align labels, but scope to media queries so that
  // labels on narrow viewports stack the same as a default form example.
Zlatan Vasović's avatar
Zlatan Vasović committed
522
  @media (min-width: @screen-sm-min) {
523
524
    .control-label {
      text-align: right;
525
526
      margin-bottom: 0;
      padding-top: (@padding-base-vertical + 1); // Default padding plus a border
527
    }
528
  }
529
530
531
532
533
534
535
536

  // Validation states
  //
  // Reposition the icon because it's now within a grid column and columns have
  // `position: relative;` on them. Also accounts for the grid gutter padding.
  .has-feedback .form-control-feedback {
    right: (@grid-gutter-width / 2);
  }
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

  // Form group sizes
  //
  // Quick utility class for applying `.input-lg` and `.input-sm` styles to the
  // inputs and labels within a `.form-group`.
  .form-group-lg {
    @media (min-width: @screen-sm-min) {
      .control-label {
        padding-top: ((@padding-large-vertical * @line-height-large) + 1);
      }
    }
  }
  .form-group-sm {
    @media (min-width: @screen-sm-min) {
      .control-label {
        padding-top: (@padding-small-vertical + 1);
      }
    }
  }
556
}