7

I would like to know how to make the border of an element not span the full length of the element. I've seen some suggestions to use line-height though that doesn't seem to work for me (at least not with the <ul> tag which is what I'm using).

A popular example of someone doing this would be the search at http://android.com which has this sort of effect though I can't find anything relating to it in the css.

Ex:

https://i.stack.imgur.com/cTn5i.png

IgnianSoft
  • 129
  • 1
  • 1
  • 7
  • 1
    What line are you referring to in your image? And what have you tried? Show some code. Seems to be a `div` with `height:5px; width:1px; background:#ccc;` – putvande Sep 09 '13 at 19:48
  • line height would dictate the height, not the length. What exactly are you trying to achieve? – Kevin Lynch Sep 09 '13 at 19:51
  • The one on the left of the search input. The bottom one is a border-bottom style element but I can't find anything that produces that border on the left, hence why there's no code. – IgnianSoft Sep 09 '13 at 19:51
  • I would use a structure and let the bottom row with a small height, have boarder bottom and border left for the cell/cells.
    – IceCode Sep 09 '13 at 19:58
  • Here's is one of many examples using 2 divs http://stackoverflow.com/questions/8804417/css-border-where-only-half-of-a-border-is-visible – Kevin Lynch Sep 09 '13 at 20:01
  • @Vector I was looking for a way without having to resort to using a second div. – IgnianSoft Sep 09 '13 at 20:05
  • @IgnianSoft If your example is not relevant, since they're basically using two elements to achieve this effect, then you should remove it from the question to avoid confusion. – Boaz Sep 09 '13 at 20:09
  • Android are using two elements to achieve this effect, if they can't do it with one element, i doubt we could. – Kevin Lynch Sep 09 '13 at 20:11
  • According to the CSS specification, borders enclose the entire element to which they are applied. Therefore, the only way to get this type of an effect is to either use a combination of a wrapper element with absolute positioning. Alternatively, you could apply a carefully constructed background image of the border shape. – Marc Audet Sep 09 '13 at 20:15

5 Answers5

12

Here's another option for the mix. box-shadow is fast becoming one of my favourite new CSS features...

No extra markup, nothing but CSS (and no pseudo-elements)...

DEMO: http://jsfiddle.net/npsMx/2/

HTML

<input type="text" class="search" />

CSS

.search {
    border: 0px solid blue;
    border-bottom-width: 1px;
    -webkit-box-shadow: -5px 4px 0px -4px blue;
       -moz-box-shadow: -5px 4px 0px -4px blue;
            box-shadow: -5px 4px 0px -4px blue;
}

We force the box-shadow on to just the left hand side. Setting it to -5px sets the width on the left to just that... The -4px later effectively shuffles is back across the way leaving just one pixel visible (i.e. equal to our border-bottom-width.

Hard to explain but easy to see if you just play with the values!

Community
  • 1
  • 1
gvee
  • 16,732
  • 35
  • 50
  • 1
    What an idea! Nicely done. I love seeing box shadows used and abused :P [I do it often](http://codepen.io/brbcoding/2). – brbcoding Sep 09 '13 at 20:27
  • 1
    Updated answer for completeness (`-webkit` and `-moz` variants added). – gvee Sep 09 '13 at 21:56
  • This has the notable disadvantage that you can't adjust the height of the left tick, it will always be the height of the input element – Robin Aug 26 '15 at 15:15
  • I had a different situation of partial border and I used this technique successfully. – Pablo Fernandez Jan 24 '19 at 12:18
  • Great tool for helping creating the box shadow element visually https://html-css-js.com/css/generator/box-shadow/ – NicolasZ Feb 25 '20 at 15:36
8

How about something like this... It's not completely cross browser due to pseudo-elements and contenteditable, but it's a different solution -- and it works.

HTML

<!--// can't use pseudo elements on input, so let's make a div contenteditable //-->
<div class="foo" contenteditable></div>

CSS

.foo {
    position: relative;
    width: 150px;    
}

.foo:after {
    position: absolute;
    top: 1em;
    left: 0;
    content: "";
    width: 150px;
    height: 0;
    border-bottom: 1px solid #bada55;
}
.foo:before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.5em;
    height: 0.5em;
    width: 1px;
    background: #bada55;
}

.foo:focus {
    outline: solid transparent;
}

JSFiddle

brbcoding
  • 13,378
  • 2
  • 37
  • 51
  • Why are you using a `:before` and an `:after`? Just use one short element with `border-bottom` and `border-left`. – user1618143 Sep 09 '13 at 20:18
  • @user1618143 The OP wants a CSS-only solution. – Boaz Sep 09 '13 at 20:20
  • This worked perfectly though I don't need all the pseudo elements :) – IgnianSoft Sep 09 '13 at 20:21
  • @Boaz I stated that my question was relating to achieving this with
      elements. Sorry for the confusion with my example being an element.
    – IgnianSoft Sep 09 '13 at 20:22
  • Yeah, I suppose it could have been simpler without the pseudo elements... For some reason it just looked *off* to me without them, but if it works for you... I'm glad :) – brbcoding Sep 09 '13 at 20:26
  • Uh, since when are `border-bottom` and `border-left` not pure CSS? I mean, you'd still need a `:before` or an `:after`, but not both. – user1618143 Sep 09 '13 at 20:33
3

Take a look at the markup in your example:

<div class="search" id="search-container">
    <div class="search-inner">
        <div id="search-btn"></div>
        <div class="left"></div>
        <form action="/search/" id="search" name="search">
            <input id="q" name="q" placeholder="Search" speech="" type="text" x-webkit-speech="">
        </form>
   </div>
</div>

What you're looking for is <div class="left"> .. look at the CSS:

.search:hover .bottom, .search:hover .left, .search:hover .right {
    background-color: #33b5e5;
}

This is what's creating the little blue line on the left side..

I take back what I said about pseudo elements because they will not work with inputs... You should use a wrapper do achieve this correctly..

Yotam Omer
  • 15,310
  • 11
  • 62
  • 65
  • I tried the :before way and it didn't seem to work :/. It seems I will have to go with adding another element to the left of of it. – IgnianSoft Sep 09 '13 at 20:04
  • Any reason you happened to remove the :before way? – IgnianSoft Sep 09 '13 at 20:04
  • I'm not using a element, my question would be with
      elements as stated^^. The pseudo elements still don't seem to work.
    – IgnianSoft Sep 09 '13 at 20:07
  • @IgnianSoft: Did you remember to add a `content` to the pseudo-element? That one trips me up a lot. – user1618143 Sep 09 '13 at 20:16
  • @user1618143 yeah, that was exactly the problem I had, I've decided to give the other answerer the accepted response as he kept the pseudo elements and explained his reasoning quite well. – IgnianSoft Sep 09 '13 at 20:25
2

Here is one approach using a wrapper around the input element.

Suppose that you have the following HTML:

<div class="input-wrap">
    <input type="text" value="Search...">
</div>

Apply the following CSS:

.input-wrap {
    display: inline-block;
    position: relative;
    border-bottom: 1px solid red;
    border-left: 1px solid red;
    height: 10px;
    width: 100px;
}
.input-wrap input {
    position: absolute;
    bottom: 0;
    left: 0;
    width: inherit;
    border: none;
    background-color: beige;
}

Fiddle: http://jsfiddle.net/audetwebdesign/rLCHa/

In this construction, the outer .input-wrap element controls the width of the input field and the bottom border, and the height of the left border (10px in this example).

The input field is positioned absolutely and pinned to the bottom of the parent container, and inherits the width. The input field's height is the default value, but you can control it independently from the height set in the .input-wrap element.

Marc Audet
  • 46,011
  • 11
  • 63
  • 83
0

Another solution is to absolutely position a div as the left border.

    .box {width:205px; position:relative;}
    .line {width:1px; height:10px; background:#ff0000; position:absolute; left:0; bottom:2px;}
    input {width:180px; background:#fff; color:#000; border:0; border-bottom:1px solid #ff0000; padding:5px 10px; position:absolute; left:1px; bottom:0;}

html

<div class="box">
<div class="line"></div>
<input type="text" value="Search" />
</div>

jsfiddle example

hupsohl
  • 46
  • 4
  • Unfortunately it looks like you would need to adjust the bottom attribute for the .line class to get it to work cross browser. IE works fine with bottom:0 but Chrome wants bottom:2px – hupsohl Sep 09 '13 at 20:18