Create a Carousel using CSS Scroll Snap and JavaScript

This tutorial will help you create a responsive carousel using the CSS scroll-snap property and very little JavaScript for navigation. You can use it for products display, or as a gallery, or for your testimonials – like the example in this tutorial. So here is what we will be creating:

carousel example

This is really just a horizontal scroll section but when you scroll, it “snaps” (auto-adjusts the position of the scroll container) to ensure it displays the full item – making it behave like a carousel. You can also use the arrows to display next and previous items, which requires JavaScript. You need to have some basic knowledge of HTML, CSS and JavaScript to follow along. On the way, you will learn about the CSS scroll-snap properties. Let’s get started.

Millions of Fonts, Themes, Graphics: Starting at ONLY $16.50 per Month
Web Fonts

Web Fonts
8,000+ Fonts

WordPress Themes

WordPress Themes
1,200+ Themes

Graphic Assets

Graphic Assets
32,000+ Graphics

DOWNLOAD NOW
Envato Elements

 

Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
  
</body>
</html>

The font used in this demo is ‘Noto Sans’. Let’s embed this font from Google fonts. Add this CDN link below the title tag to embed regular and italic styles of this font.

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">

Create your stylesheet and name it style.css. Link the stylesheet to your HTML document below the Google fonts CDN link using

<link rel="stylesheet" href="style.css">

I have downloaded three portrait images from Pexels and cropped them square for this demo. You can choose to include your own. Name them testimonial1.jpg, testimonial2.jpg and testimonial3.jpg.

Creating a basic scroller

Let’s first create a simple horizontal scroller with three items with width same as that of the scroll container.

HTML

Add this markup within body tag in your HTML file:

<div class="testimonials">
   <div class="scroller">
       <div class="item">
           Item 1
       </div>
       <div class="item">
           Item 2
       </div>
       <div class="item">
           Item 3
       </div>
   </div>
</div>

Here, the testimonials div acts as the wrapper, within which is the horizontal scroller, and then three item divs.

CSS

In style.css, begin with some common styles for all elements:

* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
}

Add these styles to the body element:

body {
   font-family: 'Noto Sans', sans-serif;
   font-size: 1em;
   color: #4A5568;
}

Restrict the width of the testimonials wrapper to about 800px and center it.

.testimonials {
   max-width: 800px;
   margin: auto;
}

Add these basics styles to see the scroller at work.

.scroller {
   overflow-x: scroll;
   display: flex;
}
.item {
   min-width: 100%;
   min-height: 200px; /* To start with */
   background-color: #EDF2F7; /* For demo */
}

With this, you can see a horizontal scroll section like this.

carousel beginnings - horizontal scroll section

Scroll Snapping

With CSS scroll snap, it is possible to enforce the scroll position (smoothly moving to the enforced position) once the user stops scrolling. This works by applying two primary properties – scroll-snap-type and scroll-snap-align.

The scroll-snap-type property is applied on the parent container (In our case, it’s the scroller div). It takes two arguments – the snap direction ( x | y | both ) and the snap behavior ( mandatory | proximity ). We need to use x for the direction because we are scrolling horizontally. For the behavior, mandatory means the browser has to snap to the position, while proximity is less strict. We will use mandatory.

The scroll-snap-align property is applied to the child items. It determines the snap point. It takes one or two arguments for x or/and y direction ( none | start | end | center ). In our case, this property can have any value except for none, because our items are 100% width of the parent container. You can dig deeper into the CSS Scroll Snap concept here.

Add these properties to the scroller and item divs.

.scroller {
   /* Existing styles here */
   scroll-snap-type: x mandatory;
}
.item {
   /* Existing styles here */
   scroll-snap-align: center;
}

That’s all you need for the magic! Now check your browser and scroll horizontally. You will notice that the browser strictly snaps to display a full item once you stop scrolling at any point. With this, the primary carousel behavior is achieved.

Adding content

Let’s add some content to the items.

HTML

<div class="item">
   <img src="testimonial1.jpg" alt="Elise">
   <div class="card">
       <p>
           Eu rebum molestie per. No nostrud imperdiet abhorreant qui, hinc incorrupte vix ad. Vel id aliquip oblique. Primis feugait sit an, brute illud convenire duo ea. Graece tempor eripuit sed in.
       </p>
       <span>Elise</span>
   </div>
</div>
<div class="item">
   <img src="testimonial2.jpg" alt="John">
   <div class="card">
       <p>
           Vitae pericula maluisset ut mei, pro eleifend gubergren eu. Et his brute graeci. Affert ponderum ei vel, dolorum accumsan ea has. Sea oblique salutatus ei, simul lucilius pri et. Errem melius temporibus ut eos
       </p>
       <span>John</span>
   </div>
</div>
<div class="item">
   <img src="testimonial3.jpg" alt="Imani">
   <div class="card">
       <p>
           Ne est virtute indoctum, quaeque vituperata cum ut. Te nisl quaeque pri. Vix ex autem latine, mel ne nobis scaevola, ei est dolor utinam commune. Pri unum doctus in, cu primis pertinax eos.
       </p>
       <span>Imani</span>
   </div>
</div>

CSS

Time to style it up.

.testimonials {
   /* Existing styles here */
   padding: 15px;
   text-align: center;
}
.item {
   /* Existing styles here */
   background-color: white; /* Change the value to white */
   margin-bottom: 10px;
   padding: 0 50px;
}
.item img {
   margin: 15px auto -60px;
   width: 120px;
   height: 120px;
   border: solid 4px #ffffff;
   border-radius: 60px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
   z-index: 2;
}
.card {
   background-color: rgb(237, 242, 247);
   padding: 80px 40px 40px;
   border-radius: 10px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
   z-index: 1;
}
.card p {
   font-style: italic;
   line-height: 1.6;
}
.card span {
   display: block;
   margin-top: 20px;
   color: teal;
   font-weight: bold;
   letter-spacing: 0.05em;
   text-transform: uppercase;
}

Our carousel has taken shape. The only thing pending now is the navigation functionality.

Adding navigation

In this demo, I have added simple arrows with < and > symbols for the navigation buttons. You can also use icons or images.

HTML

Add these two lines immediately after the scroller div, but within the testimonial div:

<span class="btn prev">&lt;</span>
<span class="btn next">&gt;</span>

CSS

Add these to your stylesheet for positioning and styling the navigation buttons:

.testimonials {
   /* Existing styles here */
   position: relative;
}
.testimonials .btn {
   position: absolute;
   top: 50%;
   margin-top: 20px;
   height: 30px;
   width: 30px;
   border-radius: 15px;
   background-color: rgba(95, 106, 117, 0.3);
   z-index: 1;
   line-height: 30px;
   text-align: center;
   color: white;
   font-weight: bold;
}
.testimonials .btn:hover{
   background-color: rgba(95, 106, 117, 0.5);
   cursor: pointer;
}
.testimonials .btn.next {
   right: 15px;
}
.testimonials .btn.prev {
   left: 15px;
}

JavaScript

We need some JavaScript to make the buttons work. Add this script before closing the body tag.

<script>
   const testimonials = document.querySelector('.testimonials');
   const scroller = testimonials.querySelector('.scroller');
   const nextBtn = testimonials.querySelector('.btn.next');
   const prevBtn = testimonials.querySelector('.btn.prev');
   const itemWidth = testimonials.querySelector('.item').clientWidth;
 
   nextBtn.addEventListener('click', scrollToNextItem);
   prevBtn.addEventListener('click', scrollToPrevItem);
 
   function scrollToNextItem() {
       scroller.scrollBy({left: itemWidth, top: 0, behavior: 'smooth'});
   }
   function scrollToPrevItem() {
       scroller.scrollBy({left: -itemWidth, top: 0, behavior: 'smooth'});
   }
</script>

In this code above, we have added ‘click’ event handlers to the prev and next buttons. The functionality of moving to the previous or next item is achieved using the scrollBy method. Check out the syntax and examples of element.scrollBy method.

The option behavior: ‘smooth’ gives a smooth sliding effect. Please note that this effect is not supported in IE 11 and a few older versions of other browsers.

Making it loop

You can optionally make this carousel loop - clicking on ‘next’ button for the last item makes the carousel start from beginning and similar behavior for ‘prev’ button, by changing the methods in your script to this:

function scrollToNextItem() {
   if(scroller.scrollLeft < (scroller.scrollWidth - itemWidth))
       // The scroll position is not at the beginning of last item
       scroller.scrollBy({left: itemWidth, top: 0, behavior:'smooth'});
   else
       // Last item reached. Go back to first item by setting scroll position to 0
       scroller.scrollTo({left: 0, top: 0, behavior:'smooth'});
}
function scrollToPrevItem() {
   if(scroller.scrollLeft != 0)
       // The scroll position is not at the beginning of first item
       scroller.scrollBy({left: -itemWidth, top: 0, behavior:'smooth'});
   else
       // This is the first item. Go to last item by setting scroll position to scroller width
       scroller.scrollTo({left: scroller.scrollWidth, top: 0, behavior:'smooth'});
}

Making it fully responsive

What we have now is already responsive. Except that, for browser widths smaller than 480px, the card becomes too narrow and long. So let’s reduce some padding for the item and card for this width using media queries.

Add this to your stylesheet:

@media screen and (max-width: 480px) {
.item {
padding: 0 30px;
}
.card {
padding: 80px 30px 30px;
}
}

This is it! You have successfully created a responsive carousel for your testimonials section with the least amount of JavaScript, and also learned about the new scroll-snap properties in CSS. You can modify this carousel to suit your needs. Try and explore using this carousel for images with varying width and watch how it behaves.

Here is the complete source code for you to download.

 

Download Source Code

 

How To Create a Responsive Timeline with Image Thumbnails

In this tutorial you will learn how to create a responsive timeline for a set of related events you wish to display in a chronological (or reverse chronological) sequence. This can be used to display significant company milestones, news or personal events. I have used personal travel events as an example in this post. Here’s what you will be able to create by the end of this tutorial.

Responsive Timeline - Desktop View

Desktop View

 

Responsive Timeline - Small Tablets / Mobile Landscape View

Small Tablets / Mobile Landscape View

 

Responsive Timeline - Mobile Portrait View

Mobile Portrait View

 

You need to have some basic knowledge of HTML and CSS to follow along. Let’s get started.

Millions of Fonts, Themes, Graphics: Starting at ONLY $16.50 per Month
Web Fonts

Web Fonts
8,000+ Fonts

WordPress Themes

WordPress Themes
1,200+ Themes

Graphic Assets

Graphic Assets
32,000+ Graphics

DOWNLOAD NOW
Envato Elements

 

Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
  
</body>
</html>

I have used the font ‘Noto Sans’ – with font weights 300 and 700. So add the following line below the title tag to embed this font using Google fonts.

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap" rel="stylesheet">

Create your stylesheet and name it style.css. Link the stylesheet to your HTML document below the Google fonts CDN link using:

<link rel="stylesheet" href="style.css">

The bare bones structure

Let’s first create the timeline structure, and in the next part we will add and style the content.

HTML

Add this to your markup:

<div class="timeline">
   <div class="container container-left">
       <div class="content"></div>
   </div>
   <div class="container container-right">
       <div class="content"></div>
   </div>
   <div class="container container-left">
       <div class="content"></div>
   </div>
</div>

CSS

In style.css, begin with some common styles for all elements:

* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
}

Add these styles to the body element:

body {
   background-color: #EDF2F7;
   font-family: 'Noto Sans', sans-serif;
   font-size: 1em;
   color: #4A5568;
}

To the timeline, add the following styles. Let’s restrict the maximum width to 1200px and center the content using margin.

.timeline {
   position: relative;
   max-width: 1200px; /* Restrict the width on large screens */
   margin: 0 auto; /* Center the content */
   padding: 30px;
}

Now, we can use the ::after pseudo element to create that actual line in the center for timeline. Add these styles:

.timeline::after {
   content: '';
   position: absolute;
   width: 6px;
   background-color: white;
   top: 0;
   bottom: 0;
   left: 50%;
   margin-left: -3px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

Width of the line is 6px. Hence, we have used left:50% and margin-left: -3px to position the line at the exact center. Read more about centering an element using absolute position.

You will now see a very tiny line at the top of your webpage, vertically centered. As we add some content, this line lengthens.

Let’s style the left and right containers that hold the timeline elements.

.container {
   position: relative;
   width: 50%;
}
.container-left {
   left: 0;
}
.container-right {
   left: 50%;
}

You will still not see anything on the web page until we style the .content element within.

.content {
   padding: 30px;
   background-color: white;
   position: relative;
   border-radius: 6px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

You should be able to see this now.

Responsive timeline so far

 

Our timeline is taking shape. Let’s add those tiny arrow marks pointing to the line using a ::before pseudo element.

.container .content::before {
   content: " ";
   height: 0;
   position: absolute;
   top: 40px;
   width: 0;
   z-index: 1;
   border: medium solid white;
   right: -10px;
   border-width: 10px 0 10px 10px;
   border-color: transparent transparent transparent white;
}

This will add all arrow marks pointing to the right, positioned to the right edge of the box. But for the boxes on the right, we need an arrow pointing to the left and positioned to the left. So, change of all this to:

.container .content::before {
   content: " ";
   height: 0;
   position: absolute;
   top: 20px;
   width: 0;
   z-index: 1;
   border: medium solid white;
}
.container-left .content::before {
   right: -10px;
   border-width: 10px 0 10px 10px;
   border-color: transparent transparent transparent white;
}
.container-right .content::before {
   left: -10px;
   border-width: 10px 10px 10px 0;
   border-color: transparent white transparent transparent;
}

Read more about how to create these CSS triangles using borders. Of course the output now looks a little odd because the boxes are sticking to the line. Add some padding to the container to space them out.

.container-left {
   /* Existing styles here */
   padding-right: 70px;
}
.container-right {
   /* Existing styles here */
   padding-left: 70px;
}

This is perfect.

responsive timeline with arrows

 

Adding and styling content

Let us first add the images and position them on the “line”.

HTML

Change your markup to this, by adding 3 div elements with background images.

<div class="timeline">
   <div class="container container-left">
       <div class="image" style="background-image:url('https://images.pexels.com/photos/307008/pexels-photo-307008.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=100')"></div>
       <div class="content"></div>
   </div>
   <div class="container container-right">
       <div class="image" style="background-image:url('https://images.pexels.com/photos/210012/pexels-photo-210012.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=100')"></div>
       <div class="content"></div>
   </div>
   <div class="container container-left">
       <div class="image" style="background-image:url('https://images.pexels.com/photos/2104152/pexels-photo-2104152.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=100')"></div>
       <div class="content"></div>
   </div>
</div>

As you can see, I have directly linked 3 images from Pexels. You can choose to include your own.

CSS

Let’s add some size and shape to this image div.

.image {
   width:90px;
   height:90px;
   background-size:cover;
   background-position:center;
   border:solid 5px #ffffff;
   border-radius:50px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

Now position them centered on the line, appearing next to boxes.

.image {
   position: absolute;
}
.container-left .image {
   right: 0;
   margin-right: -45px;
}
.container-right .image {
   left: 0;
   margin-left: -45px;
}

But the images appear behind the line! This is easily fixed with some z-index.

.timeline::after {
   /* Existing styles here */
   z-index: 1;
}
.image {
   /* Existing styles here */
   z-index: 2;
}

Don’t mind the images overlapping each other right now. It will be fixed when we add some content within the boxes. But if your content is going to be very little, add a minimum height to the container.

.container {
   /* Existing styles here */
   min-height: 120px;
}

Next, add the actual content.

HTML

Add this markup within each .content block. Change the text as you wish.

<span>July 2020</span>
<h2>Visit to Spain</h2>
<p>
   Et hinc magna voluptatum usu, cum veniam graece et. Ius ea scripserit temporibus, pri cu harum tacimates neglegentur. At adipisci incorrupte nam. Cu qui sumo appareat constituto.
</p>

CSS

We need to position the arrow marks such that they align with the center of the image.

.container .content::before {
   /* Existing styles here */
   top: 35px;
}

Align the text on left side boxes to the right and right side boxes to the left.

.container-left {
   /* Existing styles here */
   text-align: right;
}
.container-right {
   /* Existing styles here */
   text-align: left;
}

Now some styles for the actual content.

.content span {
   color: #2C7A7B;
   font-size: 1.1em;
   font-weight: bold;
}
.content h2 {
   font-size: 1.8em;
   padding-top: 5px;
}
.content p {
   line-height: 1.6;
   padding-top: 5px;
}

Isn’t this neat? Great! Now resize your browser window to make it smaller, and things start to look messy when the screen size is too small.

Make it responsive

In smaller screens, when there are boxes on both sides of the line, the boxes become too narrow. Time to add some media queries. Let’s add a breakpoint at 767px width and position both the boxes on one side when the screen width is smaller than this width.

@media screen and (max-width: 767px) {
   /* Add styles to change the behaviour for screens smaller than 767px width */
}

First, position the line to the left of the page. Add the below styles within the media query:

.timeline::after {
   left: 65px;
}

Make the containers full width and position them correctly by overriding the previous styles.

.container {
   width: 100%;
   padding-left: 100px;
   padding-right: 0px;
}
.container-right {
   left: 0%;
}
.container-left {
   text-align: left;
}

Add some top margin to all the containers, except the first.

.container {
   /* Existing styles here */
   margin-top: 30px;
}
.container:first-of-type {
   margin-top: 0px;
}

Override image styles to position them on the line.

.container .image {
   left:-10px;
   top: 0px;
   margin-left: 0;
   margin-right: 0;
}

The arrows on the “left” boxes need to change position and direction.

.container-left .content::before {
   left: -10px;
   right: auto;
   border-width: 10px 10px 10px 0;
   border-color: transparent white transparent transparent;
}

This is what we have now:

Timeline responsive view one

 

Further reduce the screen size and you will notice that on really small screens (less than 400px width), the boxes again get narrow. Which is why, below 480px, let’s push the containers below the image giving them full screen’s width to occupy.

@media screen and (max-width: 480px) {
   .container {
       padding-left: 0px;
       padding-top: 105px;
   }
}

To prevent the line from appearing on top of the boxes instead of below, just add a z-index to the container and give a higher value than the “line”.

.container {
   /* Existing styles here */
   z-index: 3;
}

The only pending thing right now is to position the arrows on top and make them point upwards.

.container .content::before {
   left: 25px;
   top: -10px;
   border: medium solid white;
   border-width: 0 10px 10px 10px;
   border-color: transparent transparent white transparent;
}

You got it! Resize your browser making it smaller and larger to see how responsive your timeline is. Go ahead and customize it to suit your needs. Just in case you didn’t get this working as expected, download the full source code and feel free to make changes as you wish.

 

Download Source Code

 

Learn How to Create Flip Cards using CSS

In this tutorial you will learn how to create blog post cards that flip on hover revealing the post excerpt on the back of the card. We will achieve this effect using CSS. The end result is responsive, making the card flip on click, on mobile devices. This GIF shows what you will be able to create by the end of this tutorial.

How To Create Flip Cards Using CSS - Demo

You need to have basic knowledge of HTML and CSS to begin with. We will explore a few advanced CSS topics such as perspective and transform towards the end. Let’s dive in.

Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
  
</body>
</html>

I have used the font ‘Lato’ – with font weights 300 and 700. So add the following line below the title tag to embed this font using Google fonts.

<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet">

Create your stylesheet and name it style.css. Link the stylesheet to your HTML document below the Google fonts CDN link using

<link rel="stylesheet" href="style.css">

I have used these three blog post images from Pexels – post1.jpg, post2.jpg and post3.jpg. You can download the same or choose to include your own. But don’t forget to name them post1.jpg, post2.jpg and post3.jpg.

A single flip card

Once the setup is done, let’s first create a single card that flips – with a front face and a back face. The card flip effect shown in the above GIF happens when the element is rotated 180 degrees along the Y-axis. To create the 3D effect, we need a 3D space for that element by adding perspective to its parent. Look at the difference between 2D effect and 3D effect.

How To Create Flip Cards Using CSS - 2D

2D Effect

 
How To Create Flip Cards Using CSS - 3D

3D Effect

 

Do you see that the card actually moves out of its space to give you depth effect in 3D? The CSS property perspective helps us do just that. Let’s say we add perspective:20px to the parent. This gives a depth of 20px to that element. This means, a 3D space is created – so the child elements can be moved near or far or can be rotated to give the 3D effect. Let’s create the markup first.

HTML

We need a parent div to add perspective. And then a child element that contains both the front face and back face absolutely positioned. So add this markup in your index.html within the body tag.

<div class="post-wrap"> <!-- The parent element -->
   <div class="post"> <!-- Child element that flips -->
       <div class="post-front">
           Front face
       </div>
       <div class="post-back">
           Back face
       </div>
   </div>
</div>

CSS

In style.css, begin with some common styles for all elements:

* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
}

Add the following styles to html and body:

html, body {
   width: 100%;
   height: 100%;
}
body{
   background-color: #f7fafc;
   font-family: 'Lato',sans-serif;
   font-size: 1rem;
   color: #444444;
}

To the post-wrap element, add width, height and perspective.

.post-wrap {
   width: 320px;
   height: 420px;
   perspective: 1000px;
}

Imagine this as a box where perspective is the depth of that box. Next, style the .post div to occupy the full space of its parent.

.post {
   position: relative; /* Required to absolutely position the child faces */
   width: 100%;
   height: 100%;
}

Let’s add styles to the two faces.

.post-front, .post-back {
   position: absolute;
   width: 100%;
   height: 100%;
   background-color: white;
}

You will see both of them placed one on top of the other. (You cannot actually see them both. Only the back face is visible. On using the browser inspector tool, you can see that they are positioned on top of each other). But we need the back face to be facing backwards – which means, it needs to be rotated 180 degrees on the Y axis. So add this:

.post-back {
   transform: rotateY(180deg);
}

This is what you will see in your browser now.

How To Create Flip Cards Using CSS - First example

 

So the element has turned backwards but the text still appears – as if it’s a glass. We don’t want the back of the element to appear. For that, we use backface-visibility: hidden;. In Safari browser, this works with a -webkit- prefix. Add these now:

.post-front, .post-back {
   /* Existing styles here */
   -webkit-backface-visibility: hidden;
   backface-visibility: hidden;
}

Now you can only see the front face – just the way we want. Next, we need to rotate the post div when the parent is hovered.

.post-wrap:hover .post {
   transform: rotateY(180deg);
}

If you check your output now, you will see that the card does rotate but we don’t see any animation or 3D effect. That’s because we haven’t added the most important properties required for these – the transition and transform-style properties.

.post {
   /* Existing styles here */
   transition: transform 1s;
   transform-style: preserve-3d;   
}

It’s perfect. We have our flip card ready. It’s time to add our blog post’s content in the markup.

HTML

Add the background image, date and title in the front face.

<div class="post-front">
   <div class="post-img" style="background-image: url('post1.jpg');"></div>
   <div class="post-info">
       <span>June 25, 2020</span>
       <h2>Productivity: Expectations vs Reality</h2>
   </div>
</div>

The title, excerpt and “Read more” button on the back face.

<div class="post-back">
   <div class="post-except">
       <h2>Productivity: Expectations vs Reality</h2>
       <p>
           Et hinc magna voluptatum usu, cum veniam graece et. Ius ea scripserit temporibus, pri cu harum tacimates neglegentur. At adipisci incorrupte nam. Cu qui sumo appareat constituto, possit phaedrum inciderint ex usu, quis ignota cotidieque nam ea. Cum deserunt periculis ocurreret.
       </p>
   </div>
   <a href="#">Read More</a>
</div>

Let’s style this single card.

CSS

Add rounded corners and shadow.

.post-front, .post-back {
   /* Existing styles here */
   border-radius: 10px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

Front face styles.

.post-img {
   background-size: cover;
   background-position: center;
   height: 300px;
   border-top-left-radius: 10px;
   border-top-right-radius: 10px;
}
.post-info {
   padding: 20px 30px 30px;
}
.post-info span {
   font-size: 0.8rem;
   color: #808080;
}
.post-info h2{
   font-weight: bold;
   font-size: 1.2rem;
   padding-top: 5px;
}

Back face styles.

.post-back {
   background-color: #ffffff;
   padding: 30px;
   display: flex;
   flex-direction: column;
   justify-content: space-between; /* To push the read more button to bottom */
   align-items: flex-start; /* To position the read more button at the left */
}
.post-back h2{
   font-weight: bold;
   font-size: 1.2rem;
   padding-top: 5px;
}
.post-back p {
   margin-top: 10px;
   line-height: 1.6;
}
.post-back a{
   text-decoration: none;
   color: #ffffff;
   background-color: #5678ba;
   padding: 10px 14px;
   text-transform: uppercase;
   letter-spacing: 0.05em;
   font-size: 0.8em;
   font-weight: bold;
   border-radius: 5px;
}

This does it. We have our single card perfected. Add two more cards in the markup, wrap all the cards within a flex container and add styles to center them. Below is the markup and CSS for the same.

HTML

<div class="container">
   <div class="post-wrap"> <!-- The parent element -->
       <div class="post"> <!-- Child element that flips -->
           <div class="post-front">
               <div class="post-img" style="background-image: url('post1.jpg');"></div>
               <div class="post-info">
                   <span>June 25, 2020</span>
                   <h2>Productivity: Expectations vs Reality</h2>
               </div>
           </div>
           <div class="post-back">
               <div class="post-except">
                   <h2>Productivity: Expectations vs Reality</h2>
                   <p>
                       Et hinc magna voluptatum usu, cum veniam graece et. Ius ea scripserit temporibus, pri cu harum tacimates neglegentur. At adipisci incorrupte nam. Cu qui sumo appareat constituto, possit phaedrum inciderint ex usu, quis ignota cotidieque nam ea. Cum deserunt periculis ocurreret.
                   </p>
               </div>
               <a href="#">Read More</a>
           </div>
       </div>
   </div>
   <div class="post-wrap">
       <div class="post">
           <div class="post-front">
               <div class="post-img" style="background-image: url('post2.jpg');"></div>
               <div class="post-info">
                   <span>May 19, 2020</span>
                   <h2>Will Artificial Intelligence Rule the World?</h2>
               </div>
           </div>
           <div class="post-back">
               <div class="post-excerpt">
                   <h2>Will Artificial Intelligence Rule the World?</h2>
                   <p>
                       Habemus principes eos id, eu sonet patrioque nam. Eu his mazim insolens, et vim saperet laboramus. Enim gubergren temporibus vix ei. Dicunt iuvaret sadipscing te nam, legere assueverit sed in, at everti labores.
                   </p>
                   <p>
                       Dico facilis dissentias mea cu. Nam assum eripuit an.
                   </p>
               </div>
               <a href="#">Read More</a>
           </div>
       </div>
   </div>
   <div class="post-wrap">
       <div class="post">
           <div class="post-front">
               <div class="post-img" style="background-image: url('post3.jpg');"></div>
               <div class="post-info">
                   <span>July 11, 2020</span>
                   <h2>This Week's Top Stories in Web Design</h2>
               </div>
           </div>
           <div class="post-back">
               <div class="post-except">
                   <h2>This Week's Top Stories in Web Design</h2>
                   <p>
                       Scaevola definitiones eum et. Assum postulant periculis per ei. Doming scribentur sea an. Eum verear docendi tincidunt in.
                   </p>
                   <p>
                       Ne duo posse deserunt, at eam euismod torquatos, est velit essent in. Et diam meliore cotidieque vim. Dicit ignota repudiandae ei pri.
                   </p>
               </div>
               <a href="#">Read More</a>
           </div>
       </div>
   </div>
</div>

CSS

.container {
   max-width: 1200px;
   margin: auto;
   padding: 60px;
   display: flex;
   justify-content: center;
   flex-wrap: wrap; /* Required to position the posts one below the other on smaller devices */
}
.post-wrap {
   /* Existing styles here */
   flex: 1;
   margin: 0 15px 30px;
}

Now the only pending part is to make this responsive. Just change the fixed width of .post-wrap to min-width and max-width instead.

.post-wrap {
   /* Existing styles here */
   min-width: 300px;
   max-width: 380px;
}

And we did it! Resize your browser to see how the posts position themselves on different screen sizes.

How To Create Flip Cards Using CSS - Finished Example

 

In this tutorial, we used the flip card effect for blog posts. You can get creative and use this to display team profiles, portfolio items or anything really. Just in case you didn’t get the expected output, here is the complete source code for you.

 

DOWNLOAD SOURCE CODE

 

Create Simple Parallax Scrolling Effect in Hero Section using Pure CSS

In this tutorial you will learn how to create a simple pure CSS parallax scrolling effect in the hero section of your landing page. Parallax scrolling is an effect where different visual elements on the page move at different speeds when the user scrolls. This creates a 3D effect adding a sense of depth and enhancing the visitor’s experience. This GIF shows what you will be able to create by the end of this tutorial.

Pure CSS Parallax - Example

 

You need to have basic knowledge of HTML and CSS to begin with. We will dive into a few advanced CSS topics such as perspective and transform towards the end. Let’s get started.

We are going to break this tutorial into two parts. In the first part we will be achieving almost the same look and feel of the page except for the parallax effect. That is, there will be no 3D effect. Just simple scrolling. If you already know how to do this, you can quickly rush through Part 1. In the second part, we will learn the advanced CSS concepts required and create the parallax scrolling effect.

Millions of Fonts, Themes, Graphics: Starting at ONLY $16.50 per Month
Web Fonts

Web Fonts
8,000+ Fonts

WordPress Themes

WordPress Themes
1,200+ Themes

Graphic Assets

Graphic Assets
32,000+ Graphics

DOWNLOAD NOW
Envato Elements


Part 1 : Without parallax

Looking at the GIF, you can see that we have a header section with a background image occupying full viewport width and height, followed by a text section. Let us create this step by step.

Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body> 

</body>
</html>

I have used the font ‘Roboto’ for the heading and ‘Lato’ for the paragraphs. So add the following line below the title tag to embed these using Google fonts.

<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300&family=Roboto+Condensed:wght@300;700&display=swap" rel="stylesheet">

Create your stylesheet and name it style.css. Link the stylesheet to your HTML document below the Font Awesome CDN link using

<link rel="stylesheet" href="style.css">

You can download the background image used in the demo from Pexels or choose to include your own. But don’t forget to name it bg.jpg.

HTML

Add the following HTML code within body for the header:

<header>
   <div>
       <h1>Parallax Scrolling Effect</h1>
       <h2>Create this simple parallax effect using pure CSS</h2>
   </div>
</header>

Add the text section below that.

<section>
   <div class="container">
       <h3>Some cool title here</h3>
       <p>
           Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores harum veritatis nemo magni odio reprehenderit atque, esse animi porro suscipit vero nobis modi quis. Exercitationem quasi beatae, assumenda officia illum sunt. Cum voluptas maiores vitae eius hic inventore deleniti placeat perferendis quam ut nostrum maxime optio voluptatibus ab laboriosam, quia consectetur atque minus?
       </p>
       <p>
           Adipisci amet aut sint voluptates delectus aperiam? Veniam ab illum enim in libero nihil culpa explicabo perspiciatis veritatis non repellendus architecto excepturi nostrum porro voluptatem aperiam animi asperiores, a voluptatibus temporibus minima voluptas ipsa! Recusandae nostrum, aut, voluptates est error iusto, eaque excepturi soluta quas maiores amet.

       </p>
   </div>
</section>

Everything else is now taken care of by CSS.

CSS

In style.css, begin with some common styles for all elements:

* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
}

Add these styles to html and body:

html {
   width: 100%;
   height: 100%;
}
body {
   width: 100%;
   height: 100%;
   /* Text styles */
   font-family: 'Lato',sans-serif;
   font-size: 18px;
   font-weight: 300;
   color: #212121;
}

Make the header occupy full viewport width and height.

header {
   width: 100%;
   min-height: 100vh;
   position: relative;
}

Let’s create the ::before pseudo element for header and add the background image.

header::before {
   content: "";
   position: absolute;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   display: block;
   background: url('bg.jpg');
   background-size: cover;
   z-index: 0;
}

You can now see your image occupying full screen. Now let’s bring the text in front and give it the required styling:

header div {
   position: absolute;
   z-index: 1;
   top: 50%;
   padding: 0 30px;
   font-family: 'Roboto Condensed', sans-serif;
}
header h1 {
   font-size: 4.5rem;
   font-weight: 700;
   color: #009688;
}
header h2 {
   font-size: 2.2rem;
   font-weight: 300;
}

You can now see this:

Pure CSS Parallax - So far

Add these to style the text section:

section{
   width: 100%;
   background: white;
}
.container {
   margin: auto; /* To center the text horizontally */
   max-width: 1000px; /* Limiting the width for extra large screens */
   padding: 80px 40px;
}
.container h3 {
   font-family: 'Roboto Condensed', sans-serif;
   font-weight: 700;
   font-size: 3rem;
}
.container p {
   padding-top: 30px;
   line-height: 1.8;
}

So far we haven’t done anything exciting yet. Let’s get to Part 2 where we create the actual magic (with just 8 more lines of CSS).

Part 2 : Adding parallax effect

To create a parallax effect we need to create a sense of depth by introducing a 3rd dimension. The CSS property perspective helps us do just that. Let’s say we add perspective:20px to an element. This gives a depth of 20px to that element. This means, a 3D space is created, and so the child elements can be transformed to make them appear to be positioned near or far from the viewer, creating a sense of depth.

So let’s add perspective to our body element along with overflow properties.

body {
   /* Existing styles here */
   perspective: 4px; /* The depth */
   overflow-x: hidden;
   overflow-y: scroll;
}

The overflow-x is hidden because we do not want any horizontal scrollbar resulting due to the 3D space created.

We also need to set overflow: hidden to the root element.

html {
   /* Existing styles here */
   overflow: hidden;
}

If you check your browser now, nothing has changed yet. It’s because we have just created the 3D space but not transformed any objects within.

The parallax effect happens when two or more elements are placed at different distances from the viewer. For that, we use the CSS transform property and “translate” the objects along the z-axis. So let’s transform the background image and the div within the header.

header::before {
   /* Existing styles here */
   transform: translateZ(-4px);
}
header div {
   /* Existing styles here */
   transform: translateZ(-2px);
}

We are moving the background image 4px away from the viewer and the headings 2px away. So when you scroll down, they seem to move at different speeds. Check your browser now. Still nothing right?

When we want the objects to be transformed in a 3D space, we need an additional transform-style property. This property when applied to an element, determines if that element’s children are positioned in 3D space, or flattened.

To understand perspective, transforms and all this in more depth, you can refer to the detailed guide to 3D transforms with CSS.

For now, add this property to header:

header {
   /* Existing styles here */
   transform-style: preserve-3d;
}

Now look at the result in your browser. Surprised to see that your background image and headings have shrunk in size? Keeping that aside for a moment, scroll down and you will see that the parallax effect is actually created! Why did these two elements shrink? It’s because they have moved farther away from you, remember? Objects that move farther appear smaller. Simple. But how to fix this? There’s a scale factor to be added along with translateZ to correct the size. This Google article gives us a formula to calculate the scale to apply.

scale = (perspective - distance) / perspective

For our background image, perspective is 4px and distance (translateZ) is -4px. Calculate:

scale = (4 - (-4))/4 = 8/4 = 2

Similarly, for header div, the scale is 1.5. Let’s include these. Change the transform properties of both the elements to include scale.

header::before {
   transform: translateZ(-4px) scale(2);
}
header div {
   transform: translateZ(-2px) scale(1.5);
}

This fixes it. Now scroll down. Do you see the effect? The only issue is that our text section is being overlapped by the header. The solution to this is to set a higher z-index to the section (along with a position property, otherwise z-index won’t work).

section{
   /* Existing styles here */
   position: relative;
   z-index: 2;
}

And there it is! A simple neat parallax scrolling effect for our hero section is achieved.

Extend this newly acquired skill and go create beautiful, pure CSS parallax scrolling websites. But be careful not to overdo it. If you got stuck somewhere in between and couldn’t achieve the desired output, here’s the complete source code.\

DOWNLOAD SOURCE CODE

 

How To Create a Responsive Dropdown Navigation Using Only CSS

This tutorial will guide you through creating a responsive dropdown navigation using CSS only, with the help of CSS flexbox and the “checkbox hack”. Basic knowledge of HTML and CSS is required to follow along.

The top navigation bar is vital for any website. Most of the sites have a similar structure for a dropdown navigation menu, but differ in their styles and implementation. Here is one implementation that can be used universally – since it is responsive and doesn’t need JavaScript to toggle the dropdown on mobile devices. Also, we use the “mobile-first” approach to build this. Here is what you will learn to create by the end of this tutorial.

CSS Responsive Dropdown Navigation

Desktop view - CSS Responsive Dropdown Navigation

Let’s get started.

Millions of Fonts, Themes, Graphics: Starting at ONLY $16.50 per Month
Web Fonts

Web Fonts
8,000+ Fonts

WordPress Themes

WordPress Themes
1,200+ Themes

Graphic Assets

Graphic Assets
32,000+ Graphics

DOWNLOAD NOW
Envato Elements


Mobile First

We will be following the “mobile-first” approach which involves designing a website starting with the mobile version first and then proceeding to design for larger screens. Read more about why mobile-first approach is important in 2020.

Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
  
</body>
</html>

I have used ‘Font Awesome’ for the hamburger menu icon on the right top. So add the following line below the title tag to be able to use this font.

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" rel="stylesheet">

Create your stylesheet and name it styles.css. Link the stylesheet to your HTML document below the Font Awesome CDN link using

<link rel="stylesheet" href="styles.css">

I have used this below image as a logo. You can save the same as logo.png or choose to include your own.

logo - CSS Responsive Dropdown Navigation

HTML

Add the following HTML code within body

<header class="menu">
   <div class="menu-wrap">
       <img src="logo.png" class="logo-img" alt="Logo">
       <nav>
           <ul>
               <li><a href="#">Home</a></li>
               <li><a href="#">About</a></li>
               <li><a href="#">Services</a></li>
               <li><a href="#">Contact</a></li>
           </ul>
       </nav>
       <i class="fa fa-bars menu-icon"></i>
   </div>
</header>

We have a header element which will form the dark navigation bar containing everything else. There is a menu-wrap div which acts as the container for the logo, navigation links and the menu icon. You will not see anything great if you open up this file in your browser yet. So, let’s add some CSS.

CSS

In your styles.css, begin with some common styles for all elements:

* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
   font-family: sans-serif;
}

Add these styles to the header element.

header {
   height: 70px;
   background-color: #22292F;
   padding: 10px 0;
}

You will now see that dark navigation bar stretching the full width of the browser.

Before you proceed further, make sure you view this page in responsive mode in your browser and select any mobile device size – because we are designing for mobile first.

Now, add these styles to the menu-wrap class:

.menu-wrap {
   display: flex;
   justify-content: space-between;
   padding: 0 15px;
}

We use display:flex to make all the child elements occupy the free space available horizontally. The property justify-content is set to space-between to stretch those elements as far apart as possible.

Let’s style each of those child elements one by one.

.logo-img {
   height: 50px;
}
.menu-icon {
   font-size: 2.4em;
   color: #ffffff;
   line-height: 50px;
}

With this, we have the logo and icon in the perfect positions with correct sizes. Coming to the menu links – we need to absolutely position the whole menu below the bar on mobile phones. First add:

nav {
   position: absolute;
   background-color: #3D4852;
   top:70px;
   left:0;
   width: 100%;
}

Now style the list and links:

nav ul {
   list-style-type: none;
}
nav ul li {
   padding: 0 15px;
}
nav ul li a {
   display: inline-block;
   padding: 12px;
   /* Add your custom styles below to change appearance of links */
   color: #DAE1E7;
   text-decoration: none;
   letter-spacing: 0.05em;
}

Also add the hover and focus styles for links:

nav ul li a:hover, nav ul li a:focus {
   color: #eb6f4a;
}

You should now be able to see this:

Preview 1 - CSS Responsive Dropdown Navigation

This menu should be hidden at first, and appear on click of the icon. So add these additional styles max-height, overflow and transition too, to the nav ul element:

nav ul li a:hover, nav ul li a:focus {
   color: #eb6f4a;
}

This will hide the entire menu because max-height is 0 and overflow is hidden. The reason we don’t use display:none for hiding the menu is because we need the animation effect of the menu sliding down – the dropdown effect – which can only be achieved by using the max-height property.

The “checkbox hack”

What is this “checkbox hack”? This is the most important part of this tutorial. Read carefully.

Now we need to toggle the menu display using only CSS – no JavaScript. Best way to do that is by using a hidden checkbox element. We use the hamburger icon as the label for this checkbox element. Once the label is clicked, the checkbox gets checked, and hence we can use the “:checked” pseudo-class selector to display the menu!

Reading this might have been an “Aha!” moment for you or it might have left you even more confused. Either way, let us look at the implementation.

HTML

In index.html, add a checkbox element before the nav element:

<input type="checkbox" id="checkbox">

NOTE: It’s really important to add it before the nav, and not after. Because CSS has a selector for the next sibling, but not the previous sibling. You will understand this soon.

Also, surround the menu-icon with a label

<label for="checkbox">
   <i class="fa fa-bars menu-icon"></i>
</label>

Here, for=”checkbox” makes sure that the checkbox gets checked / unchecked whenever this label is clicked.

CSS

We need to first hide the checkbox. In styles.css, add this:

#checkbox {
   display: none;
}

Here comes the heart of the code:

#checkbox:checked ~ nav ul {
   max-height: 200px;
   padding: 15px 0;
   transition: all 0.5s;
}

The ~ symbol is the general sibling selector – which separates two selectors (#checkbox:checked and nav ul) and matches the second element only if it follows the first element. Understand the general sibling selector better with some examples here. This means, when the checkbox is checked, the menu slides down because max-height goes from 0 to a large number.

This is it! If you got everything right, clicking on the hamburger icon now makes your menu slide up and down. Neat.

11,000+
Icons
20,000+
Illustrations
Envato Elements

DOWNLOAD NOW
14,000+
UI & UX Kits
16,000+
Web Templates

For larger screens

We surely don’t want the hamburger icon on larger screens where there’s enough space for the links to appear directly.

Larger Screens - CSS Responsive Dropdown Navigation

Let’s add some media queries for tablet size and above, to display the links directly, in place of the menu icon. In styles.css, add this media query:

@media (min-width: 768px) {
}

Within this, first hide the menu icon

@media (min-width: 768px) {
  .menu-icon {
     display: none;
  }
}

Make sure to increase the screen size in your browser to something larger than 768px in width, to see the changes next.

Now, add styles to relatively position the nav element and change its background color. Then add display:inline-flex for nav ul li to place the links next to each other.

@media (min-width: 768px) {
  nav {
    position: relative;
    top:-10px;
    background-color: transparent;
  }
  nav ul {
    max-height: 70px;
    padding: 15px 0;
    text-align: right;
  }
  nav ul li {
    display: inline-flex;
    padding-left: 20px;
  }
}

There you go.

Congratulations! You now know how to create a responsive dropdown navigation that displays the menu links on the nav bar for larger screens, while displaying a hamburger icon for smaller screens where the icon can be toggled to display / hide the menu using pure CSS. Your newly-learned “checkbox hack” can be put to use in other places too!

If you got stuck anywhere and couldn’t achieve the expected output, here’s the complete source code. Go and implement this dropdown navigation on the awesome websites you now create.

DOWNLOAD SOURCE CODE

 

How To Add reCAPTCHA v3 to PHP Form and Submit Using Ajax

In this tutorial, we will add Google reCAPTCHA v3 to a PHP form and submit it without leaving the page, using Ajax. If you have had a contact form or any such form on your website, you know how annoying it is to receive spam messages from bots. Google reCAPTCHA protects you from spam and other automated abuse. To follow along this tutorial, you need to have some basic knowledge of HTML, jQuery and PHP.

Millions of Fonts, Themes, Graphics: Starting at ONLY $16.50 per Month
Web Fonts

Web Fonts
8,000+ Fonts

WordPress Themes

WordPress Themes
1,200+ Themes

Graphic Assets

Graphic Assets
32,000+ Graphics

DOWNLOAD NOW
Envato Elements


Why Google reCAPTCHA v3?

We have all had the frustrating experience of trying to quickly submit some information through a form only to be faced by a Captcha challenge in the end. We’ve had to type in random characters and wondered, “Is that two Vs or a W?”, “Should I add that space or not?”.

Google Recaptcha

And then we’ve had to select all the images that have zebra crossing or bridges to prove that we are humans. Thankfully, these days, a lot of websites have added Google reCAPTCHA v2 which just displays a checkbox – “I’m not a Robot”.

Google reCAPTCHA v2

However, in 2018, Google released the next version – reCAPTCHA v3 which doesn’t need any user interaction at all. It works behind the scenes observing the user’s behavior. This version provides us (developers) with a score that indicates how suspicious an interaction is. We could use that score and prevent spam. Read how it works at Google’s official webmaster blog.

Now let’s learn how to add this to a simple form.

Register reCAPTCHA v3 keys

You need to first register your website and get the keys here –  https://www.google.com/recaptcha/admin/create. Add a label, select reCAPTCHA v3, type your domain name(s) and submit.

Google reCAPTCHA v3

This will generate a “site key” and a “secret key”. Copy both and keep them safe. We will need them soon.

HTML Form

Let’s take a simple contact form with Full name, Email and Message fields

Contact Form without Google reCAPTCHA

The HTML

For the sake of simplicity of this tutorial, only the HTML code is displayed below. For CSS used in the above screenshot, download the full source code at the end of this tutorial.

<form id="contact-form" method="post">
   <p class="label">Full Name *</p>
   <input type="text" name="name" placeholder="Full Name" required>
   <p class="label">Email *</p>
   <input type="email" name="email" placeholder="Email" required>
   <p class="label">Message *</p>
   <textarea name="message" rows="6" placeholder="Type your message here" required></textarea>
   <!-- A hidden div “alert” below to display the message received from server once form is submitted-->   
   <div id="alert"></div>
   <button id="submit-button" type="submit">Send Message</button>
</form>

Ajax Form Submission

Let’s work on the form submission using Ajax before we add the reCAPTCHA, for which we need the jQuery library. Load it using a CDN. Paste this line before the closing body tag in your HTML.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

 

We need to make the Ajax request on form submission.

<script>
   $('#contact-form').submit(function(event) {
       event.preventDefault(); // Prevent direct form submission
       $('#alert').text('Processing...').fadeIn(0); // Display "Processing..." to let the user know that the form is being submitted
       $.ajax({
           url: 'contact.php',
           type: 'post',
           data: $('#contact-form').serialize(),
           dataType: 'json',
           success: function( _response ){
               // The Ajax request is a success. _response is a JSON object
               var error = _response.error;
               var success = _response.success;
               if(error != "") {
                   // In case of error, display it to user
                   $('#alert').html(error);
               }
               else {
                   // In case of success, display it to user and remove the submit button
                   $('#alert').html(success);
                   $('#submit-button').remove();
               }
           },
           error: function(jqXhr, json, errorThrown){
               // In case of Ajax error too, display the result for demo purpose
               var error = jqXhr.responseText;
               $('#alert').html(error);
           }
       });
   });
</script>

 

With this code, if you hit “Submit”, you will get a 404 error displayed because contact.php doesn’t exist yet. Let’s do that next.

11,000+
Icons
20,000+
Illustrations
Envato Elements

DOWNLOAD NOW
14,000+
UI & UX Kits
16,000+
Web Templates

PHP

Create contact.php. On the server side, we need to validate the data received and send a JSON response. We will integrate reCAPTCHA in a while.

<?php

// Server side validation
function isValid() {
   // This is the most basic validation for demo purposes. Replace this with your own server side validation
   if($_POST['name'] != "" && $_POST['email'] != "" && $_POST['message'] != "") {
       return true;
   } else {
       return false;
   }
}

$error_output = '';
$success_output = '';

if(isValid()) {
   $success_output = "Your message sent successfully";
} else {
   // Server side validation failed
   $error_output = "Please fill all the required fields";
}

$output = array(
   'error'     =>  $error_output,
   'success'   =>  $success_output
);

// Output needs to be in JSON format
echo json_encode($output);

?>

 

Perfect! We have the complete flow of form submission using Ajax. Now it’s time to integrate reCAPTCHA v3 and you will see how simple it really is, if you carefully follow along.

Client Side Integration

First step is to load the JavaScript API with your sitekey. Paste this below your jQuery CDN link.

<script async src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY_HERE"></script>

IMPORTANT: Replace YOUR_SITE_KEY_HERE with the site key that you copied earlier.

If you look at the reCAPTCHA v3 docs, we need to call the grecaptcha.execute on each action we wish to protect. In our case, it is the form submission. This call generates a token, which needs to be sent along with our form data to be verified on the server side. Best way to do that is to include a hidden input field in our form like this and dynamically assign the token value to this field:

<input type="hidden" name="recaptcha_response" id="recaptchaResponse">

 

Call this below function just outside of the Ajax request and populate the hidden input field with token value. This will automatically include the token value along with other form data when the Ajax request is made.

grecaptcha.ready(function () {
   grecaptcha.execute('YOUR_SITE_KEY_HERE', { action: 'contact' }).then(function (token) {
      var recaptchaResponse = document.getElementById('recaptchaResponse');
      recaptchaResponse.value = token;
      // Make the Ajax call here
   });
});

IMPORTANT: Replace YOUR_SITE_KEY_HERE with the site key that you copied earlier.

The ‘action’ value is specific to this action of contact form submission. Different actions help you analyse data all over your website when you add reCAPTCHA in multiple places.

NOTE: reCAPTCHA tokens expire every two minutes. Which is why, we need to generate this token only after the user clicks on the submit button and just before we make the Ajax request.

This completes client side integration.

Server Side Integration

Once we validate the data (Name, Email and Message) on the server-side, we need to fetch the score from Google to verify if it’s a human interaction or not. Inside the if(isvalid()){ } block, add the below code to make the API request to get the score.

// Build POST request to get the reCAPTCHA v3 score from Google
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_secret = 'YOUR_SECRET_KEY_HERE'; // Insert your secret key here
$recaptcha_response = $_POST['recaptcha_response'];

// Make the POST request
$recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response);

IMPORTANT: Replace YOUR_SECRET_KEY_HERE with the secret key that you copied earlier. Secret key is for server-side only.

The response received is a JSON object.

{
"success": true|false, // whether this request was a valid reCAPTCHA token for your site
"score": number // the score for this request (0.0 – 1.0)
"action": string // the action name for this request (important to verify)
"challenge_ts": timestamp, // timestamp of the challenge load (ISO format yyyy-MM-dd’T’HH:mm:ssZZ)
"hostname": string, // the hostname of the site where the reCAPTCHA was solved
"error-codes": […] // optional
}

 

Let’s decode the JSON object $recaptcha and check for success, score and action. Score varies from 0.0 to 1.0. By default, you can use a threshold of 0.5.

$recaptcha = json_decode($recaptcha);
// Take action based on the score returned
if ($recaptcha->success == true && $recaptcha->score >= 0.5 && $recaptcha->action == 'contact') {
   // This is a human. Insert the message into database OR send a mail
   $success_output = "Your message sent successfully";
} else {
   // Score less than 0.5 indicates suspicious activity. Return an error
   $error_output = "Something went wrong. Please try again later";
}

 

You’re all set! Hit that Submit button, and if you integrated everything correctly, you should see a response that your message was sent successfully.

success message

Bonus tip:

Once you added the javascript API, you might have noticed an annoying reCAPTCHA badge at the bottom right corner of your page that looks like this.

Google reCAPTCHA badge

This might not go well with your website design. Guess what? This FAQ here says that you are allowed to hide this badge provided you include the following text in the user flow

This site is protected by reCAPTCHA and the Google
   <a href="https://policies.google.com/privacy">Privacy Policy</a> and
   <a href="https://policies.google.com/terms">Terms of Service</a> apply.

 

So add this within a p element below your “Submit” button.

reCAPTCHA message

Now, to actually hide the badge, just add this into your CSS.

.grecaptcha-badge {
   visibility: hidden;
}

 

Congratulations! You have successfully set up Google reCAPTCHA v3 into your form. Now you will receive messages only from humans – without them having to face a Captcha challenge AND without leaving the page.

Download full source code here.

 

DOWNLOAD SOURCE CODE

 

Pure CSS Animation of Blog Post Excerpt on Hover

In this tutorial, we’ll make this cool animation of revealing the blog post excerpt on hover using pure CSS and no JavaScript. The GIF below shows what you will be able to create by the end of this. You should have basic knowledge of HTML and CSS to follow the tutorial.

 

Pure CSS Animation

 

This is a simple and neat animation that can be used on a page that lists blog posts. Each post on the list (or grid) shows only the featured image with the title at first. When you hover anywhere on the image, the background zooms in and the title slowly moves up revealing the excerpt, a “read more” link, the published date and time to read. Let’s get started!

Your Web Designer Toolbox

Unlimited Downloads: 500,000+ Web Templates, Icon Sets, Themes & Design Assets
Starting at only $16.50/month!


Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
  
</body>
</html>

Create your stylesheet and name it styles.css. Link the stylesheet to your HTML document below the <title> tag using

<link rel="stylesheet" href="styles.css" type="text/css">

I have used ‘Lato’ font for the text and ‘Font Awesome’ for the icons. So add the following two lines below the title tag, before your stylesheet line to be able to use these fonts.

<link href="https://fonts.googleapis.com/css2?family=Lato&display=swap" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" rel="stylesheet">

HTML & CSS

Each developer has a different way of working. Some developers create the complete HTML first and then get started with CSS. However I prefer to do both simultaneously because it helps me see the result taking shape bit by bit. To make it easier for you, I’ve split the next process into two parts.

Part 1

In the first part, we will achieve these:

  1. Create a blog post item
  2. Set the background image
  3. Zoom the image on hover
  4. Add a dark background overlay on the image which darkens more on hover

HTML

First add a div within the opening and closing body tags with a class "wrapper". This acts as a container. Within that comes a single blog post item in an article tag. Give it a class name "post".

<div class="wrapper">
   <article class="post">
      
   </article>
</div>

The background image cannot be added to this article element directly because we need to apply the zoom effect. Hence let’s create an empty div inside the article just for this.

<div class="post-bg"></div>

If you open this up on your browser, you will see nothing yet! So, it’s time for some CSS.

CSS

Add these basic styles into styles.css:

body{
   font-family: 'Lato',sans-serif;
   line-height: 1.5;
}
a{
   color: #fff;
   text-decoration: none;
}
a:hover{
   color: #b1fffa; /* A bright green color */
}
.wrapper{
   margin: auto; /* This is to center the content on page */
   width: 1100px; /* You can change this value for smaller screens using media queries */
   padding: 40px;
}

Next, add styles to the article element:

article.post{
   position: relative;
   width: 515px; /* You can change this value for smaller screens using media queries */
   height: 450px; /* Height is required */
   overflow: hidden;
}

The position property needs to be set because we will be absolutely positioning its child elements – the title, excerpt and other text. overflow: hidden is to make sure that this block doesn’t expand when the child background div is transformed to give the zoom effect. You will understand this in just a minute.

We need to now add styles to the div we placed for our background image.

.post-bg{
   width: 100%;
   height: 100%;
   background-image: url('https://images.pexels.com/photos/267569/pexels-photo-267569.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260');
   background-position: center;
   background-size: cover;
   transition: all .7s;
}

I have used a direct link of an image from pexels.com. You can use your own image. The CSS transition property is used to set the properties that need to animate (in our case it is all) and the time for transition ( we have set it to 0.7 seconds). Refer to CSS transitions on w3schools.com for a more detailed explanation.

Here comes the code snippet used for the zoom effect:

.post:hover .post-bg,
.post:focus .post-bg {
   transform: scale(1.1);
}

Now check your browser. And if you got everything right, you will see the blog post image and when you take your mouse on it, the image zooms.

Pure CSS Animation of Blog Post Excerpt on Hover

As you can see in the CSS above, we are actually just increasing the size (using transform) of .post-bg div by 1.1 times when it’s parent element is hovered/focused. But since the parent’s overflow property is set to hidden, you feel the image is being zoomed.

Next, if you observe carefully, there’s a dark background overlay over this image. And on mouse hover, the overlay darkens further. To add this overlay, we need to use ::after to create a pseudo element and give styles as follows.

.post-bg::after {
   content: '';
   background: rgba(0, 0, 0, 0.5);
   width: 100%;
   height: 100%;
   position: absolute;
   top: 0;
   left: 0;
   transition: all .7s;
}

The position:absolute along with width and height of 100% makes this pseudo element cover the image completely. The background color is black with 0.5 opacity. Again, the transition property is for animation.

Add the below code to increase the opacity when the parent element .post is hovered/focused.

.post:hover .post-bg::after,
.post:focus .post-bg::after {
   background: rgba(0, 0, 0, 0.7);
}

Opacity of 0.5 is changed to 0.7. This works!

Part 2

We have our background all set. Now let’s achieve the following:

Add the title, excerpt, read more link, published date and time to read

Place the above elements in their respective positions

Display only the title in the center at first (Hide the other elements)

Animate the title and reveal the other elements simultaneously

HTML

After the .post-bg div, let’s add all the required elements. The HTML part is mostly self-explanatory.

<h2 class="post-title">
   <a href="#">Pure CSS Animation of Blog Post Excerpt on Hover</a>
</h2>
<p class="post-excerpt">
   The excerpt of your post that compels the user to click on "Read More" link below
</p>
<a class="post-read-more" href="#">
Read More
<i class="fa fa-arrow-right"></i>
</a>
<div class="post-date-time">
   <span class="post-icon-text">
      <i class="fa fa-calendar"></i>
      June 1, 2020
   </span>
   <span class="post-icon-text">
      <i class="fa fa-clock"></i>
      8 Minutes Read
   </span>
</div>

If you check your browser now, you cannot see any changes at all. Where have all the elements gone? You can use the inspector tool of your browser and check. They have been pushed down by the .post-bg div and are not visible because the overflow property of .post is set to hidden. Let’s work on the CSS.

CSS

The best way to get each of these in place is by setting position property to absolute and using the top, left and right properties for alignment.

.post-title, .post-excerpt, .post-read-more, .post-date-time {
   position: absolute;
   top: 20%;
   left: 8%;
   right: 8%;
   text-align: center;
   overflow: hidden;
}

Of course, now you will see that everything overlaps. Let’s give different values to top property and space them out correctly – the way we want to see them once revealed.

.post-title{
   top: 15%;
}
.post-excerpt{
   top: 46%;
}
.post-read-more{
   top: 67%;
}
.post-date-time{
   top: 80%;
}

This sets the position of elements, but we need some additional styling to get the font sizes and spacing right. Replace the above code with this:

.post-title{
   top: 15%;
   max-height: 120px; /* This is to make sure that longer titles are truncated */
}
.post-title a{
   font-size: 1.4em;
   line-height: 1;
}
.post-excerpt{
   top: 46%;
   max-height: 82px; /* This is to make sure that longer excerpts are truncated */
   font-size: 1.1em;
}
.post-excerpt:after{
   content: '...';
}
.post-read-more{
   top:67%;
   font-weight: bold;
   font-size: 1.1em;
}
.post-date-time{
   top: 80%;
   font-size: 0.8em;
}
.post-icon-text {
   padding: 0 10px;
}
i.fa{
   padding: 0 5px;
}

This looks perfect!

Pure CSS Animation of Blog Post Excerpt on Hover

Let’s hide all the elements except for the title, simply by setting the opacity to 0.

.post-excerpt, .post-read-more, .post-date-time {
   opacity: 0;
}

Change the top value of .post-title to 35% – to make it appear in the center. Also, the top value of .post-date-time to 90% because the date and time slide up from bottom.

You have come really far! The only part remaining now is the actual animation – which is simple. First, set the transition property to all the four elements:

.post-title, .post-excerpt, .post-read-more, .post-date-time {
   transition: all 0.5s;
}

Now let’s set the properties of each element on hover.

The top property of .post-title on .post hover

.post:hover .post-title{
   top: 15%;
}

The opacity of .post-excerpt and .post-read-more

.post:hover .post-excerpt, .post:hover .post-read-more{
   opacity: 1;
}

The top and opacity properties of .post-date-time

.post:hover .post-date-time{
   top: 80%;
   opacity: 1;
}

And there you go! You did it.

You now know how to create a zoom effect on a background image, how to add an overlay on a background image, and how to animate various elements using pure CSS animation. Just in case you didn’t get the expected output, I’ve got you covered. Download the full source code here and compare yours with this one.

Source Code