In this tutorial I will like to show you how we can create a really cool animated search box with CSS3 and JavaScript.
To start off, you will need the following tools:
- CSS3 for styling and animations
- HTML for the structure
- JavaScript and jQuery as the manager of our demonstration.
You can find the demo and download link for these, here :
If we look back in the days, developers used to animate HTML elements by changing values of CSS properties with JavaScript. That was not only slow but also hard to code, or to maintain the same quality on major mobile and desktop browsers.
Thanks to CSS3, now we can animate elements much faster, much easier and the results can be really cool!
So let’s get started!
Part 1 : HTML
First of all, we have a container, div, with “search-wrapper” class. This will hold and center our search box.
The first children element of our primary container is called .input-holder. This one has a fixed width in our main container .search-wrapper. The .input-holder contains the text input and the search button.
Remember:
- The text input is positioned absolute and stretched on the full length of his “parent”
- The search button has the CSS float property with the value of right, in order to keep it on the right side of our container while animating it.
The second children element of our div is called .close ,and it acts as a container for the close icon, created using the CSS pseudo classes ::before and ::after.
Take a look at our structure:
<div class="search-wrapper">
<div class="input-holder">
<input type="text" class="search-input" placeholder="Type to search" />
<button class="search-icon" onclick="searchToggle(this, event);"><span></span></button>
</div>
<span class="close" onclick="searchToggle(this, event);"></span>
</div>
Part 2 : CSS
Note : In order to have a light code structure and easy to read article, I will not add the vendors prefixes for any CSS property. You can easily find the complete source on the DEMO page, or in the DOWNLOAD link.
Since our demonstration is about animating with CSS, I will insist on explaining the CSS animation/ transition techniques, and not on the casual CSS properties. Now, let’s take a close look at the way I centered the main wrapper, .search-wrapper, and talk about that :
.search-wrapper {
position: absolute;
transform: translate(-50%, -50%);
top:50%;
left:50%;
}
.search-wrapper.active {}
First of all, to center an element in the middle of the document, you’ll need to use position:absolute , and set the top and left side to 50%. You have the result of that in bullet 1 in the picture below.
Next, you will see that the top-left side of the element is positioned in the middle of the document, but that’s not exactly what we want. So by using CSS3 property transform:translate(x,y) , where “x” and “y” are -50%, you will be able to subtract 50% of your current element’s width and height from the current position. See bullet 2!
P.S.: before having CSS transform at our disposal, we used to calculate that offset with JavaScript, and you know how annoying that was, right, developers?
Now let’s see . input-holder :
.search-wrapper .input-holder {
height: 70px;
width:70px;
overflow: hidden;
background: rgba(255,255,255,0);
border-radius:6px;
position: relative;
transition: all 0.3s ease-in-out;
}
.search-wrapper.active .input-holder {
width:450px;
border-radius: 50px;
background: rgba(0,0,0,0.5);
transition: all .5s cubic-bezier(0.000, 0.105, 0.035, 1.570);
}
The .input-holder has 2 different transitions, one using the ease-in-out predefined timing function (that applies when you close the search box), and the second one using cubic-bezier timing function (that applies when you expand it).
.input-holder has 2 values for width, one for the closed state, and another for the expanded state. Same thing with the border-radius and background properties.
Moving forward with .input-holder, we have the text input (.search-input) and the search button (.search-icon):
.search-wrapper .input-holder .search-input {
width:100%;
height: 50px;
padding:0px 70px 0 20px;
opacity: 0;
position: absolute;
top:0px;
left:0px;
background: transparent;
box-sizing: border-box;
border:none;
outline:none;
font-family:"Open Sans", Arial, Verdana;
font-size: 16px;
font-weight: 400;
line-height: 20px;
color:#FFF;
transform: translate(0, 60px);
transition: all .3s cubic-bezier(0.000, 0.105, 0.035, 1.570);
transition-delay: 0.3s;
}
.search-wrapper.active .input-holder .search-input {
opacity: 1;
transform: translate(0, 10px);
}
.search-wrapper .input-holder .search-icon {
width:70px;
height:70px;
border:none;
border-radius:6px;
background: #FFF;
padding:0px;
outline:none;
position: relative;
z-index: 2;
float:right;
cursor: pointer;
transition: all 0.3s ease-in-out;
}
.search-wrapper.active .input-holder .search-icon {
width: 50px;
height:50px;
margin: 10px;
border-radius: 30px;
}
.search-wrapper .input-holder .search-icon span {
width:22px;
height:22px;
display: inline-block;
vertical-align: middle;
position:relative;
transform: rotate(45deg);
transition: all .4s cubic-bezier(0.650, -0.600, 0.240, 1.650);
}
.search-wrapper.active .input-holder .search-icon span {
transform: rotate(-45deg);
}
.search-wrapper .input-holder .search-icon span::before, .search-wrapper .input-holder .search-icon span::after {
position: absolute;
content:'';
}
.search-wrapper .input-holder .search-icon span::before {
width: 4px;
height: 11px;
left: 9px;
top: 18px;
border-radius: 2px;
background: #FE5F55;
}
.search-wrapper .input-holder .search-icon span::after {
width: 14px;
height: 14px;
left: 0px;
top: 0px;
border-radius: 16px;
border: 4px solid #FE5F55;
}
.search-wrapper .close {
position: absolute;
z-index: 1;
top:24px;
right:20px;
width:25px;
height:25px;
cursor: pointer;
transform: rotate(-180deg);
transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
transition-delay: 0.2s;
}
.search-wrapper.active .close {
right:-50px;
transform: rotate(45deg);
transition: all .6s cubic-bezier(0.000, 0.105, 0.035, 1.570);
transition-delay: 0.5s;
}
.search-wrapper .close::before, .search-wrapper .close::after {
position:absolute;
content:'';
background: #FE5F55;
border-radius: 2px;
}
.search-wrapper .close::before {
width: 5px;
height: 25px;
left: 10px;
top: 0px;
}
.search-wrapper .close::after {
width: 25px;
height: 5px;
left: 0px;
top: 10px;
}
As earlier mentioned in the HTML part of our tutorial, the .search-input has position:absolute, stretched at 100%. This means that it takes the value of his parent.
For the animation, we have 2 states:
- When the .input-holder closes, we apply a few CSS3 properties on .search-input :
- transform:translate (0,60px), this moves the search input on y axis (bottom) with 60 pixels
- opacity:0 (self explanatory)
- transition-delay: .3s, this allows delaying the transition with 3 milliseconds, to have a more interactive animation
- the last thing we need to do is to apply a transition that has a cubic-bezier timing function with a 3 milliseconds duration, transition:all.3s cubic-bezier (0.000,0.105,0.035,1.570
- When the .input-holder opens, we switch the opacity from 0 to 1 and transform from translate (0,60px) to translate (0,10px). As for the transition property, it’s inherited from the previous state.
The .search-icon and .close use the same methods for the transition as described earlier, with a few differences, such as using the transition property in conjunction with transform:rotate (x deg). This allows us to rotate our element around its own center.
In the HTML part of our tutorial, I’ve mentioned how some of the icons are created with CSS pseudo classes, ::before and ::after. When using before and after pseudo classes, you have the possibility of inserting content before or after the content of the selected element. You can create a lot of cool stuff, such as icons, but we’ll share more info about this in future articles.
To close this section, I want to let you know that I’ve used a lot of transitions to achieve the desired animations, and a lot of cubic-bezier. If you want to get the best animations using transitions, my advice would be to check out some cubic-bezier documentation and tutorials.
Part 3: JavaScript
Before doing anything else, you will need to include jQuery for this to work. Notice that our main wrapper, .search-wrapper has a .active class attached in the CSS. We’ll use this class for toggling between the states of the main wrapper child.
The searchToggle() function adds or removes the .active class from .search-wrapper in a toggle like fashion.
function searchToggle(obj, evt){
var container = $(obj).closest('.search-wrapper');
if(!container.hasClass('active')){
container.addClass('active');
evt.preventDefault();
}
else if(container.hasClass('active') && $(obj).closest('.input-holder').length == 0){
container.removeClass('active');
// clear input
container.find('.search-input').val('');
}
}
Conclusion
Animating with CSS3 can be fun and easy!
Hope you liked this tutorial and find it useful. And don’t hesitate to download the source and try out new projects with it. I will keep creating some other fun stuff, examples on cubic-bezier function and CSS pseudo classes in my future articles. Until then, enjoy!
If you have any questions or suggestions you can post them in the comment section below. I will reply and find answers as often as I can.
Comments