This blog post walks you through creating a visually appealing and interactive neumorphic button with a progress bar using HTML, CSS, and JavaScript. Here’s a detailed explanation of each component:
Key Features of the Button
- Neumorphic Design:
- A soft, modern 3D effect created using CSS shadows.
- Mimics a subtle “popping out” style, giving the button a sleek appearance.
- Progress Bar with Water-Filling Effect:
- The progress bar animates like water filling the button from bottom to top.
- The height of the progress bar dynamically changes based on the simulated progress percentage.
- Dynamic Progress Text:
- The percentage displayed updates in real-time as the progress bar fills.
- Once the upload completes, the button resets automatically.
- Interactive Hover Effect:
- The button slightly enlarges when hovered over, enhancing interactivity.

Project Structure
- HTML File (
index.html
): Contains the structure of the button and includes links to the CSS and JavaScript files. - CSS File (
style.css
): Manages the styling for the neumorphic button and the progress bar. - JavaScript File (
script.js
): Implements the logic for progress simulation and dynamic updates.
HTML Structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Progress Bar Button</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="upload-container">
<input type="file" id="fileInput" style="display: none;">
<div class="neumorphic-btn" id="uploadBtn">
<div class="progress-text" id="progressText">Upload File</div>
<div class="progress-bar-fill"></div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS for Styling
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #F4F7FF;
font-family: 'Arial', sans-serif;
}
.upload-container {
display: flex;
flex-direction: column;
align-items: center;
}
/* Neumorphic Button */
.neumorphic-btn {
width: 250px;
height: 60px;
background: #e0e0e0;
border-radius: 30px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
box-shadow: 7px 7px 14px #bebebe, -7px -7px 14px #ffffff;
overflow: hidden;
cursor: pointer;
font-size: 18px;
transition: transform 0.2s ease;
}
.neumorphic-btn:hover {
transform: scale(1.05);
}
/* Progress Fill */
.progress-bar-fill {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 0%;
background: linear-gradient(45deg, #6A5ACD, #48D1CC);
border-radius: 30px;
transition: height 0.3s ease;
}
/* Progress Text */
.progress-text {
position: relative;
z-index: 1;
color: #333;
font-weight: bold;
text-align: center;
width: 100%;
}
.complete {
color: #ffffff;
}
JavaScript for Functionality
const uploadBtn = document.getElementById('uploadBtn');
const fileInput = document.getElementById('fileInput');
const progressBarFill = document.querySelector('.progress-bar-fill');
const progressText = document.getElementById('progressText');
uploadBtn.addEventListener('click', () => {
fileInput.click(); // Simulate a file upload input
});
fileInput.addEventListener('change', () => {
if (fileInput.files.length > 0) {
startUpload(); // Begin progress bar animation
}
});
function startUpload() {
let progress = 0;
progressText.textContent = '0%';
const interval = setInterval(() => {
progress += 10;
progressBarFill.style.height = `${progress}%`;
progressText.textContent = `${progress}%`;
if (progress >= 100) {
clearInterval(interval);
progressText.textContent = 'Complete!';
progressText.classList.add('complete');
setTimeout(() => resetButton(), 2000);
}
}, 300); // Simulate upload every 300ms
}
function resetButton() {
progressBarFill.style.height = '0%';
progressText.textContent = 'Upload File';
progressText.classList.remove('complete');
}
Customizations
- Colors: Adjust the background, gradient, and text colors in the CSS.
- Animation Speed: Change the
setInterval
duration in JavaScript for faster/slower progress. - Shape: Modify the
border-radius
property for a different button style.
Demo
By combining these files, you get an elegant, interactive button that simulates progress while providing visual feedback to the user. You can enhance it further with additional animations, sounds, or effects to make it even more engaging.
Let me know if you need additional help with this implementation!