forms.less 13.3 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
144
145
  &[disabled],
  &[readonly],
  fieldset[disabled] & {
    cursor: not-allowed;
    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
171
172
// In Mobile Safari, setting `display: block` on temporal inputs causes the
// text within the input to become vertically misaligned.
// As a workaround, we set a pixel line-height that matches the
173
174
// given height of the input. Since this fucks up everything else, we have to
// appropriately reset it for Internet Explorer and the size variations.
175

176
177
178
179
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
180
  line-height: @input-height-base;
181
182
183
184
185
186
187
188
189
  // IE8+ misaligns the text within date inputs, so we reset
  line-height: @line-height-base ~"\0";

  &.input-sm {
    line-height: @input-height-small;
  }
  &.input-lg {
    line-height: @input-height-large;
  }
190
191
}

Mark Otto's avatar
Mark Otto committed
192
193
194
195
196
197
198
199
200
201
202
203
204
205

// 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.
206
207
208

.radio,
.checkbox {
209
  position: relative;
210
  display: block;
Mark Otto's avatar
Mark Otto committed
211
  min-height: @line-height-computed; // clear the floating input if there is no label text
Mark Otto's avatar
Mark Otto committed
212
213
  margin-top: 10px;
  margin-bottom: 10px;
Mark Otto's avatar
Mark Otto committed
214

Mark Otto's avatar
Mark Otto committed
215
  label {
216
217
    padding-left: 20px;
    margin-bottom: 0;
Mark Otto's avatar
Mark Otto committed
218
    font-weight: normal;
219
    cursor: pointer;
Mark Otto's avatar
Mark Otto committed
220
  }
221
}
222
.radio input[type="radio"],
Mark Otto's avatar
Mark Otto committed
223
224
225
.radio-inline input[type="radio"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
226
  position: absolute;
227
  margin-left: -20px;
228
  margin-top: 4px \9;
229
}
230

Mark Otto's avatar
Mark Otto committed
231
232
.radio + .radio,
.checkbox + .checkbox {
Mark Otto's avatar
Mark Otto committed
233
  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing
Mark Otto's avatar
Mark Otto committed
234
}
235

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

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

Mark Otto's avatar
Mark Otto committed
283

Mark Otto's avatar
Mark Otto committed
284
// Form control sizing
Mark Otto's avatar
Mark Otto committed
285
286
287
288
//
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.

289
.input-sm {
290
  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);
291
292
}

ggam's avatar
ggam committed
293
.input-lg {
294
  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);
295
}
296

Mark Otto's avatar
Mark Otto committed
297

Mark Otto's avatar
Mark Otto committed
298
299
300
// Form control feedback states
//
// Apply contextual and semantic states to individual form controls.
301

302
303
304
305
306
307
308
309
.has-feedback {
  // Enable absolute positioning
  position: relative;

  // Ensure icons don't overlap text
  .form-control {
    padding-right: (@input-height-base * 1.25);
  }
310
311
312
313
314
315
}
// Feedback icon (requires .glyphicon classes)
.form-control-feedback {
  position: absolute;
  top: (@line-height-computed + 5); // Height of the `label` and its margin
  right: 0;
316
  z-index: 2; // Ensure icon is above input groups
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  display: block;
  width: @input-height-base;
  height: @input-height-base;
  line-height: @input-height-base;
  text-align: center;
}
.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;
332
333
334
}

// Feedback states
335
336
337
.has-success {
  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);
}
338
.has-warning {
339
  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);
340
}
341
.has-error {
342
  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
343
}
344
345


346
347
// Reposition feedback icon if label is hidden with "screenreader only" state
.has-feedback label.sr-only ~ .form-control-feedback {
Sean Dwyer's avatar
Sean Dwyer committed
348
  top: 0;
349
350
351
}


352
353
354
355
356
357
// 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 {
358
359
360
361
362
  // 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;
363
364
365
}


Mark Otto's avatar
Mark Otto committed
366
367
368
369
// 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.
370

371
.help-block {
372
  display: block; // account for any element using help-block
Mark Otto's avatar
Mark Otto committed
373
374
375
  margin-top: 5px;
  margin-bottom: 10px;
  color: lighten(@text-color, 25%); // lighten the text some for contrast
Jacob Thornton's avatar
Jacob Thornton committed
376
}
377
378
379
380
381



// Inline forms
//
382
383
384
385
386
387
// 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).
388
389
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
390
391

.form-inline {
392

393
  // Kick in the inline
394
  @media (min-width: @screen-sm-min) {
395
    // Inline-block all the things for "inline"
396
    .form-group {
397
398
399
400
      display: inline-block;
      margin-bottom: 0;
      vertical-align: middle;
    }
401
402
403
404

    // In navbar-form, allow folks to *not* use `.form-group`
    .form-control {
      display: inline-block;
405
      width: auto; // Prevent labels from stacking above inputs in `.form-group`
406
      vertical-align: middle;
407
    }
Mark Otto's avatar
Mark Otto committed
408
409
410
411
412
413
414
415
416
417
418
419

    .input-group {
      display: inline-table;
      vertical-align: middle;

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

420
421
422
423
    // Input groups need that 100% width though
    .input-group > .form-control {
      width: 100%;
    }
424

425
426
427
    .control-label {
      margin-bottom: 0;
      vertical-align: middle;
428
429
    }

430
431
432
433
434
435
436
437
    // Remove default margin on radios/checkboxes that were used for stacking, and
    // then undo the floating of radios and checkboxes to match (which also avoids
    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).
    .radio,
    .checkbox {
      display: inline-block;
      margin-top: 0;
      margin-bottom: 0;
438
      vertical-align: middle;
439
440
441
442

      label {
        padding-left: 0;
      }
443
444
445
446
447
448
    }
    .radio input[type="radio"],
    .checkbox input[type="checkbox"] {
      float: none;
      margin-left: 0;
    }
449
450
451
452
453
454
455
456

    // 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 {
      top: 0;
    }
457
458
459
460
461
462
463
464
465
466
  }
}


// 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 {
467

468
469
  // Consistent vertical alignment of radios and checkboxes
  //
470
  // Labels also get some reset styles, but that is scoped to a media query below.
471
472
473
474
475
476
477
478
  .radio,
  .checkbox,
  .radio-inline,
  .checkbox-inline {
    margin-top: 0;
    margin-bottom: 0;
    padding-top: (@padding-base-vertical + 1); // Default padding plus a border
  }
479
480
481
482
  // Account for padding we're adding to ensure the alignment and of help text
  // and other content below items
  .radio,
  .checkbox {
483
    min-height: (@line-height-computed + (@padding-base-vertical + 1));
484
  }
485
486

  // Make form groups behave like rows
487
488
489
490
  .form-group {
    .make-row();
  }

491
492
  // 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
493
  @media (min-width: @screen-sm-min) {
494
495
    .control-label {
      text-align: right;
496
497
      margin-bottom: 0;
      padding-top: (@padding-base-vertical + 1); // Default padding plus a border
498
    }
499
  }
500
501
502
503
504
505
506
507
508

  // 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 {
    top: 0;
    right: (@grid-gutter-width / 2);
  }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533

  // 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-control {
      &:extend(.input-lg);
    }
  }
  .form-group-sm {
    @media (min-width: @screen-sm-min) {
      .control-label {
        padding-top: (@padding-small-vertical + 1);
      }
    }
    .form-control {
      &:extend(.input-sm);
    }
  }
534
}