vikmalhotra
vikmalhotra

Reputation: 10071

Expanding input box using only css

I am trying to create an search input box that expands to left when focussed, just like Google's mobile website. I am trying to do this using css only.

Search box when not focussed in Safari (mac/iOS). white-space at left is for company logo. Notice that there is no white space between input text box and search button. Input box has position:absolute, left:120px, right:80px.

Search box when not focussed on Safari

Search box when focussed. I change the left of input box to 0 on input:focus.

Search box upon focussing

Search box when not focussed on Firefox. Conflicting absolute position values left:120px, right:80px result in whitespace between input text box and button on Chrome/Firefox.

Search box when not focussed on Firefox

What can I do create such a left expanding input box using css only and without specifying constant value for width.

Here is a working sample on Codepen.

Here is the code...

header {
  padding: 0;
}
input[type='text'] {
  left: 120px;
  position: absolute;
  right: 77px;
  top: 0;
  transition-duration: 100ms;
}
input[type='text']:focus {
  left: 0;
  transition-duration: 300ms;
}
input[type='submit'] {
  background: #1352ec;
  color: #fff;
  position: absolute;
  right: 0;
  top: 0;
  width: 80px;
}
<header>
    <form method="get" action="/search">
        <input class="clearable" type="text" value="ipad"/>
        <input type="submit" value="Search"/>
    </form>
</header>

Upvotes: 5

Views: 4782

Answers (3)

Stickers
Stickers

Reputation: 78676

I suggest to use CSS table, see the following demo. Note, I added a <span> around each <input>, that is for set up the table-cell.

The benefit of using table-cell is - we can set one cell to 100% width (for input box), and the other cell will get a minimal width to fit the content inside automatically (for the button).

form {
    display: table;
    width: 100%;
}
span {
    display: table-cell;
    text-align: right;
}
span:first-child {
    width: 100%;
}
input[type='text'] {
    box-sizing: border-box;
    -webkit-transition: width 1s;
    -moz-transition: width 1s;
    transition: width 1s;
    width: 50%;
    height: 30px;
}
input[type='text']:focus {
    width: 100%;
}
input[type='submit'] {
    background: #1352ec;
    background: -webkit-linear-gradient(top, #4685f9 0%, #1659e1 100%);
    background: -moz-linear-gradient(top, #4685f9 0%, #1659e1 100%);
    background: linear-gradient(top, #4685f9 0%, #1659e1 100%);
    color: #fff;
    border-radius: 0;
    border: 0;
    width: 80px;
    height: 30px;
}
<header>
    <form method="get" action="/search">
        <span><input class="clearable" type="text" value="ipad" name="q" autocomplete="off" /></span>
        <span><input type="submit" value="Search" /></span>
    </form>
</header>

Fiddle demo: http://jsfiddle.net/6mn6be2j/

EDIT: updated demo with logo included, CSS calc() involved.

body {
    padding: 0;
    margin: 0;
}
form {
    display: table;
    width: 100%;
}
h1 {
    position: absolute;
    top: 0;
    left: 0;
    margin: 0;
}
span {
    display: table-cell;
    text-align: right;
}
span:first-child {
    width: 100%;
}
input[type='text'] {
    box-sizing: border-box;
    -webkit-transition: width 1s;
    -moz-transition: width 1s;
    transition: width 1s;
    width: calc(100% - 120px);
    height: 30px;
    position: relative;
    z-index: 1;
}
input[type='text']:focus {
    width: 100%;
}
input[type='submit'] {
    background: #1352ec;
    background: -webkit-linear-gradient(top, #4685f9 0%, #1659e1 100%);
    background: -moz-linear-gradient(top, #4685f9 0%, #1659e1 100%);
    background: linear-gradient(top, #4685f9 0%, #1659e1 100%);
    color: #fff;
    border-radius: 0;
    border: 0;
    width: 80px;
    height: 30px;
}
<header>
    <h1><img src="http://placehold.it/120x30"/></h1>
    <form method="get" action="/search">
        <span>
            <input class="clearable" type="text" value="ipad" name="q" autocomplete="off" />
        </span>
        <span>
            <input type="submit" value="Search" />
        </span>
    </form>
</header>

Fiddle demo: http://jsfiddle.net/ergdc0r1/

Upvotes: 2

Kawinesh S K
Kawinesh S K

Reputation: 3220

CSS

   header {
  height: 30px;
  line-height: 30px;
  padding: 0;
}
input[type='text'] {
  border-radius: 0;
  height: 24px;
  line-height: 24px;
  outline: none;
  position: absolute;
  right: 80px;
  top: 0;
  -webkit-transition: width 10s ease;  
    -moz-transition: width 10s ease;  
    -o-transition: width 10s ease;  
    -ms-transition: width 10s ease;  
    transition: width 10s ease;  
  width:200px;
}
input[type='text']:focus {
  width:1000px;

}
input[type='submit'] {
  background: #1352ec;
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #4685f9), color-stop(100%, #1659e1));
  background: -webkit-linear-gradient(top, #4685f9 0%, #1659e1 100%);
  background: -moz-linear-gradient(top, #4685f9 0%, #1659e1 100%);
  background: -o-linear-gradient(top, #4685f9 0%, #1659e1 100%);
  border: 0;
  border-radius: 0;
  color: #fff;
  height: 30px;
  line-height: 30px;
  position: absolute;
  right: 0;
  top: 0;
  width: 80px;
}

DEMO

I hope this is what you wanted.

The things you done wrong are

  1. Left property will only help you to move the box and it won't expand the box
  2. left and right both the properties were used on your text box so it created a space between your search button and text box either one should be used be used to place it in correct position and in your case right property suits better.
  3. to increase the size of the of the text box use width property

Upvotes: 1

JoshWillik
JoshWillik

Reputation: 2645

Setting an input's width through right and left seems to be a bit problematic in most browsers.

To make this work, we need to use a couple of horrible hacks.

The first hack is to wrap the input in a .wrapper div. The input's width is then made 100%, and the wrapper is given the absolute positioning and the left and right values. This will make the input's initial size correct according to your question.

The second hack is for when we :focus the input. CSS doesn't (yet) allow us to style the wrapper based on whether or not the child is focused. To get around this, we can target the child input and make it intentionally overflow the wrapper. The calc here lets us specify an exact amount to overflow by. If that doesn't work on your browser, using 110% here should be fine too.

.wrapper input:hover {
  width: calc( 100% + 30px );
}

Demo

.wrapper {
  position: absolute;
  right: 100px;
  left: 10px;
}
.wrapper input {
  background: green;
  width: 100%;
  transition: all 1000ms;
}
.wrapper input:focus {
  width: calc( 100% + 50px );
}
<div class="wrapper">
  <input>
</div>

Upvotes: 2

Related Questions