How to Code an Expanding HTML5/CSS3 Search Input Field

A common user interface style for Apple and WordPress has been the expanding search field. Whenever a user clicks to focus, the field will expand wider, then contracts when the user de-focuses. This technique has become popular because it saves room on your page when the search isn’t being used. But it also highlights the search field when it is in use, which catches the user’s attention and lets them know the website is responding.

In this tutorial I want to demonstrate two different methods for building an expanding search field. The first is using basic CSS3 transitions which are only supported in newer web browsers. This works great for simple designs, but there is no way to check if the user has entered data strictly via CSS. In the second field we will use JavaScript to expand, and then only shrink back if the user hasn’t entered any text. It is a small yet fascinating piece of UI which can blend nicely into any website project.

2 Million+ Digital Assets, With Unlimited Downloads

Get unlimited downloads of 2 million+ design resources, themes, templates, photos, graphics and more. Envato Elements starts at $16 per month, and is the best creative subscription we've ever seen.

Explore Design Resources

Live DemoDownload Source Code

Building a Simple Form

I do not want to have the demo forms actually submit anything, so I am using JavaScript for stopping the submit event. But the plain HTML of the document is still normal and fairly straightforward. Feel free to download a copy of my demo if you want to work on a local copy of the tutorial.

<!doctype html>
<html lang="en-US">
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <title>Expanding Search Input Field</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="shortcut icon" href="https://designshack.net/favicon.ico">
  <link rel="icon" href="https://designshack.net/favicon.ico">
  <link rel="stylesheet" type="text/css" media="all" href="styles.css">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script type="text/javascript" src="jsinput.js"></script>
</head>

This snippet contains all the header codes we need in the HTML page. I have included a copy of the jQuery library for quicker scripting. My custom-written JavaScript is saved into an external file named jsinput.js. It doesn’t contain anything too complex, but it will be worth understanding how we complete the different effects via CSS and JS. Here are the two form input areas with their exact HTML codes:

    <form id="searchform" name="searchform" method="get" action="index.html">
      <div class="fieldcontainer">
        <input type="text" name="s" id="s" class="searchfield" placeholder="Keywords..." tabindex="1">
        <input type="submit" name="searchbtn" id="searchbtn" value=""> 
      </div><!-- @end .fieldcontainer -->
    </form>



    <form id="searchform2" name="searchform2" method="get" action="index.html">
      <div class="fieldcontainer">
        <input type="text" name="s2" id="s2" class="searchfieldjs" placeholder="Keywords..." tabindex="2">
        <input type="submit" name="search2btn" id="search2btn" value="">
      </div>
    </form>

The search fields are named #s and #s2 respectively. I kept to a similar naming convention with the form elements and submit buttons. Reading through the CSS document should be a lot easier since we have the fields split by unique ID names. But first we can look at the CSS transitions and then move onto the dynamic JavaScript field.

Expanding with CSS Transitions

My demo CSS file contains a series of resets along with basic styles for creating the layout structure. There is nothing out of the ordinary if you are familiar with CSS. However one block I think is worth mentioning actually targets the placeholder text for various input elements. These selectors are not supported in all browsers, but we can get a majority of the newer engines with these codes:

::-webkit-input-placeholder { /* WebKit browsers */
  color: #ccc;
  font-style: italic;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
  color: #ccc;
  font-style: italic;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
  color: #ccc;
  font-style: italic;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
  color: #ccc !important;
  font-style: italic;  
}

It looks a lot nicer to blend typical input text with the rest of your design. The CSS properties for each search field mimics a similar tone. I have an outer wrapper class named .fieldcontainer which encapsulates the form at 100% width. This means the form will never expand beyond the page container, so we can use 100% as max and anything else will be relative.

/** search input **/
#searchform, #searchform2 {
  display: block;
  margin-bottom: 15px;
}

.fieldcontainer {
  display: block;
  position: relative;
  width: 90%;
  margin: 0 auto;
}

.searchfield {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  display: block;
  width: 45%;
  padding: 11px 7px;
  padding-right: 43px;
  background-color: #fff;
  font-size: 1.6em;
  color: #ccc;
  border: 1px solid #c8c8c8;
  border-bottom-color: #d2e2e7;
  -webkit-border-radius: 1px;
  -moz-border-radius: 1px;
  border-radius: 1px;
  -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1), 0 0 0 6px #f0f0f0;
  -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1), 0 0 0 6px #f0f0f0;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.1), 0 0 0 6px #f0f0f0;  
  -webkit-transition: all 0.4s linear;
  -moz-transition: all 0.4s linear;
  transition: all 0.4s linear;
}

.searchfield:focus {
  width: 100%;
  color: #666;
  -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.2), 0 0 0 6px #e0e0e0;
  -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.2), 0 0 0 6px #e0e0e0;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.2), 0 0 0 6px #e0e0e0;
}

The transition properties can be found at the very bottom of the .searchfield class. The common CSS3 property and vendor prefixes should cover a majority of web browsers. But if you need support for backwards-compatibility then using a strict JavaScript method would yield greater results. Although admittedly this code is much cleaner and easier to organize.

#searchbtn {
  position: absolute;
  right: 360px;
  top: 5px;
  height: 32px;
  width: 32px;
  border: 0;
  cursor: pointer;
  zoom: 1;
  filter: alpha(opacity=65);
  opacity: 0.65;
  background: transparent url('images/search.png') top left no-repeat;
  /* Icon credits to Brightmix http://www.iconfinder.com/icondetails/43272/128/find_loop_magnify_monotone_search_zoom_icon */
  -webkit-transition: all 0.4s linear;
  -moz-transition: all 0.4s linear;
  transition: all 0.4s linear;
}
#searchbtn:hover, #searchbtn:focus, #search2btn:hover, #search2btn:focus {
	filter: alpha(opacity=90);
	opacity: 0.9;  
}
.searchfield:focus + #searchbtn {
  right: 10px; /* adjust btn position as the field expands */
}

One last bit for the search input area will fix placement for our search icon. This needs to be positioned at the very end of the input field which also includes a bit of padding on the right side. This way the user can never enter text which writes over the search button icon. The original source of this graphic is from Icon Finder designed by Brightmix. The flat icon set is perfect for such a basic search field input.

The biggest problem with CSS-only animation is handling dynamic user selections. When a visitor enters text in the expanded field they may hit enter, or they may go to click on the magnifying glass. If they click to search this will remove focus from the input and it will shrink back to 45%, which also messes with the click event. You may choose to edit the transition properties and fix them onto the :focus state. But then there won’t be any animation when resizing back down, so the effect is even worse.

Handling Dynamic Input via jQuery

In my sample demo the second input field is the only one targeted by jQuery. At the top of jsinput.js I have created two variables which select the second input field and search button. It is possible to change these positions if you would rather target the first field. But then it may also be worth removing the CSS3 transitions and only using these as a fallback method when JS is disabled in the browser.

$(function(){
  var search2 = $('#s2');
  var icon2   = $('#search2btn');
  
  // handling the focus event on input2
  $(search2).on('focus', function(){
    $(this).animate({
      width: '100%'
    }, 400, function(){
      // callback function
    });
    $(icon2).animate({
      right: '10px'
    }, 400, function(){
      // callback function
    });
  });

I have broken up the file into two large chunks of code. This first half contains the initial variables along with the focus event handler. Whenever the user focuses on the second input field we need to expand the width out 100%. Also we need to move the search icon from its default position all the way over to the right side. The two jQuery.animate() methods should run at the exact same time, producing a very similar animation effect as with CSS3 transitions.

  // handling the blur event on input2
  $(search2).on('blur', function(){
    if(search2.val() == '') {
      $(search2).animate({
        width: '45%'
      }, 400, function(){ });
      
      $(icon2).animate({
        right: '360px'
      }, 400, function(){ });
    }
  });
  
  // handling both form submissions
  $('#searchform, #searchform2').submit(function(e) {
    e.preventDefault();
  });
});

Then this last chunk has two more events for binding. The first happens after the user blurs off the second input field. The script will test against search2.val() and determine if the user has entered any data. If the field is empty then we animate back down to 45% width, and the icon gets repositioned as well. Otherwise the user has entered some search terms and we leave it at full 100% width.

The second small block of codes will trigger once you try to submit data for either of the forms. It will automatically catch the submission and stop it from happening with event.preventDefault(). Overall it should not be a complex script, but developers who are unfamiliar with jQuery may need to research a couple functions. The codes are exceptionally small and should work in all JS-enabled web browsers.

Live DemoDownload Source Code

Conclusion

This interface doesn’t require a whole lot of planning or extra code in your design. And even if you keep the same design style for your website input fields, this technique can be done using a few CSS3 transitions along with an outer container.

It would also be possible to include this on any number of similar forms like contact fields or profile settings pages. Download a copy of my demo source code, and feel free to implement this feature into any number of projects!