Learn how to create an engaging Morphing Submit Button using HTML, CSS, and JavaScript for your web forms.
Table of Contents
A Morphing Submit Button is a type of button used in web forms that changes its shape, size, or color when the user interacts with it, providing a more engaging and interactive user experience. It can be achieved using HTML, CSS, and JavaScript, and can be customized to fit the look and feel of any website. By enhancing the design and interactivity of web forms, Morphing Submit Button can help to improve user engagement and increase conversions.
Let's start making an amazing Morphing Submit Button Using HTML, CSS, and Vanilla JavaScript step by step.
Prerequisites:
Before starting this tutorial, you should have a basic understanding of HTML, CSS, and JavaScript. Additionally, you will need a code editor such as Visual Studio Code or Sublime Text to write and save your code.
Source Code
Step 1 (HTML Code):
To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our morphing button.
The button element has a class of btn and a type of button. Inside the button
element, there is a span element with a class of btn__text
that contains the text Submit.
Next, there is an SVG element with a class of btn__progress
that creates the progress indicator. It has two circle elements inside it, one with a class of btn__progress-track
and another with a class of btn__progress-fill
. The btn__progress-track
circle creates a gray circle with a stroke width of 8. The btn__progress-fill
circle creates a black circle with a stroke width of 8 and a dash array and dash offset that create the animation effect.
Finally, there is a polyline element with a class of btn__progress-check
that creates a checkmark when the progress is complete. It has a stroke width of 4 and a dash array and dash offset that create the animation effect.
After creating the files just paste the below codes into your file. Make sure to save your HTML document with a .html extension, so that it can be properly viewed in a web browser.
This is the basic structure of our morphing button using HTML, and now we can move on to styling it using CSS.
Step 2 (CSS Code):
Once the basic HTML structure of the button is in place, the next step is to add styling to the submit button using CSS.
Next, we will create our CSS file. In this file, we will use some basic CSS rules to create our morphing effect.
The below CSS code block defines the styling for a button element. It includes several CSS properties that define the appearance and behavior of the button. Here's a breakdown of what the code does:
The first rule selects all elements and sets their border, box-sizing, margin, and padding to zero, which is a common CSS reset to ensure consistent styling across different browsers and devices.
The :root
selector sets some custom CSS variables, which can be used throughout the stylesheet to define colors, sizes, and other values. The --hue variable is set to 223, which is a hue value in the HSL color space. The other variables are defined using this hue value and specify different shades of the primary color, a font size that adjusts to the viewport width, and other styling options.
The body
and button
selectors set the font to Nunito, a sans-serif font, with a font size of 1em and a line height of 1.5em.
The body
selector sets the background color, text color, height, and grid display properties, which center the button on the screen.
The .btn
selector defines the main styles for the button, including transparent background color, rounded corners, and a width and height of 7.5em and 3em, respectively. It also sets a transition effect for the button width when it's hovered over or clicked.
The .btn__text
selector styles the text inside the button, setting a background color that corresponds to the primary color defined earlier, white text color, and rounded corners that inherit the border radius of the parent element. It also sets a transition effect for the background color and text color when the button is hovered over or clicked.
The .btn__progress
selector defines an SVG element that will display a progress circle when the button is clicked. It's initially hidden and positioned on top of the button using absolute positioning.
The .btn__progress-track
selector styles the outer ring of the progress circle, setting its stroke color, stroke width, and radius.
The .btn__progress-fill
selector styles the progress circle itself, setting its stroke color, stroke width, stroke-dasharray, and stroke-dashoffset. These properties are used to animate the progress circle and create a spinning effect when the button is clicked.
The .btn__progress-check
selector defines a polyline that creates a checkmark shape inside the progress circle when the button animation is complete.
The .btn--running
and .btn--done
selectors define styles for the button when it's in the running or done state, respectively. These states are used to control the animation and visibility of the progress circle and checkmark.
The @media (prefers-color-scheme: dark)
selector defines a dark theme for the button by adjusting the background and text colors using the --bg1, --bg2, --fg1, and --fg2 variables. This theme is applied when the user's device is set to a dark color scheme.
This will give our morphing button an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--hue: 223;
--bg1: #cebfbf;
--bg2: hsl(var(--hue),10%,80%);
--fg1: hsl(var(--hue),10%,10%);
--fg2: hsl(var(--hue),10%,20%);
--primary1: hsl(var(--hue),90%,55%);
--primary2: hsl(var(--hue),90%,45%);
font-size: calc(20px + (40 - 20) * (100vw - 320px) / (1280 - 320));
}
body, button {
font: 1em/1.5 Nunito, sans-serif;
}
body {
background-color: var(--bg1);
color: var(--fg1);
height: 100vh;
display: grid;
place-items: center;
}
/* Main button styles */
.btn {
background-color: transparent;
border-radius: 1.5em;
display: block;
position: relative;
width: 7.5em;
height: 3em;
transition: width 0.3s ease-in-out;
}
.btn:not(:disabled):active {
transform: translateY(0.1em);
}
.btn__text {
background-color: var(--primary1);
border-radius: inherit;
color: hsl(0,0%,100%);
display: inline-block;
padding: 0.75em 1.5em;
transition:
background-color 0.15s linear,
color 0.15s 0.3s ease-in-out;
width: 100%;
}
.btn:not(:disabled):focus .btn__text,
.btn:not(:disabled):hover .btn__text {
background-color: var(--primary2);
}
.btn__progress {
overflow: visible;
position: absolute;
top: 0;
left: 0;
width: 3em;
height: 3em;
visibility: hidden;
}
.btn__progress-track {
r: 12px;
stroke: var(--bg2);
stroke-width: 24;
}
.btn__progress-fill {
stroke: var(--primary1);
stroke-dashoffset: 125.66;
}
.btn__progress-check {
stroke: hsl(0,0%,100%);
stroke-dashoffset: 34;
}
/* Both states */
.btn--running,
.btn--done {
outline: none;
pointer-events: none;
width: 3em;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
.btn--running .btn__text,
.btn--done .btn__text {
color: transparent;
transition:
background-color 0.3s ease-in-out,
visibility 0.3s steps(1);
}
.btn--running .btn__progress,
.btn--done .btn__progress {
visibility: visible;
}
/* Running state */
.btn--running .btn__text {
background-color: var(--bg2);
visibility: hidden;
}
.btn--running .btn__progress {
transition: visibility 0.3s 0.3s steps(1,start);
}
.btn--running .btn__progress-track {
r: 20px;
stroke-width: 8;
transition:
r 0.3s 0.3s ease-in-out,
stroke-width 0.3s 0.3s ease-in-out;
}
.btn--running .btn__progress-fill {
stroke-dashoffset: 0;
transition: stroke-dashoffset 2s 0.6s linear;
}
/* Done state */
.btn--done .btn__progress-track {
stroke: var(--primary1);
transition:
r 0.3s ease-in-out,
stroke-width 0.3s ease-in-out;
}
.btn--done .btn__progress-check {
stroke-dashoffset: 0;
transition: stroke-dashoffset 0.3s 0.3s ease-out;
}
/* Dark theme */
@media (prefers-color-scheme: dark) {
:root {
--bg1: hsl(var(--hue),10%,10%);
--bg2: hsl(var(--hue),10%,20%);
--fg1: hsl(var(--hue),10%,90%);
--fg2: hsl(var(--hue),10%,80%);
}
}
Step 3 (JavaScript Code):
Finally, we need to add JavaScript to our button.
The JavaScript code adds an event listener to the DOMContentLoaded
event of the window object. When the DOM has loaded, it selects the first button element on the page and attaches a click event listener to it. When the button is clicked, the following happens:
- The button is disabled and given a
btn--running
class to indicate that the submission process has started. - Two timeouts are cleared to ensure that they don't interfere with the current submission process.
- A new timeout is created that simulates a submission process that takes
submitDuration
milliseconds (2 seconds) to complete. - After 600ms, the
btn--running
class is removed and replaced with abtn--done
class to indicate that the submission process is complete. - Another timeout is created to reset the button after
resetDuration
milliseconds (1.5 seconds). The disabled property is set back to false, and the btn--done class is removed.
The purpose of this code is to simulate a button click that triggers a submission process, and then visually indicates that the submission process has been completed successfully. The setTimeout()
function is used to create a fake delay to simulate the submission process, and then to add a delay between the end of the submission process and the resetting of the button.
Create a JavaScript file with the name script.js and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.
window.addEventListener("DOMContentLoaded",() => {
const btn = document.querySelector("button");
var doneTimeout = null,
resetTimeout = null;
if (btn) {
btn.addEventListener("click",function() {
const runClass = "btn--running";
const doneClass = "btn--done";
// `.btn--running .btn__progress-fill` `stroke-dashoffset` duration in ms
const submitDuration = 2000;
const resetDuration = 1500;
// fake the submission
this.disabled = true;
this.classList.add(runClass);
clearTimeout(doneTimeout);
clearTimeout(resetTimeout);
doneTimeout = setTimeout(() => {
this.classList.remove(runClass);
this.classList.add(doneClass);
// reset the button
resetTimeout = setTimeout(() => {
this.disabled = false;
this.classList.remove(doneClass);
}, resetDuration);
}, 600 + submitDuration);
});
}
});
Final Output:
Conclusion:
Congratulations, you've created a Morphing Submit Button with HTML, CSS, and JS! You can now add this button to your web forms and enhance the user experience of your website. Feel free to experiment with different colors, shapes, and transitions to create your own version of the button.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊