3

I've been trying to apply carets to input-group elements in Bootstrap 3. Failing so far. Tried using table-cell display for the inserted pseudo element, tried absolute positioning, tried using the content property to display a web font caret instead of my preferred CSS triangle caret. Just can't wrap my head around this one.

Here's a JSFiddle (the red borders being where I'd expect the caret to show).

.input-group .input-group-addon:last-child:before,
.input-group .input-group-btn:last-child:before,
.input-group .input-group-addon:not(:last-child):before,
.input-group .input-group-btn:not(:last-child):before {
  position: absolute;
  content: '';
  width: 0;
  height: 0;
  border: 10px solid transparent;
  margin: auto;
  top: 0;
  bottom: 0;
  z-index: 1000;
}

.input-group .input-group-addon:last-child:before,
.input-group .input-group-btn:last-child:before {
  border-right-color: red;
  right: 0;
}

.input-group .input-group-addon:not(:last-child):before,
.input-group .input-group-btn:not(:last-child):before {
  border-left-color: red;
  left: 0;
}

EDIT : Based on an answer, I modified the styles which now work fine in all but IE10 and below. IE offsets left-aligned input-group carets by 4px as can be seen here http://jsfiddle.net/W8mFS/3/. Any ideas how to fix this up?

The updated CSS:

.input-group.input-group-caret span:after,
.input-group.input-group-caret > input + span:before {
  position: absolute;
  content: '';
  width: 0;
  height: 0;
  top: 0;
  bottom: 0;
  margin: auto;
  border: 10px solid transparent;
}

.input-group.input-group-caret > input + span:before {
  border-right-color: #cccccc;
  margin-left: -20px;
}

.input-group.input-group-caret > input + span:empty:before {
  margin-left: -44px;
}

.input-group.input-group-caret > input + span:after {
  border-left-color: transparent;
}

.input-group.input-group-caret span:after {
  border-left-color: #cccccc;
}

.input-group.input-group-caret .input-group-addon {
  padding: 0;
}

.input-group.input-group-caret .input-group-addon i {
  font-style: normal;
  margin-left: 12px;
  padding-right: 12px;
}

.input-group.input-group-caret .input-group-addon:empty {
  padding-left: 24px;
}

UPDATE : With added input-group sizing JSFiddle here: http://jsfiddle.net/W8mFS/4/.

The LESS code shows the use of Bootstrap variables to control caret size, margins and padding:

@import "path_to_bootstrap/less/mixins";
@import "path_to_bootstrap/less/variables";

// input-group caret size
@caret-size-base:  ceil(@font-size-base * 0.70);  // ~10px;
@caret-size-large: ceil(@caret-size-base * 1.20); // ~12px;
@caret-size-small: ceil(@caret-size-base * 0.80); // ~8px;

// input-group caret
.input-group.input-group-caret {
  span:after,
  > input + span:before {
    position: absolute;
    content: '';
    width: 0;
    height: 0;

    // v-align to middle
    top: 0;
    bottom: 0;
    margin: auto;

    border: @caret-size-base solid transparent;
  }

  > input + span:before { border-right-color: @input-border; margin-left: -( 2 * @caret-size-base ); }                  // right aligned
  > input + span:empty:before { margin-left: -(( 2 * @padding-base-horizontal ) + ( 2 * @caret-size-base )); }          // right aligned
  > input + span:after  { border-left-color: transparent; }                                                             // right aligned
  span:after  { border-left-color: @input-border; }                                                                     // left aligned

  // sizing
  &.input-group-sm {
    span:after,
    > input + span:before {
      border: @caret-size-small solid transparent;
    }

    > input + span:before { border-right-color: @input-border; margin-left: -( 2 * @caret-size-small ); }               // right aligned
    > input + span:empty:before { margin-left: -(( 2 * @padding-base-horizontal ) + ( 2 * @caret-size-small )); }       // right aligned
    > input + span:after  { border-left-color: transparent; }                                                           // right aligned
    span:after  { border-left-color: @input-border; }                                                                   // left aligned
  }

  &.input-group-lg {
    span:after,
    > input + span:before {
      border: @caret-size-large solid transparent;
    }

    > input + span:before { border-right-color: @input-border; margin-left: -( 2 * @caret-size-large ); }               // right aligned
    > input + span:empty:before { margin-left: -(( 2 * @padding-base-horizontal ) + ( 2 * @caret-size-large )); }       // right aligned
    > input + span:after  { border-left-color: transparent; }                                                           // right aligned
    span:after  { border-left-color: @input-border; }                                                                   // left aligned
  }

  // input-group caret alignment fixes
  .input-group-addon {
    padding: 0;

    i {
      font-style: normal;
      margin-left: @padding-base-horizontal;
      padding-right: @padding-base-horizontal;
    }

    // fix-up alignment of empty addon
    &:empty {
      padding-left: 2 * @padding-base-horizontal;
    }
  }
}
Karl Offenberger
  • 85
  • 1
  • 2
  • 10
  • i'm not sure i understand your question well. It this what you are looking for: http://bootply.com/83654 – Bass Jobsen Sep 27 '13 at 17:52
  • Yes, that's exactly what I am looking to achieve. The problem I have is defining a set of CSS rules that will achieve this effect consistently across all possible combinations of the input-group contents. e.g. input-group-addon or input-group-btn preceeded by form-control and vice versa, only apply to last element of input-group-* and flip caret depending on directionality e.g. form-control comes before or after input-group-* – Karl Offenberger Sep 27 '13 at 18:43
  • 1
    create a new question for your new problem maybe? – Bass Jobsen Sep 28 '13 at 13:14

1 Answers1

6

It seems .input-group > input + span:before will be a good selector for Right Aligned. But there will also be the problem that box-sizing : border-box (Why did Bootstrap 3 switch to box-sizing: border-box?) breaks the carets / forms. (width include :after and :before too?)

see: http://bootply.com/83702

.input-group > input + span:before {
  display: inline-block;
  width: 0;
  height: 0;
  border-right: 10px solid red;
  border-top: 10px solid transparent;
  border-left: 0 dotted;
  border-bottom: 10px solid transparent;

  vertical-align: middle;
  margin-left: 2px;
  content:'';
}
Community
  • 1
  • 1
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
  • Awesome! Your selectors for left- and right-aligned `input-groups` had me on the right track. I found that the `border-box` model didn't really affect the caret positioning in the end. However, see [http://jsfiddle.net/W8mFS/](http://jsfiddle.net/W8mFS/) which works fine in all but IE10 and below - some left-aligned `input-group` carets are mis-aligned by `4px` :-( Tried using IE hacks (the ominous `\9`) to fix it, but couldn't get it right. Any ideas? – Karl Offenberger Sep 28 '13 at 11:50
  • great. You did not update your fiddle? Sorry i don't have IE to test. Maybe this the same for width: https://shanetomlinson.com/2012/box-sizing-border-box-padding-and-min-height-bug-in-firefox-and-ie/ – Bass Jobsen Sep 28 '13 at 12:10
  • Sorry, updated the fiddle link in my original post. Here's the current fiddle: [http://jsfiddle.net/W8mFS/3/](http://jsfiddle.net/W8mFS/3/). Wouldn't know if it was the same issue described in your comment's link related to `box-sizing` as I am still a novice to these specific browser differences, bugs, workarounds and fuggly hacks. – Karl Offenberger Sep 28 '13 at 12:36
  • Nice work. I see you add the position:asbsolute which solve some problems (i expect i will give you more troubles). You add margins and padding. I think this compensate some internal padding (so still box-sizing related). The original Bootstrap's caret have a margin-left of 2px, this maybe helps to fix your IE problem. – Bass Jobsen Sep 28 '13 at 13:12
  • What troubles do you expect from using `position: absolute` for the pseudo element? I don't mind adjusting some of the padding and margins as the actual caret additions are written in LESS where I plug in Bootstrap variables. – Karl Offenberger Sep 28 '13 at 13:44
  • i expect the absolute position of :after/:before will be unexpected but it is not as you have shown – Bass Jobsen Sep 28 '13 at 13:46