How To Create An Animated Email Subscription Form With Pure CSS

0 Comments

Forms are ugly by default. Creating a basic form is not hard — but a lot of tutorials I remember encountering in my early days of coding required some sort of JavaScript.

CSS, however, is a lot more powerful than you think. This is the write-up part for the video below. Don’t forget to like and subscribe 😉

Tutorial Version:

Speed Coding Version:


Here is what we will be making:

Here is the HTML to kickstart us off:

<div class="wrapper">
    <input type="checkbox" id="click">
    <label for="click" class="btn-1">Subscribe</label>
    <div class="field">
      <input type="text" placeholder="Email Address">
      <label for="click" class="btn-2">Subscribe</label>
    </div>
</div>

This is basically a simple form with some labels and a checkbox so we know which visual state we’re in. It will let us leverage pseudo-states in CSS without needing to do any programmatic selection. There is no actual button here. In part, it’s because I’m assuming that you’ll be using Angular, React, Vue, or some sort of frontend framework to handle what happens with the click event.

Here is what the subscribe form looks like without CSS:

Yup. It’s pretty darn ugly. Let’s get on with styling it in CSS.

The CSS inside html and body can be abstracted out into its own container. However, I’m just putting it here because there is no other element on the page. What’s happening here is that a grid is created and all the items have been centered on the page. The font-family can be whatever you want it to be, along with the background.

The .wrapper selector repositions the subscribe form to the center of the page via position:relative , in addition to setting the height and width. display:flex turns elements inside into flex items and aligns the items inside to be centered against the .wrapper container.

html,body{
  display:grid;
  height:100%;
  place-items:center;
  background: #8F6593;
  font-family:'Arial', sans serif; 
}
.wrapper{
  position:relative;
  height: 60px;
  width: 400px;
  display:flex;
  align-items:center;
  justify-content:center;
  text-align:center;
}

Here is what it looks like:

Now that we’ve got everything into position, it’s time to style it. Let’s start with the first Subscribe label. This one has the class btn-1 attached to it.

We are going to make it the full height of the subscribe container, with a white background, and text color that matches the background (#3B252C ). There are a few other font related configurations in the CSS, such as font-weight , font-size , and line-height. Because we also want this to look like a button, we are going to round the corners with border-radius: 5px. The cursor is changed to a pointer so the user knows to click on it.

We are also adding a transition to this button, so when the user clicks it, there is a smooth ease-in-out flow animation effect.

.wrapper .btn-1{
  position: absolute;
  height: 100%;
  width: 50%;
  background:white;
  color:#3B252C;
  font-weight: 500;
  font-size:25px;
  line-height: 60px;
  border-radius: 5px;
  cursor:pointer;
  transition: all 0.4s ease-in-out;
}

This is what the subscription form looks like with the above CSS applied:

The next thing we want to do is hide this button when it gets clicked. This is so it makes room for the actual subscription form we want to show. To do this, we use the ~ sign to indicate and target the sibling selector .btn-1 . So what the selector below is saying is — if the state of #click is checked , apply the following CSS to .btn-1 . We hide .btn-1 by reducing the opacity, and decrease its size via height and width to give the shrinking animation that’s achieved through the transition set at the actual .btn-1 selector.

#click:checked ~ .btn-1 {
  height: 40px;
  width: 100px;
  opacity: 0;
  pointer-events: none;
}

Here is what the subscribe button looks like in action:

Although .btn-1 looks like an actual button, it’s actually a label in reality. We’re just clicking on the label to toggle the checkbox, and therefore hide and show our .btn-1 .

Now it’s time to style our email field. There are three things happening in the CSS below for our subscribe form. The .wrapper .field selector is dealing with the container that holds our actual form. It’s setting the width to 0 so that we can create the expanding animation when #click is checked. The opacity is also set to 0 so that we don’t see it until #click is checked .

.wrapper .field input is the actual styling for the field itself and has nice rounded corners through the border-radius. There are a few other visual things like padding and outline .

Like .btn-1, .field is targeted via the sibling sector when #click:checked happens. The opacity is increased to 1 and the width becomes 100% to fill the length of the container.

.wrapper .field{
  height: 100%;
  width: 0%;
  opacity:0;
  transition: 0.4s ease-in-out;
}
.wrapper .field input{
  height:100%;
  width:100%;
  border:2px solid #fff;
  border-radius:5px;
  padding: 0 130px 0 15px;
  outline:none;
}
#click:checked ~ .field{
  opacity:1;
  pointer-events: auto;
  width:100%;
}

Here’s what our subscribe form looks like now:

The final step is to style the second Subscribe button and hide the checkbox. This is easily achieved with the CSS below.

.wrapper .field .btn-2{
  cursor:pointer;
  position: absolute;
  right: -135px;
  top:50%;
  transform: translateY(-45%);
  height:40px;
  width: 100px;
  background: #8F6593;
  color:white;
  border-radius: 5px;
  line-height: 40px;
  transition: 0.4s ease-in-out;
}
.wrapper #click{
  display:none;
}

And that is basically it! Here is the final result.

Here is the full HTML and CSS for our subscribe form.

<div class="wrapper">
    <input type="checkbox" id="click">
    <label for="click" class="btn-1">Subscribe</label>
    <div class="field">
      <input type="text" placeholder="Email Address">
      <label for="click" class="btn-2">Subscribe</label>
    </div>
</div>

And the CSS:

html,body{
  display:grid;
  height:100%;
  place-items:center;
  background: #8F6593;
  font-family:'Arial', sans serif; 
}
.wrapper{
  position:relative;
  height: 60px;
  width: 400px;
  display:flex;
  align-items:center;
  justify-content:center;
  text-align:center;
}
.wrapper .btn-1{
  position: absolute;
  height: 100%;
  width: 50%;
  background:white;
  color:#3B252C;
  font-weight: 500;
  font-size:25px;
  line-height: 60px;
  border-radius: 5px;
  cursor:pointer;
  transition: 0.4s ease-in-out;
}
#click:checked ~ .btn-1 {
  height: 40px;
  width: 100px;
  opacity: 0;
  pointer-events: none;
}
.wrapper .field{
  height: 100%;
  width: 0%;
  opacity:0;
  pointer-events:none;
transition: 0.4s ease-in-out;
}
.wrapper .field input{
  height:100%;
  width:100%;
  border:2px solid #fff;
  border-radius:5px;
  padding: 0 130px 0 15px;
  outline:none;
}
#click:checked ~ .field{
  opacity:1;
  pointer-events: auto;
  width:100%;
}
.wrapper .field .btn-2{
  cursor:pointer;
  position: absolute;
  right: -135px;
  top:50%;
  transform: translateY(-45%);
  height:40px;
  width: 100px;
  background: #8F6593;
  color:white;
  border-radius: 5px;
  line-height: 40px;
  transition: 0.4s ease-in-out;
}
.wrapper #click{
  display:none;
}