Tags:

Simple and elegant search bar that expands on click with a really cool transform affect using SCSS pseudo classes

Level: Intermediate / Advanced

Project at a Glance:

The search bar is broken up into four sections. We will have our main <form> element, an <input> and two <span> elements. One <span> will be our element that expands the search bar and the other will act as the parent of our pseudo elements for our transform affect. When we click on our first <span> element, it will trigger a simple JavaScript function that will toggle a class on and off. When the class is on, the search bar will expand, and when the class is removed, the search bar will be hidden.

Note: We will be using SCSS for this project. SCSS turns your CSS into a styling powerhouse and gives us much more flexibility while keeping everything very readable.

Let's create the Html markup.

<div class="wrapper">
<form action="#" class="searchForm">
  <input class="searchInput" placeholder="What do you want to find?">
     <span class="searchBtn">
       <span class="searchIcon">
     </span>
  </span>
</form>
</div>

 Let's create our variables so we don't have to repeat our yourselves in our code. 

$backgroundColor: #e4136e;
$outlineColor: #fff;
$width:300px;
$formHeight: 45px;

Next, set our html and body to 100% height and width and center our form element in the center of the body. We will also give it some styling and a transition for our slide affect later on.

PRO TIP: Use the transform property to easily center elements.

form {
  position:absolute;
  width:300px;
  height:$formHeight;
  background:transparent;
  top:50%;
  left:50%;
  transform:translate(-50%, -50%);
  transition:0.5s;
  border-radius: 25px 0px 0px 25px;
  box-shadow: 0px 3px 9px -4px #0e0d0e;
  border-bottom: 5px solid #7d0544;
  
}

Now let's nest some styling inside our form selector. We use the & selector to select the parent element and then select our child element. We put all of this inside our parent brackets.

form {
  position:absolute;
  width:300px;
  height:$formHeight;
  background:transparent;
  top:50%;
  left:50%;
  transform:translate(-50%, -50%);
  transition:0.5s;
  border-radius: 25px 0px 0px 25px;
  box-shadow: 0px 3px 9px -4px #0e0d0e;
  border-bottom: 5px solid #7d0544;
  

  & input {
    outline:none;
    background:transparent;
    color:#fff;
    font-size:22px;
    display:none;
    border:0px;
    height:100%;
    border-radius:3px;
    width:0px;
    transition:0.5s;
    
    &::placeholder {
    color:#ff97bb;
  }
    
  }

} 

This just adds some simple styling our input. Notice we set it to a width:0px and display:none. These will get changed later on when we expand our search bar.

Let's create the styling for our span element which will act as our onclick element. We are going to make our span a circle and use ::before and ::after pseudo elements to create a search icon in the center of it. First let's style our .searchBtn element which is our parent span tag.

.searchBtn {
    position: absolute;
    right: -30px;
    top: -10px;
    border-radius: 50%;
    display: block;
    height: 75px;
    width: 75px;
    background: #e4136e;
    box-shadow: 0px 0px 15px -3px #000000;
    transition:0.5s;
  
}

Got a pink-ish circle in the center of your screen now? Yes? Good!  No? Go back and see what happened. 

Now select our .searchIcon child span tag and nest our styling inside the .searchBtn selector for our search icon. Our ::after element will be the circle outline of our search icon and the ::before will be the diagonal line. For our ::before element, we are going to use the transform property to rotate our line to make it diagonal.

.searchBtn {
    position: absolute;
    right: -30px;
    top: -10px;
    border-radius: 50%;
    display: block;
    height: 75px;
    width: 75px;
    background: #e4136e;
    box-shadow: 0px 0px 15px -3px #000000;
    transition:0.5s;
  
    & .searchIcon {
    
      
      &::after {
        content: "";
        position: absolute;
        width:30px;
        height:30px;
        top:14px;
        left:15px;
        border:3px solid #fff;
        border-radius:50%;
        transition:0.5s;
        
      }
      &::before {
        content: "";
        position: absolute;
        height: 15px;
        top:43px;
        left: 46px;
        background: $outlineColor;
        border: 2px solid $outlineColor;
        transition:0.5s;
        transform: rotate(-45deg);
      }    
    } 
  }

Now that's cool! Now that our icon is created with CSS and we have two separate elements, we can manipulate them individually when we click it.

Let's write our JavaScript so we can expand our input, and a CSS class that will toggle when we click our search icon. 

var searchBtn = document.querySelector(".searchBtn");
var form = document.querySelector(".searchForm");

searchBtn.addEventListener("click", expandSearch);

function expandSearch() {
  form.classList.toggle("expandInput");
  searchBtn.classList.toggle("searchBtnExpand");
}

Add this class to your CSS so the form opens and closes. This also adds some padding, gives the form a background color and sets our input to a full width. The padding we added prevents the text in the input field from going outside of our form element when the user is typing in it.

.expandInput {
  width:300px;
  padding: 5px 55px 5px 15px;
  background:$backgroundColor;
  
  & .searchInput {
    display:inline-block;
    width:100%;
  }
  
}

Cool! Now we need to add the fun part. The transform effect for our search icon. We're going to select our pseudo elements and change the position and size so it turns into an 'X' when the class is toggled on. In our JavaScript function, we are calling a .searchBtnExpand class so let's create that.

.searchBtnExpand {
  background:#240536;
  
  & .searchIcon::before {
    content: "";
    position: absolute;
    height: 39px;
    top: 18px;
    left: 36px;
    background: $outlineColor;
    border: 2px solid $outlineColor;
    transform: rotate(-45deg);
  }
  
  & .searchIcon::after {
    content: "";
    position: absolute;
    border-radius:0;
    width:0px;
    height: 39px;
    top: 17px;
    left: 36px;
    background: $outlineColor;
    border: 2px solid $outlineColor;
    transition:0.5s;
    transform: rotate(45deg);
   }
}

And there you have it! Feel free to practice with the transform effects. I highly recommend opening it up in the developer tools of your browser and changing the values of the transform and see how you can manipulate them. 

If you have any questions or comments, let me know below! 

Let's take a quick look on how to create a simple, but attractive bouncing animation that can be used a loader animation. 

What we're going to use

  • animation-name
  • animation-duration
  • animation-iteration-count
  • animation-timing-function
  • animation-delay
  • transform with scale and translate

Create a wrapper div and three divs inside of it with the classes of .cirlce1, .circle2 and .circle3.

<div class="wrapper">

  <div class="circle1"></div>
  <div class="circle2"></div>
  <div class="circle3"></div>
   
</div>

We want our loader to be aligned to the center of the screen. Make our body 100% height and width and set it to absolute positioning. for the .wrapper, we're going to set to display:flex and justify-content:center and align-items:center.

body {
  position:absolute; 
  width:100%;
  height:100%;
}
.wrapper {
  
  display:flex;
  flex-direction:row;
  width:100%;
  height:100%;
  justify-content:center;
  align-items:center;
  position:relative;
}

Make our circles width and height to 100px width a 50% border radius.

We need to have separate CSS for each circle since each one will have it's own animation-delay applied to it.

Animation

  • animation-name - Self explanatory. Sets the name of our animation.
  • animation-duration - Sets the length that it takes the animation to finish 1 iteration.
  • animation-iteration-count - The amount of times you want the animation to repeat. Set it to infinite if you want it to continue forever.
  • animation-timing-function - Uses a mathematical function called Cubic Bezier Curve which specifies the speed curve of the animation. It's meant to help keep animations smooth. You can use preset settings or create your own steps.
  • animation-delay - How long to delay the animation before it begins.
.circle1 {
  background:#40ded3;
  animation-name:move-circle;
  animation-duration:1.3s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
  animaton-delay:.25s;
  -webkit-animation-delay:.25s;
  -moz-animation-delay:.25s;
}

.circle2 {
  background:#40de8f;
  animation-name:move-circle;
  animation-duration:1.3s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
  animaton-delay:.35s;
  -webkit-animation-delay:.35s;
  -moz-animation-delay:.35s;
  
}

.circle3 {
  background:#b7de40;
  animation-name:move-circle;
  animation-duration:1.3s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
  animaton-delay:.45s;
  -webkit-animation-delay:.45s;
  -moz-animation-delay:.45s;
}

Now let's put the animation in motion! Using @keyframes, we are going to set custom animation frames.

To make our animation smooth, we are going to set several custom key frames and adjust the X and Y axis of our circles. We want to make our circles appear as they are leaping off the ground then landing with a slight bounce. To do this, we use the transform: scale() and translate().

@keyframes move-circle {
 0%   { transform: scale(1,1)    translateY(0); 
  }
 10%  { transform: scale(1.2, .9)
 translateY(10px);
  }
  30% { transform: scale(.9, 1.2)
  translateY(-100px)
  }
  50% { transform: scale(1.2,.9)
  translateY(0)
  }
  57% {transform: scale(1.1,.9)
  translateY(-7px);
  }
  75% {transform: scale(1,1)
  translateY(0)
  }
  100% {transform: scale(1,1)
  translateY(0)
  }
  
}

Final Output!

 

CSS is a fantastic front-end style-sheet language. It's responsible for making our projects look fantastic. Now with the evolution of CSS, many useful and fun features have been thrown into the mix including how we target our elements. Over the years of creating web apps and websites, there's some selectors that are constantly being used and others than get used a little less often, but hold a high amount of importance. Let's get into it!

#skillLevel: Beginner; {

1. *

* {
margin:0;
padding:0;
}

 This is not recommended for production code, as this targets all elements on a page. This method can work for testing purposes, but this will hurt performance if used in production mode. 

2. #Id, .ClassName

#thisIsAnId {
  background:#000;
  color:#fff;
  padding:0px;

}

.thisIsAClass {
  background:#000;
  color:#fff;
  padding:0px;
  
}

This is probably the most commonly used selector in CSS. The # symbol is used to select an ID from a page while the period is used to select classes on a page. The ID will target only the element with that name, while the period will select all elements with the same class name. It is not recommended to overly use id's. There are numerous ways for selecting elements to reduce the use of using id's on too many elements. I'll cover those as we go on.

3. element > element

#thisIsTheParentId > p { 
   color:red;
}

In this example, by using the greater than symbol, it will target all `p` elements within the parent element. This is a powerful way to style many elements at one time that share a common style while still keeping them contained to a specific parent element.

4. .sampleClass1.sampleClass2

.thisIsTheParentId.anotherClassName { 
   font-size:18px;
}

This method will select an element(s) that have both class names within the class attribute. An example case of this could be in a navigation menu where there are multiple <li> elements. Some list items could have a single class while some could have two classes so a specific style can be assigned for certain uses.

5. .sampleClass1 .sampleClass2

.thisIsTheParentId .anotherChildClass {
   width:100%;
   margin:0 auto;
}

In this example, we are selecting the elements with a class name of .anotherChildClass which are children of .thisIsTheParentClass. 

6. element.class

p.sampleClass {
   color:#fff;
   font-size:18px;
   line-height:1;
   
}

This selector targets all p tags with the specified class name. This is a simple and effective way to target multiple of the same element while narrowing down the styling to a specific class name. 

7. element element

div p {
   color:#fff;
}

li a  {
   text-decoration:none;
}

ul li {
   background-color:#f8f8f8;
}

The descendant selector. This is a very common selector method that allows you to get a little more precise with your styling. For example, instead of selecting all links, you can select links within a list element or you could select specific heading tags within a div

 

8. Target Links

a:visited {
   color:red;
}

a:link {
   color:#000;
}

This is a pseudo class that allows us to target links which have not been clicked on by using a:link. Conversely, you can use a:visited to target the list that have been clicked on.

9. element:hover

#sampleId:hover {
   color:#000; 
   box-shadow:0px 3px 3px -3px #444;
   transform:scale(1.1);
}

Ok, this one is pretty self explanatory. This is another pseudo class selector that targets a specific element, Id or Class and adds a hover effect to it. This will be very commonly used to add hover effects to links within a menu. It's also very commonly used now for modern designs to incorporate the :hover for interactivity such as flipboxes and fancy button animations. The Code Crypt has some of these hover effects featured on our site!

}

#skillLevel:intermediate {

10. element[attribute]

input[type="email"] {
   color:red;
   background:#f8f8f8;
   border:1px solid blue;
}

<form action="" method="post" id="myForm">
   <input type="text" value="" placeholder="Enter Name">
   <input type="email" value="" placeholder="Enter Email">
</form>

This is an attribute selector. This allows you to select different types of attributes within an element. This is a very common method of styling when creating forms.

11. element[attribute].checked

input[type=radio]:checked {
   border:1px solid red;
}

This is a pseudo class that allows you to style elements that are checked. This works with radio buttons and checkboxes. 

12.element:not(selector)

input:not(.className) {
   background-color:#eeeeee;
}

This is an overlooked but relatively helpful pseudo class that allows you to select all of an element except for one that has a specific ID or class. 

13 ::before, ::after

#h2::before {
   content:"";
   position:absolute;
   display:inline-block;
   height:2px;
   width:150px;
   background-color:red;
   margin:0 0 10px 25px;

}

#h2::after{
   content:"";
   position:absolute;
   display:inline-block;
   height:2px;
   width:150px;
   background-color:red;
   margin:0 25px 10px 0;

}

This is by far one of my favorites. Instead of a pseudo class, this is considered a pseudo element which is distinguished by the :: notation that came along with CSS3. Due to earlier versions of CSS, User Agents are still required to remain compatible with the : notation so :after and :before is just as accepted as ::after and ::before. However, over the years I have found it a nice way to distinguish pseudo classes from pseudo elements so I prefer the :: notation, although some will still argue that : should still be used. 

These pseudo elements allow you to add content before and after the selected element. You can create arrows, menu icons, quoting text, breadcrumbs navigation etc. The above snippet will add a horizontal line to the left and right of the h2 element giving it a nice styled appearance. The possibilities are endless with these pseudo elements!

14. element:nth-child(x)

li:nth-child(2) {
   color: green;
}

Need to target a specific element within a list or a specific paragraph in a div? The nth-child pseudo class allows you to select it. Unlike arrays in JavaScript and PHP which start at zero, this is not zero-based. If you want the 4th child in a list, it'll read li:nth-child(4).

15. element:nth-last-child(x)

li:nth-last-child(3) {
   color:blue;
}

Almost exactly the same thing as nth-child except for nth-last-child starts at the other end of the element list. For example, if you have 200 list items, and you want to style the 197th list item, li:nth-last-child(4) would style it.

16. element:first-child & element:last-child

<div>
  <article>
      <p>One</p>
      <p>Two</p>
      <p>Three</p>
  </article>
</div>

p:first-child {
   font-size:1.6em;
   color:#444;
}

p:last-child {
   font-size:1.2em;
   color:blue;
}  

This pseudo class is relatively straight forward. The :first-child selects the first child within a parent regardless of type of element. This is similar to the :first-of-type pseudo class, but it is less specific. :first-child matches the very first child element and :last-child matches the very last child element while :first-of-type matches the first occurrence of an element. 

}

© 2019 The Code Crypt. All Rights Reserved.