20
\$\begingroup\$

I've got a text input element which is decorated with an underline. The underline goes up half the height of the input on either side of it and turns blue when the input is focused. It's similar to how inputs look on Android devices.

Here's a JSFiddle and some accompanying code.

<span class="input-underline-wrapper">
    <input placeholder="Search..." type="text" value="">
    <div class="underline"></div>   
</span>

//  Start:normalize
*, *:before, *:after {
    box-sizing: border-box;
}

input:focus {
    outline: none 
}
//  End:normalize

.input-underline-wrapper {
    display: inline-block;
    width: 100%;
}

input {
    width: calc(100% - 2px);
    margin-left: 1px;
    padding-bottom: 2px;
}

input[type=text] {
    border: 0;
    cursor: text;
}

.underline {
    background-color: #ebebeb;
    transition: color 0.3s, background 0.3s, border 0.3s, text-shadow 0.3s;
    z-index: 0;
    height: 5px;
    margin-top: -4px;
    width: 100%;
}

input:focus ~ .underline {
    background-color: #4EA6EA;
}

This all works well and good, but it feels a bit verbose. I'm wondering if I've missed something simple here. Is it possible to achieve the same effect using a white box-shadow which covers the upper-half of the input and omit using a wrapper and a second, underlining div? I only need to support the latest version of Google Chrome.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ What you can and cannot do after receiving answers. I've rolled back Rev 3 → 2. \$\endgroup\$ Sep 8, 2014 at 20:54
  • \$\begingroup\$ Uhh, sure, but the answer was not relevant to the question being asked and I didn't want someone in the future to utilize an incorrect solution. \$\endgroup\$ Sep 8, 2014 at 21:06
  • 2
    \$\begingroup\$ Nearly every question on this site contains imperfect code. Only a fool would take code from a question without reading the answers. Editing code in questions invalidates answers. (You wouldn't edit a Stack Overflow question to say, "Thanks, never mind, fixed it!", would you?) \$\endgroup\$ Sep 8, 2014 at 21:09
  • 4
    \$\begingroup\$ On Code Review, all aspects of the code are considered fair game for review. \$\endgroup\$ Sep 8, 2014 at 22:00

3 Answers 3

23
+100
\$\begingroup\$

Using box-shadows on the input can let you have the same underlining effect without any wrapper or unsemantic markup + strip your CSS a lot :

input[type=text] {
  height:17px;
  border: 0;
  width: calc(100% - 2px);
  margin-left:1px;
  box-shadow: -8px 10px 0px -7px #ebebeb, 8px 10px 0px -7px #ebebeb;
  -webkit-transition: box-shadow 0.3s;
  transition: box-shadow 0.3s;
}
input[type=text]:focus {
  outline: none;
  box-shadow: -8px 10px 0px -7px #4EA6EA, 8px 10px 0px -7px #4EA6EA;
}
<input placeholder="Search..." type="text" value=""/>

For browser support :

\$\endgroup\$
4
  • 3
    \$\begingroup\$ you should check out the cool new Stack Snippets, no need for the JSFiddle on these simple answers, it's the new icon right next to the picture insertion icon when you edit a post. \$\endgroup\$
    – Malachi
    Sep 11, 2014 at 21:21
  • 1
    \$\begingroup\$ I like this answer! I am going to be implementing this into some websites for sure! \$\endgroup\$
    – Malachi
    Sep 11, 2014 at 21:22
  • 2
    \$\begingroup\$ @Malachi thx and you are right, I'll give the new snippet feature a go! \$\endgroup\$
    – web-tiki
    Sep 11, 2014 at 21:23
  • 2
    \$\begingroup\$ I like that you listed the browser support as well! very good answer \$\endgroup\$
    – Malachi
    Sep 11, 2014 at 21:38
5
\$\begingroup\$

Your HTML markup is invalid: a <span> should never contain a <div>. However, you may swap them, such that the <div> contains a <span>.

\$\endgroup\$
4
  • \$\begingroup\$ I realize that. It's made indifferent by the fact that it's display: inline-block, but understood. I'll make the change. \$\endgroup\$ Sep 8, 2014 at 20:52
  • 1
    \$\begingroup\$ Setting a span to display: block does not change the rules regarding what elements it is allowed to contain. Improper nesting can cause undesirable side effects when browsers attempt to compensate by altering the nesting in an attempt to make it valid. \$\endgroup\$
    – cimmanon
    Sep 9, 2014 at 15:18
  • \$\begingroup\$ better source for why span can't contain a div: whatwg.org/specs/web-apps/current-work/multipage/… hattip to @cimmanon \$\endgroup\$
    – albert
    Sep 9, 2014 at 23:14
  • \$\begingroup\$ you should change the span to label, regardless if you have no text there. its so much better for ux \$\endgroup\$
    – albert
    Sep 9, 2014 at 23:15
3
\$\begingroup\$

You talk about omitting the wrapper, you really don't need to do much differently here,

I removed the Wrapper and the CSS that went along with it, and nothing changed in the JSFiddle

My Fiddle

It's not good to have a whole bunch of HTML that you don't need, it makes things weird.

The same goes for CSS, the more CSS that you have the more CSS gets interpreted by the browser and the better chance you have of CSS overwriting itself.


input:focus {
    outline: none 
}

input {
    width: calc(100% - 2px);
    margin-left: 1px;
    padding-bottom: 2px;
}

input[type=text] {
    border: 0;
    cursor: text;
}

.underline {
    background-color: #ebebeb;
    transition: color 0.3s, background 0.3s, border 0.3s, text-shadow 0.3s;
    z-index: 0;
    height: 5px;
    margin-top: -4px;
    width: 100%;
}

input:focus ~ .underline {
    background-color: #4EA6EA;
}
<input placeholder="Search..." type="text" value="" />
<div class="underline"></div>   

Let's check it out in the fancy Stack Snippets tool and see how it stacks up to JSFiddle

input:focus {
    outline: none 
}

input {
    width: calc(100% - 2px);
    margin-left: 1px;
    padding-bottom: 2px;
}

input[type=text] {
    border: 0;
    cursor: text;
}

.underline {
    background-color: #ebebeb;
    transition: color 0.3s, background 0.3s, border 0.3s, text-shadow 0.3s;
    z-index: 0;
    height: 5px;
    margin-top: -4px;
    width: 100%;
}

input:focus ~ .underline {
    background-color: #4EA6EA;
}
    <input placeholder="Search..." type="text" value="" />
    <div class="underline"></div>   

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.