8

I need to create an input text box with a bottom border and the side borders should span half the height of the input on left and right.

Is there an easy way to design this in CSS?

Image is show below: Input with border on half of it's height

Harry
  • 87,580
  • 25
  • 202
  • 214
anu g prem
  • 545
  • 5
  • 15
  • Yes there is. Also SO is for code problem, not for code request, so try something and, if it fails, come and show the community :) – GillesC May 07 '15 at 09:49
  • Try something like this using css masks http://stackoverflow.com/a/8804714/4615177 – George May 07 '15 at 09:50

5 Answers5

13

Maybe this could be an elegant solution.

If you use background then you can specify really nicely where what goes and it improves readability a bit.

input[type="text"] {
  padding: 10px;

  background: linear-gradient(#000, #000), linear-gradient(#000, #000), linear-gradient(#000, #000);
  background-size: 1px 20%, 100% 1px, 1px 20%;
  background-position: bottom left, bottom center, bottom right;
  background-repeat: no-repeat;

  border: none;
  color: #999;
}
<input type="text" />
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
Criss Lion
  • 209
  • 1
  • 7
  • 1
    This could be better than box-shadows is that from what I have seen box-shadows have bad performance on mobile devices so stacking them especially if you will have multiple input boxes would lead to bad performance. – Criss Lion May 07 '15 at 10:17
  • 4
    Can you elaborate on performance and box shadow for mobile devices or link a reference? I am aware of animations beeing not costly performance wise for box shadow animations (which would be intersting to compare with gradients) but not for stacking. Also, browser support is wider for box-shadows ([IE9 + for box-shadows](http://caniuse.com/#feat=css-boxshadow)) – web-tiki May 07 '15 at 10:28
  • 1
    @CrissLion: This probably has one of the least cross browser compatibilities, as well as performance issues. I am lead to believe box-shadows are just as efficient, (if not more) than gradients. – jbutler483 May 07 '15 at 10:32
  • BTW I meant "being costly" instead off "being not costly" in my last comment. Sorry for that typo – web-tiki May 07 '15 at 10:45
  • 1
    @web-tiki I am working on web apps currently and box-shadow seems to be the biggest performance killer. From what I dig up on the net it seems to be a similar problem for a lot of people http://www.html5rocks.com/en/tutorials/speed/css-paint-times/ This is maybe fixed now but from this article stacking rules does not seem to increase processing time linearly. https://quickleft.com/blog/4-steps-to-minimizing-rendering-issues-in-cordova-applications/ Here it is mentioned it specifically (I know it is for cordova, but cordova uses web view and renders like browser). – Criss Lion May 07 '15 at 11:26
  • 1
    @web-tiki I could not find direct link but I think that linear gradient stacking also increases painting time in non-linear way only difference would be that in generates image object. There is no reason to recompute the image if background properties does not change. So it should be as fast after the initial painting as sprite. – Criss Lion May 07 '15 at 11:33
  • 3
    @CrissLion your sources don't speak about gradient rendering so I tested both (your solution and mine) localy in chrome. According to those, painting and rendering times are shorter with box-shadows than with gradients. Results in [this screenshot](http://i.imgur.com/7hAPVZA.png). Left is linear gradients and box-shadows on the right. The test was made on a page with 80 inputs. – web-tiki May 07 '15 at 12:29
  • 1
    @web-tiki I checked myself and you are correct, box-shadow seems to be at least in my case for 80 inputs do painting 2 ms faster, I checked what happens when you set blur for box shadow and painting time tripled for me. So it seems that box-shadow without blur is efficient way to solve this particular problem! – Criss Lion May 07 '15 at 13:16
  • @CrissLion I also think that painting/rendering time isn 't relevant for the OP as the difference wouldn't be noticed compared to browser support, maintainability and comfort of use. – web-tiki May 07 '15 at 13:19
10

With 2 box-shadows, you can achieve the bottom border and small borders on both sides. Here is an example:

input[type=text] {
  width:300px; height:17px;
  border: 0; outline:none;
  padding:0;
  box-shadow: -5px 5px 0px -4px #000, 5px 5px 0px -4px #000;
  text-align:center;
}
<input placeholder="Email" type="text" value=""/>

The spread radius and the X/Y offset of the box-shadows need to be tweaked according to the height of the input and the desired height of left/right borders. As you can see in this example with a different height on the input:

input {
  width:300px; height:40px;
  padding:0;
  border: 0; outline:none;
  box-shadow: -18px 18px 0px -17px #000, 18px 18px 0px -17px #000;
  text-align:center;
}
<input placeholder="Email" type="text" />

Browser support for box-shadows is IE9+.

web-tiki
  • 99,765
  • 32
  • 217
  • 249
6

I would go for a slightly different approach to web-tiki's answer, and use a wrapper div and a pseudo element, as this would not require a fixed height input (but would require this extra element):

input {
  border: none;
}
div {
  display: inline-block;
  position: relative;
  margin-bottom: 30px;
}
div:before {
  content: "";
  position: absolute;
  bottom: 0;
  left: -2px;
  height: 50%;
  width: 100%;
  border: 2px solid black;
  border-top: none;
}
textarea {
  display: block;
  height: 100px;
  /*border:none*/
  /*This was commented to show where text area is*/
}
<div>
  <input type="text" placeholder="Please Enter your PIN" />
</div>

<br/>

<div>
  <textarea placeholder="Please Enter your bank details and mother's maiden name;)"></textarea>
</div>
jbutler483
  • 24,074
  • 9
  • 92
  • 145
4

A linear-gradient based answer already exists in this thread but it is a bit complex and makes use of multiple linear gradients to achieve the border but it can be done with just one linear-gradient.

Using border-bottom on the element avoids the need for one of those linear gradients. Using a linear gradient which is colored for 2px (2 x required border width), repeats in the X-axis and has a negative offset for background-position in X-axis can produce border on left and right using only one gradient instead of two. The negative offset is equal to border's width (1px). It means that 1px of the gradient is visible on left side and since the gradient repeats in X-axis (and its size is only 100%), the 1px border on the right side is produced by the second tile of the gradient.

A few advantages of this approach are:

  • It doesn't need any extra real or pseudo-elements. Since input elements are self-closing and so cannot have pseudo-elements, this implies that no extra wrapper elements are required.
  • The border produced is responsive and can adapt itself even if the input element's dimensions change.

One drawback is that linear-gradient background images are supported only from IE10+.

input[type="text"] {
  padding: 2px;
  background-image: linear-gradient(to right, black 2px, transparent 2px);
  background-repeat: repeat-x;
  background-size: 100% 50%;
  background-position: -1px bottom;
  border: none;
  border-bottom: 1px solid black;
  color: #999;
  text-align: center;
}
input[type="text"].padding {
  padding: 4px 10px;
}
.narrow {
  width: 100px;
}
.wide {
  width: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<input type="text" placeholder="Name" />
<input type="text" placeholder="Address" class="wide" />
<input type="text" placeholder="City" class="narrow" />
<input type="text" placeholder="Email" class="padding" />
Harry
  • 87,580
  • 25
  • 202
  • 214
2

You can use pseudo elements :

input {
  position: relative;
  width: 200px;
  height: 18px;
  border: none;
  outline: none;
}
::-webkit-input-placeholder {
  text-align: center;
  text-transform: uppercase;
}
:-moz-placeholder {
  /* Firefox 18- */
  text-align: center;
  text-transform: uppercase;
}
::-moz-placeholder {
  /* Firefox 19+ */
  text-align: center;
  text-transform: uppercase;
}
:-ms-input-placeholder {
  text-align: center;
  text-transform: uppercase;
}
div {
  position: relative;
}
div::before {
  content: '';
  display: block;
  position: absolute;
  left: -1px;
  bottom: -1px;
  width: 204px;
  height: 9px;
  background-color: red;
}
<div>
 <input type="text" placeholder="email" />
</div>
Mehdi Brillaud
  • 1,846
  • 2
  • 13
  • 22