forms.less 14.6 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
  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.
Mark Otto's avatar
Mark Otto committed
127
128
129
  .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
  &[disabled],
  &[readonly],
  fieldset[disabled] & {
    background-color: @input-bg-disabled;
145
    opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655
Mark Otto's avatar
Mark Otto committed
146
  }
147
148
149
150
151
  
  &[disabled],
  fieldset[disabled] & {
    cursor: @cursor-disabled;
  }
Mark Otto's avatar
Mark Otto committed
152
153
154
155
156
157
158

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

159
160
161
162
163
164
165
166
167
168
169
170
171

// 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;
}


172
// Special styles for iOS temporal inputs
173
//
174
// In Mobile Safari, setting `display: block` on temporal inputs causes the
Mark Otto's avatar
Mark Otto committed
175
176
// 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
177
// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
178

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

    &.input-sm,
    .input-group-sm & {
      line-height: @input-height-small;
    }

    &.input-lg,
    .input-group-lg & {
      line-height: @input-height-large;
    }
195
196
197
  }
}

Mark Otto's avatar
Mark Otto committed
198
199
200
201
202
203
204

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

.form-group {
Kevin Kirsche's avatar
Kevin Kirsche committed
205
  margin-bottom: @form-group-margin-bottom;
Mark Otto's avatar
Mark Otto committed
206
207
208
209
210
211
}


// Checkboxes and radios
//
// Indent the labels to position radios/checkboxes as hanging controls.
212
213
214

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

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

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

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

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

Mark Otto's avatar
Mark Otto committed
289

290
291
292
293
294
295
296
297
298
299
300
// 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;
301
  min-height: (@line-height-computed + @font-size-base);
302
303
304
305
306
307
308
309
310

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


Mark Otto's avatar
Mark Otto committed
311
// Form control sizing
Mark Otto's avatar
Mark Otto committed
312
313
314
//
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.
315
316
317
//
// 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
318

319
.input-sm {
320
  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);
321
}
322
323
324
325
.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);
  }
326
327
328
329
330
  .form-control-static {
    height: @input-height-small;
    padding: @padding-small-vertical @padding-small-horizontal;
    font-size: @font-size-small;
    line-height: @line-height-small;
331
    min-height: (@line-height-computed + @font-size-small);
332
  }
333
}
334

335
.input-lg {
336
  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);
337
}
338
339
340
341
.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);
  }
342
343
344
345
346
  .form-control-static {
    height: @input-height-large;
    padding: @padding-large-vertical @padding-large-horizontal;
    font-size: @font-size-large;
    line-height: @line-height-large;
347
    min-height: (@line-height-computed + @font-size-large);
348
  }
349
}
350

Mark Otto's avatar
Mark Otto committed
351

Mark Otto's avatar
Mark Otto committed
352
353
354
// Form control feedback states
//
// Apply contextual and semantic states to individual form controls.
355

356
357
358
359
360
361
362
363
.has-feedback {
  // Enable absolute positioning
  position: relative;

  // Ensure icons don't overlap text
  .form-control {
    padding-right: (@input-height-base * 1.25);
  }
364
365
366
367
}
// Feedback icon (requires .glyphicon classes)
.form-control-feedback {
  position: absolute;
368
  top: 0;
369
  right: 0;
370
  z-index: 2; // Ensure icon is above input groups
371
372
373
374
375
  display: block;
  width: @input-height-base;
  height: @input-height-base;
  line-height: @input-height-base;
  text-align: center;
Kyle's avatar
Kyle committed
376
  pointer-events: none;
377
378
379
380
381
382
383
384
385
386
}
.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;
387
388
389
}

// Feedback states
390
391
392
.has-success {
  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);
}
393
.has-warning {
394
  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);
395
}
396
.has-error {
397
  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
398
}
399

400
401
// Reposition feedback icon if input has visible label above
.has-feedback label {
Mark Otto's avatar
Mark Otto committed
402

403
404
405
406
407
408
  & ~ .form-control-feedback {
     top: (@line-height-computed + 5); // Height of the `label` and its margin
  }
  &.sr-only ~ .form-control-feedback {
     top: 0;
  }
409
410
411
}


Mark Otto's avatar
Mark Otto committed
412
413
414
415
// 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.
416

417
.help-block {
418
  display: block; // account for any element using help-block
Mark Otto's avatar
Mark Otto committed
419
420
421
  margin-top: 5px;
  margin-bottom: 10px;
  color: lighten(@text-color, 25%); // lighten the text some for contrast
Jacob Thornton's avatar
Jacob Thornton committed
422
}
423
424
425
426


// Inline forms
//
427
428
429
430
431
432
// 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).
433
434
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
435
436

.form-inline {
437

438
  // Kick in the inline
439
  @media (min-width: @screen-sm-min) {
440
    // Inline-block all the things for "inline"
441
    .form-group {
442
443
444
445
      display: inline-block;
      margin-bottom: 0;
      vertical-align: middle;
    }
446
447
448
449

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

454
455
456
457
458
    // Make static controls behave like regular ones
    .form-control-static {
      display: inline-block;
    }

Mark Otto's avatar
Mark Otto committed
459
460
461
462
463
464
465
466
467
468
469
    .input-group {
      display: inline-table;
      vertical-align: middle;

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

470
471
472
473
    // Input groups need that 100% width though
    .input-group > .form-control {
      width: 100%;
    }
474

475
476
477
    .control-label {
      margin-bottom: 0;
      vertical-align: middle;
478
479
    }

480
    // Remove default margin on radios/checkboxes that were used for stacking, and
481
    // then undo the floating of radios and checkboxes to match.
482
483
484
485
486
    .radio,
    .checkbox {
      display: inline-block;
      margin-top: 0;
      margin-bottom: 0;
487
      vertical-align: middle;
488
489
490
491

      label {
        padding-left: 0;
      }
492
493
494
    }
    .radio input[type="radio"],
    .checkbox input[type="checkbox"] {
495
      position: relative;
496
497
      margin-left: 0;
    }
498

Mark Otto's avatar
Mark Otto committed
499
    // Re-override the feedback icon.
500
501
502
    .has-feedback .form-control-feedback {
      top: 0;
    }
503
504
505
506
507
508
509
510
511
512
  }
}


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

514
515
  // Consistent vertical alignment of radios and checkboxes
  //
516
  // Labels also get some reset styles, but that is scoped to a media query below.
517
518
519
520
521
522
523
524
  .radio,
  .checkbox,
  .radio-inline,
  .checkbox-inline {
    margin-top: 0;
    margin-bottom: 0;
    padding-top: (@padding-base-vertical + 1); // Default padding plus a border
  }
525
526
527
528
  // Account for padding we're adding to ensure the alignment and of help text
  // and other content below items
  .radio,
  .checkbox {
529
    min-height: (@line-height-computed + (@padding-base-vertical + 1));
530
  }
531
532

  // Make form groups behave like rows
533
534
535
536
  .form-group {
    .make-row();
  }

537
538
  // 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
539
  @media (min-width: @screen-sm-min) {
540
541
    .control-label {
      text-align: right;
542
543
      margin-bottom: 0;
      padding-top: (@padding-base-vertical + 1); // Default padding plus a border
544
    }
545
  }
546
547
548
549
550
551
552
553

  // 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);
  }
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

  // 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);
      }
    }
  }
573
}