2

I need to style a text input like this input

The requiremets are:

  1. fluid width (stretches to container width)
  2. border color changes on focus
  3. border color changes on error

Is there some simple way to do it with css?

What I've come up now is quite complex, requires js and it works not too smoothly -

<div class="inpt"><input type="text" /></div>

jQuery(".inpt").delegate("*", "focus blur", function() {
    var elem = jQuery(this);
    var elem2 = jQuery(this).parent();
    setTimeout(function() {
        elem2.toggleClass("focused", elem.is(":focus"));
    }, 0);
});

http://jsfiddle.net/4sKV9/

I had to wrap an input in a div and style that div using images on :before and :after
Obviously :active doesn't work for div in this case and thus I had to toggle some class with a script.

I feel like there must be some simple solution that I'm missing. Can someone suggest anything better?

Community
  • 1
  • 1
artemean
  • 805
  • 1
  • 10
  • 24

2 Answers2

2

This solution uses jQuery to detect focus on the <input> and add/remove .focused class on parent container.

Both left and right arrrows are made of CSS with 2 <span> elements and :before / :after.

The input is responsive and adapts to the width of it's container.

FIDDLE

HTML :

<div class="inpt"> 
    <span class="left arrow"></span>
    <input type="text" /> 
    <span class="right arrow"></span>
</div>

CSS :

.inpt {
    position:relative;
    margin:5%;
    width:50%;
}
.left, .right {
    position: absolute;
    top:14px;
}
.right {
    right:0;
}
.arrow:after, .arrow:before {
    top: 50%;
    border: solid transparent;
    content:" ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
}
.arrow:after {
    border-color: rgba(255, 255, 255, 0);
    border-width: 12px;
    margin-top: -12px;
}
.arrow:before {
    border-color: rgba(220, 228, 228, 0);
    border-width: 15px;
    margin-top: -15px;
}
.left:after, .left:before {
    right: 100%;
}
.left:after {
    border-right-color: #fff;
}
.left:before {
    border-right-color: #dce4e4;
}
.right:after, .right:before {
    left: 100%;
}
.right:after {
    border-left-color: #fff;
}
.right:before {
    border-left-color: #dce4e4;
}
.focused input {
    border-color: #afddda;
}
.focused .right:before {
    border-left-color: #afddda;
}
.focused .left:before {
    border-right-color: #afddda;
}
input {
    border-top: 2px #dce4e4 solid;
    border-bottom: 2px #dce4e4 solid;
    border-left:none;
    border-right:none;
    padding:2px 10px 0px;
    height: 29px;
    display: block;
    outline: 0;
    width: 100%;
    margin: 6px 0;
    box-sizing:border-box;
}

jQuery

$('input').focus(function () {
    $(this).parent().addClass('focused');
});

$('input').blur(function () {
    $(this).parent().removeClass('focused');
});
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • Can you change the angle of arrows? – artemean Apr 06 '14 at 15:14
  • @Andrey do you mean make them less wide? – web-tiki Apr 06 '14 at 15:33
  • I mean make them like on the image in my original question. I have to follow the design. – artemean Apr 06 '14 at 15:37
  • 1
    @Andrey sorry to be so long, I had other things to do here is the fiddle : http://jsfiddle.net/webtiki/N36WS/ – web-tiki Apr 06 '14 at 17:33
  • web-tiki Thanks for your input. This solution is not perfect, but I'll mark it as accepted because it seems that nothing better can be found. Just to mention the cons - 1. two additional spans; 2. the border looks a little distorted (especially when you zoom in your browser). Anyways thanks again! – artemean Apr 07 '14 at 13:05
  • @Andrey glad I could help, I can't think of a way to remove those spans, even if `:after/:before` could be used with `` you could only make one triangle. The border can probably be tweaked to make it look less distorted. – web-tiki Apr 07 '14 at 13:09
0

Edit: You do need JS for this. :before and :after can't be applied to input fields. See web-tiki's answer.

You don't need Javascript in this case. :focus is a valid pseudo class in CSS. Have a look at this article about :focus.

input:focus {
    border-color: red;
}

With the help of the pseudo classes :before and :after you can create arrows in pure css, too.

M165437
  • 897
  • 1
  • 10
  • 18
  • You didn't understand what the problem is and you haven't looked into my fiddle. I already used :before and :after. But you have to know that :before and :after elements are not applicable to inputs. So I had to apply them to a wrapper div. But you can't apply :focus or :active on div, you apply it to input. But the styles are tied to a wrapper div, so you need some js to check if an input has focus then toggle class on wrapper div. This is what I did and it works, but I'm still looking for a more elegant solution. – artemean Apr 06 '14 at 14:01
  • The css arrows you suggested won't help because you can only make 45 degree with them. – artemean Apr 06 '14 at 14:04
  • You're right about :before and :after, my mistake. But you can make CSS arrows with less or more then 45 degrees. – M165437 Apr 06 '14 at 14:18