Getting the search experience right is never an easy task. The starting point is always the search form, which, in most cases, consists only of an input field plus a submit button. The search results page can be tricky to design, in particular if you have different content categories.
For big websites and online stores, what is crucial though is to try to anticipate a user’s move. We have to take into account that often our users are not clear about where to find specific information on our website. In those cases they tend to turn to the search form. Providing filtering options and quick links upfront is a way to narrow the search experience to what the user is really interested in, as well as a way to build simpler, more focused search result pages.
Here is a quick animation that shows our advanced search form in action:
Creating the structure
The HTML structure is composed by three main elements: a <header>
element, wrapping the main navigation, a div.cd-main-search
for the search form and a main.cd-main-content
for the page main content.
<header class="cd-main-header animate-search">
<div class="cd-logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div>
<nav class="cd-main-nav-wrapper">
<a href="#search" class="cd-search-trigger cd-text-replace">Search</a>
<ul class="cd-main-nav">
<li><a href="#0">Products</a></li>
<!-- additional navigation items -->
</ul>
</nav>
<a href="#0" class="cd-nav-trigger cd-text-replace">Menu<span></span></a>
</header>
<main class="cd-main-content">
<!-- your content here -->
</main>
<div id="search" class="cd-main-search">
<form>
<input type="search" placeholder="Search...">
<div class="cd-select">
<span>in</span>
<select name="select-category">
<option value="all-categories">all Categories</option>
<!-- additional options here -->
</select>
<span class="selected-value">all Categories</span>
</div>
</form>
<div class="cd-search-suggestions">
<div class="news">
<h3>News</h3>
<ul>
<li>
<a class="image-wrapper" href="#0"><img src="img/placeholder.png" alt="News image"></a>
<h4><a class="cd-nowrap" href="#0">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</a></h4>
<time datetime="2016-01-12">Feb 03, 2016</time>
</li>
<!-- additional news here -->
</ul>
</div> <!-- .news -->
<div class="quick-links">
<h3>Quick Links</h3>
<ul>
<li><a href="#0">Find a store</a></li>
<!-- additional quick links here -->
</ul>
</div>
</div> <!-- .cd-search-suggestions -->
<a href="#0" class="close cd-text-replace">Close Form</a>
</div> <!-- .cd-main-search -->
Adding style
On small devices (viewport width smaller than 1024px), the main navigation and the search form are on the right side, hidden by default; when a user clicks the menu icon, the <main>
and <header>
elements translate to the left (nav-is-visible
class is applied) to reveal the navigation.
.cd-main-header, .cd-main-content {
position: relative;
transition: transform 0.3s;
}
.cd-main-header.nav-is-visible, .cd-main-content.nav-is-visible {
transform: translateX(-260px);
}
On bigger devices, the search form is on top of the main navigation, hidden by default. When a user clicks the .cd-search-trigger
element, the .is-visible
class is used to reveal the form.
@media only screen and (min-width: 1024px) {
.cd-main-search {
position: absolute;
z-index: 2;
top: 0;
left: 0;
height: 100%;
width: 100%;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s, visibility 0.3s;
}
.cd-main-search.is-visible {
/* search form open */
opacity: 1;
visibility: visible;
}
}
To trigger the search form animation, we use the .animate-search
class added to the <header>
element. This class triggers two different CSS3 Animations: cd-slide-in
(for the search form) and cd-3d-rotation
(for the suggestions dropdown).
@media only screen and (min-width: 1024px) {
.animate-search .cd-main-search.is-visible {
/* trigger search form animation if <header> has the .animate-search class */
animation: cd-slide-in 0.3s;
}
.animate-search .is-visible .cd-search-suggestions {
/* trigger the dropdown animation if <header> has the .animate-search class */
transform-origin: center top;
animation: cd-3d-rotation 0.5s 0.3s;
animation-fill-mode: backwards;
}
}
@keyframes cd-slide-in {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
@keyframes cd-3d-rotation {
0% {
transform: perspective(1000px) rotateX(-90deg);
}
100% {
transform: perspective(1000px) translateY(0);
}
}
If you prefer a basic fade-in effect (rather than animating the search form), you can remove the .animate-search
class from the <header>
element.
About the category selection: to make sure the div.cd-select
width changes according to the option the user chooses, the <select>
element is in absolute position (so it doesn't take space), while a span.selected-value
is used to show the option selected (its text is changed when the user selects a new option using jQuery).
@media only screen and (min-width: 1024px) {
.cd-main-search .cd-select {
position: absolute;
right: 0;
overflow: hidden;
}
.cd-main-search select {
/* the <select> element is not visible - it is covered by the .selected-value element */
position: absolute;
right: 0;
opacity: 0;
color: transparent;
}
.cd-main-search .selected-value {
color: #ffffff;
pointer-events: none;
}
.cd-main-search select, .cd-main-search .selected-value {
padding: 0.5em 1.7em 0.5em .3em;
font-size: 1.4rem;
border-radius: 3px;
}
}
Events handling
In the starting HTML structure, the navigation is inside the <header>
. On small devices, we wanted the navigation to be on the side, hidden by default, and it was easier for us to have it outside the <header>
. So we use jQuery to do that.
We do the same for the div.cd-main-search
: by default, it's outside the main navigation, while on small devices we move it inside the nav.cd-main-nav-wrapper
element.
var navigationWrapper = $('.cd-main-nav-wrapper'),
navigation = navigationWrapper.children('.cd-main-nav'),
searchForm = $('.cd-main-search'),
navigationTrigger = $('.cd-nav-trigger'),
mainHeader = $('.cd-main-header');
function moveNavigation(){
var screenSize = checkWindowWidth(); //returns 'mobile' or 'desktop'
if ( screenSize == 'desktop' && (navigationTrigger.siblings('.cd-main-search').length == 0) ) {
//desktop screen - insert navigation and search form inside <header>
searchForm.detach().insertBefore(navigationTrigger);
navigationWrapper.detach().insertBefore(searchForm).find('.cd-serch-wrapper').remove();
} else if( screenSize == 'mobile' && !(mainHeader.children('.cd-main-nav-wrapper').length == 0)) {
//mobile screen - move navigation and search form after .cd-main-content element
navigationWrapper.detach().insertAfter('.cd-main-content');
var newListItem = $('<li class="cd-serch-wrapper"></li>');
searchForm.detach().appendTo(newListItem);
newListItem.appendTo(navigation);
}
}
Besides, we used jQuery to detect click events and add/remove classes accordingly and to change the span.selected-value
text when user selects a different option from the <select>
dropdown.