Tutorials Web Development

Custom CSS3 & jQuery Toggle Search Form: Tutorial

4.5/5 (2)

Website search is one of the most commonly-expected features in modern design. Although it can be difficult to build usable search functionality, the interface is often a lot simpler and more compact than you'd expect. Search fields require a single input and a submit button which can be styled, positioned, and formatted in any way you like.

For this tutorial I'll explain how you can build a toggle search form with CSS3 and jQuery. I've provided two distinct methods for the toggle effect: a hover and click event. All of the event handling is managed through jQuery while CSS3 is used to display the hidden search field. You can see a live demo of my final project code below.

Live Demo - Download Source Code

Getting Started

Make a new HTML file with an empty header section. The search field events require a copy of the jQuery library. I'm also including the Font Awesome webfont library to create a scalable magnifying glass icon.

1
2
3
4
5
6
7
8
9
10
11
12
13
<!doctype html>
<html lang="en-US">
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Type" content="text/html">
  <title>Toggleable Search Form - Template Monster Demo</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="shortcut icon" href="http://static.tmimgcdn.com/img/favicon.ico">
  <link rel="icon" href="http://static.tmimgcdn.com/img/favicon.ico">
  <link rel="stylesheet" type="text/css" media="all" href="css/styles.css">
  <link rel="stylesheet" type="text/css" media="all" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css">
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>

I've chosen to include many of the header files externally through a cloud resource CDN JS. You might alternatively choose to download the files and store them locally if that would be easier.

My demo uses a responsive technique to hide the navigation links beyond a certain point. The text is coded with pixel values so it will remain constant throughout various browsers. So the effect is handled within an HTML5 nav element using the ID #topbar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<nav id="topbar">
  <ul class="navigation">
    <li class="threebar"><a href="#"><i class="fa fa-bars"></i></a></li>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Stuffington</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
 
  <div class="searchlink" id="searchlink">
    <i class="fa fa-search"></i>
 
    <div class="searchform">
      <form id="search">
        <input type="text" class="s" id="s" placeholder="keywords...">
        <button type="submit" class="sbtn"><i class="fa fa-search"></i></button>
      </form>
    </div>
  </div>
</nav>

Each link in the navigation is contained in a regular unordered list. The first list item uses a class .threebar which creates space for the typical hamburger menu icon. It only appears once the browser window has been resized below a certain amount.

After the unordered list I created a div with the ID #searchlink. This contains the magnifying glass icon as well as the dropdown toggle div contents. Both the nav and search elements float opposing each other on either side of the page. This will leave plenty of room as the browser window grows smaller to keep the effect usable.

CSS Design Style

Aside from my typical CSS resets I've written a lengthy set of rules to style the page. First is the navigation setup with all the primary links and the .threebar class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#topbar {
  display: block;
  height: 70px;
  background: #424242;
}
 
.navigation {
  display: block;
  float: left;
}
 
.navigation li { 
  display: block;
  float: left;
}
 
.navigation li a {
  display: block;
  float: left;
  font-size: 1.4em;
  line-height: 70px;
  padding: 0 25px;
  text-decoration: none;
  font-weight: bold;
  color: #c1c1c1;
}
.navigation li a:hover {
  color: #dedede;
}
 
.navigation li.threebar {
  display: none;
  font-size: 1.8em;
}
.navigation li.threebar a { position: relative; padding: 0 30px; }
.navigation li.threebar a:hover {
  padding: 0 30px;
  color: #bababa;
  background: #3a3a3a;
}
 
.searchlink {
  display: block;
  float: right;
  position: relative;
  padding: 0 40px;
  right: 0;
  font-size: 2.4em;
  cursor: pointer;
  height: 70px;
  line-height: 65px;
}
.searchlink:hover, .searchlink.open {
  color: #bababa;
  background: #3a3a3a;
}
 
.searchlink.open > .searchform {
  display: block;
}

Each nav link is floated in a single line on the page. The very first .threebar link is hidden by default using display:none. It will only appear through a media query which becomes active on smaller screens.

You should also notice a set of styles targeting the .searchlink element. This is the outer div which contains the magnifying glass as well as the toggle search box. The form itself is another element which is hidden by default and will only appear once the container gains the .open class through JavaScript.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/** search field **/
.searchform {
  display: none;
  position: absolute;
  width: 300px;
  height: 50px;
  line-height: 40px;
  top: 70px;
  right: 0;
  padding: 0 15px;
  cursor: default;
  background: #3a3a3a;
}
 
.searchlink.open .searchform {
  display: block;
}
 
#search {
  display: block;
  position: relative;
}
 
#s {
  width: 270px;
  background: #272727;
  padding: 8px 11px;
  border: 0;
  color: #eee;
  -webkit-border-radius: 15px;
  -moz-border-radius: 15px;
  border-radius: 15px;
}
 
.sbtn {
  display: block;
  position: absolute;
  right: 5px;
  top: 13px;
  background: none;
  border: none;
  color: #bcbcbc;
  font-size: 0.6em;
  cursor: pointer;
}

Inside the search form there aren't too many surprises. One area worth explaining is the search button which also uses the Font Awesome magnifying glass icon. Since it needs to be positioned in relation to the form field I've added relative positioning onto .searchform.

The button itself is positioned absolutely with updated settings for the border and background.

1
2
3
4
5
6
/** media queries **/
@media screen and (max-width: 515px) {
  .navigation li { display: none; }
  .navigation li.threebar { display: block; }
 
}

Lastly we have this brief set of responsive codes that become active once the browser is resized to 515px or smaller. At this smaller size the search link bumps into the other nav links and the layout starts to break down.

So first I'm hiding every single list item with the display: none property. Then my list item with the .threebar class is displayed in place of these links. Note that this nav menu doesn't actually work, it's just a placeholder to demonstrate how you could build an interface with this same effect.

jQuery Event Handlers

Turn back into the HTML file and open a new block of JavaScript at the bottom of the page. In my example I've written two different event handlers - one for the default hover effect and another for the click event.

There is no right or wrong choice just differences of opinion, so play around and see what you like the most.

1
2
3
4
5
6
7
8
9
$(function() {
  var $searchlink = $('#searchlink');
 
  // hover effect
  $searchlink.on('mouseover', function(){
    $(this).addClass('open');
  }).on('mouseout', function(){
    $(this).removeClass('open');
  });

This first line creates a selector variable which can be used as a cached element. $searchlink targets the search container and will be used in either of the jQuery calls. My initial event handler uses the .on() method for mouseover and mouseout events.

Inside each respective function I'm adding or removing the .open class onto the primary search container. Remember, this class regulates when to hide or display the search field. The entire effect is managed through this lone CSS class.

Moving further down in my code is a somewhat larger block for the click event. I have it commented out because we can't use both click and hover effects on the same page. But if you want to try it out simply hide the mouseover code before removing the comment tag.

1
2
3
4
5
6
7
8
9
10
11
  $searchlink.on('click', function(e){
    var target = e ? e.target : window.event.srcElement;
 
    if($(target).attr('id') == 'searchlink') {
      if($(this).hasClass('open')) {
        $(this).removeClass('open');
      } else {
        $(this).addClass('open');
      }
    }
  });
[related_posts]

This method targets the same $searchlink element but instead listens for any click event. Once the function runs it'll create a new variable named target. This checks the event itself to see which element was clicked. It helps us recognize when to close the search form(and when not to close it).

This whole click event is predicated around checking the currently-clicked element. If it has an ID of #searchlink then we know the user has clicked onto the search link div. Otherwise they've clicked elsewhere, such as the search input field or the search button.

You may not need to use this event syntax again but it's worth keeping this snippet handy just in case. JavaScript is a versatile language once you understand how it all operates. Just remember the hover & click events shouldn't be running at the same time, so be sure to either comment out or completely remove one of them.

Closing

There's a lot of power to glean from everyday rudimentary jQuery and CSS techniques. I hope this search bar tutorial can be of use to frontend developers and designers on any type of project. Feel free to download a copy of my source code and let us know your thoughts in the post discussion area.