Learn how to create a modern newsletter template using HTML, CSS, and JavaScript with simple steps. Beginner-friendly guide with clean code and animations.
Table of Contents
If you want to grow your email list or add a modern subscription form to your website, creating a custom newsletter template is a great start. In this guide, you'll learn how to make a simple and attractive newsletter form using HTML, CSS, and JavaScript.
This project is easy for beginners and perfect for learning front-end web development. You can use it for personal blogs, business websites, or landing pages.
Prerequisites
Before you start, make sure you have:
- Basic knowledge of HTML, CSS, and JavaScript
- A code editor like VS Code
- A modern browser (like Chrome)
- Internet connection for CDN links (Tailwind CSS, Font Awesome, Google Fonts)
Source Code
Step 1 (HTML Code):
To get started, we first need to create a basic HTML file. In this file, we will include the main structure for our newsletter template. Let's break down the HTML code step by step:
<!DOCTYPE html>, <html lang="en">, <head>:
- Declares the document as HTML5 and sets the language to English.
- Includes metadata and links to:
- Tailwind CSS via CDN.
- Google Fonts: Inter (body) and Poppins (heading).
- Font Awesome for icons.
- A local stylesheet: styles.css.
<body> contains:
main-container: Holds the entire layout.
Split into two parts:1. Visual Section (visual-section)
- Tailwind classes are used for spacing, responsiveness, and design.
- Includes:
- An SVG book/library-style icon inside a glass-like div (with blur and rotation effects).
- Heading: "Elevate Your Inbox" styled with large font and drop-shadow.
- Paragraph: Short description about the newsletter.
2. Form Section (form-section)
Heading: "Join Our Community" with gradient text.
Subheading: Explains what users get.
Form:
- id="subscriptionForm": The main subscription form.
- Input field:
- Type: email, required.
- Placeholder: [email protected].
- Envelope icon (fa-envelope) placed using absolute positioning.
- Submit button:
- Uses gradient background, animation effects, and a paper plane icon (fa-paper-plane).
Thank You Message:
- id="thankYouMessage": Hidden by default (hidden class).
- Includes a check icon (fa-check-circle), heading, and reset button (Subscribe Another Email).
JavaScript and Custom Logic
Linked script: script.js
- Submitting the form.
- Showing the thank you message.
- Resetting the form.
Step 2 (CSS Code):
Once the basic HTML structure of the newsletter is in place, the next step is to add styling to the newsletter using CSS. Let's break down the CSS code step by step:
body
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #e0f2f7 0%, #c1e4ed 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
overflow: hidden;
position: relative;
}
- Font: Uses Inter for clean, modern typography.
- Background: Soft diagonal gradient in cool blues.
- Flexbox: Centers the .main-container both vertically and horizontally.
- Full-height layout: min-height: 100vh makes the body fill the screen.
- Overflow hidden: Prevents scrollbars when animations run outside the body.
- Position relative: Required for absolute children like ::before.
body::before – Subtle Background Pattern
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(...);
z-index: -1;
}
- Adds a layer of faint radial gradients in the background for soft texture.
- Positioned behind everything using z-index: -1.
.main-container
.main-container {
max-width: 1000px;
display: flex;
flex-direction: column;
border-radius: 2.5rem;
box-shadow: ...;
transition: all 0.5s ...;
}
- Rounded corners, soft box-shadow, and responsive layout.
- Uses smooth transitions for interaction/resize effects.
@media (min-width: 768px)
.main-container {
flex-direction: row;
min-height: 550px;
}
- On tablets and desktops, changes to horizontal layout with fixed height.
.visual-section
.visual-section {
background: linear-gradient(to bottom right, #8b5cf6, #3b82f6);
display: flex;
justify-content: center;
align-items: center;
animation: backgroundShift 15s ... infinite alternate;
}
- Background is a purple-blue gradient.
- Uses flex to center contents.
- Animated background shifts subtly with @keyframes backgroundShift.
Abstract Overlays
.visual-section::before, .visual-section::after {
content: '';
position: absolute;
background: radial-gradient(...);
transform: rotate(...);
z-index: 0;
opacity: ...;
}
- Adds abstract light shapes for a dynamic, modern visual effect.
.form-section
.form-section {
background-color: white;
padding: 2.5rem;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
- Simple, clean white box for the form.
- Layout is centered and columnar.
Media Query
@media (min-width: 768px) {
.visual-section, .form-section {
flex: 1;
}
}
- On larger screens, both sections split 50/50 horizontally.
Thank You Animations
fadeInScale
@keyframes fadeInScale {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
- Smooth fade and zoom in when the thank-you message is shown.
bounceIn
@keyframes bounceIn { ... }
- Used for the success icon animation, creating a bouncy entry effect.
.thank-you-animation {
animation: fadeInScale 0.6s ease-out forwards;
}
.icon-bounce {
animation: bounceIn 1s forwards;
}
Input Border Gradient on Focus
.input-gradient-border:focus {
border-image-slice: 1;
border-image-source: linear-gradient(to right, #6366f1, #3b82f6);
}
- When the input is focused, the border becomes a gradient line from indigo to blue.
Button Hover Animation
.button-hover-effect {
background-size: 200% auto;
transition: ...;
}
.button-hover-effect:hover {
background-position: right center;
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
}
- Enlarges and shifts the background gradient.
- Button lifts slightly and gets a stronger shadow on hover.
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #e0f2f7 0%, #c1e4ed 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
overflow: hidden;
position: relative;
}
/* Subtle background pattern */
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at 10% 20%, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0) 70%),
radial-gradient(circle at 90% 80%, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0) 70%);
z-index: -1;
}
.main-container {
max-width: 1000px;
width: 100%;
display: flex;
flex-direction: column;
border-radius: 2.5rem; /* Even more rounded */
overflow: hidden;
box-shadow: 0 30px 60px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(0, 0, 0, 0.08); /* Deeper, softer shadow */
transition: all 0.5s cubic-bezier(0.25, 0.8, 0.25, 1); /* Smoother transition */
}
@media (min-width: 768px) {
.main-container {
flex-direction: row;
min-height: 550px; /* Slightly taller */
}
}
.visual-section {
background: linear-gradient(to bottom right, #8b5cf6, #3b82f6); /* Modern purples and blues */
display: flex;
justify-content: center;
align-items: center;
padding: 2.5rem;
color: white;
text-shadow: 0 2px 8px rgba(0,0,0,0.3); /* Stronger text shadow */
position: relative;
overflow: hidden;
animation: backgroundShift 15s ease-in-out infinite alternate; /* Subtle background animation */
}
@keyframes backgroundShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.visual-section::before {
content: '';
position: absolute;
top: -10%;
left: -10%;
width: 120%;
height: 120%;
background: radial-gradient(circle, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0) 70%);
transform: rotate(35deg);
z-index: 0;
opacity: 0.8;
}
.visual-section::after { /* Another layer of abstract shapes */
content: '';
position: absolute;
bottom: -15%;
right: -15%;
width: 80%;
height: 80%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 60%);
transform: rotate(-20deg);
z-index: 0;
opacity: 0.6;
}
.form-section {
background-color: #ffffff;
padding: 2.5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
}
@media (min-width: 768px) {
.visual-section, .form-section {
flex: 1;
}
}
/* Custom animation for the thank you message */
@keyframes fadeInScale {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes bounceIn {
0%, 20%, 40%, 60%, 80%, 100% {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
0% {
opacity: 0;
-webkit-transform: scale3d(.3, .3, .3);
transform: scale3d(.3, .3, .3);
}
20% {
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
40% {
-webkit-transform: scale3d(.9, .9, .9);
transform: scale3d(.9, .9, .9);
}
60% {
opacity: 1;
-webkit-transform: scale3d(1.03, 1.03, 1.03);
transform: scale3d(1.03, 1.03, 1.03);
}
80% {
-webkit-transform: scale3d(.97, .97, .97);
transform: scale3d(.97, .97, .97);
}
100% {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.thank-you-animation {
animation: fadeInScale 0.6s ease-out forwards;
}
.icon-bounce {
animation: bounceIn 1s forwards;
}
/* Gradient for the input border on focus */
.input-gradient-border:focus {
border-image-slice: 1;
border-image-source: linear-gradient(to right, #6366f1, #3b82f6);
}
/* Button hover animation */
.button-hover-effect {
background-size: 200% auto;
transition: background-position 0.4s ease-in-out, transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}
.button-hover-effect:hover {
background-position: right center;
transform: translateY(-3px); /* More pronounced lift */
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); /* Enhanced shadow on hover */
} Step 3 (JavaScript Code):
Finally, we need to create a function in JavaScript. Let's break down the JS code step by step:
1. Getting Elements from the Page
const subscriptionForm = document.getElementById('subscriptionForm');
const subscriptionFormSection = document.getElementById('subscription-form-section');
const thankYouMessage = document.getElementById('thankYouMessage');
const emailInput = document.getElementById('emailInput');
- These lines grab HTML elements using their id attributes so they can be manipulated.
- subscriptionForm → the actual
<form>. - subscriptionFormSection → the container holding the form.
- thankYouMessage → the hidden confirmation message section.
- emailInput → the email input field.
- subscriptionForm → the actual
2. Handling Form Submission
subscriptionForm.addEventListener('submit', function (event) {
event.preventDefault();
- Listens for the submit event.
- event.preventDefault() prevents the page from reloading, which is the default form behavior.
3. Simulate Submission
console.log('Submitting email:', emailInput.value);
- Logs the email to the console.
- In a real-world case, you’d send the email to a backend using fetch() or Axios.
4. Hide the Form / Show Confirmation
subscriptionFormSection.classList.add('hidden');
thankYouMessage.classList.remove('hidden');
thankYouMessage.classList.add('thank-you-animation');
emailInput.value = '';
- Hides the form by adding the hidden class.
- Shows the thank-you message by:
- Removing its hidden class.
- Adding the thank-you-animation class (CSS animates it).
- Clears the email input field.
5. Reset the Form
function resetForm() {
thankYouMessage.classList.add('hidden');
thankYouMessage.classList.remove('thank-you-animation');
subscriptionFormSection.classList.remove('hidden');
emailInput.value = '';
emailInput.focus();
}
- Called when the user clicks "Subscribe Another Email" button.
- It:
- Hides the thank-you section.
- Removes the animation class.
- Reveals the form again.
- Clears and focuses the input for a new email.
// Get references to DOM elements
const subscriptionForm = document.getElementById('subscriptionForm');
const subscriptionFormSection = document.getElementById(
'subscription-form-section'
);
const thankYouMessage = document.getElementById('thankYouMessage');
const emailInput = document.getElementById('emailInput');
// Add event listener for form submission
subscriptionForm.addEventListener('submit', function (event) {
event.preventDefault(); // Prevent default form submission behavior (page reload)
// Simulate a submission process (e.g., sending data to a server)
console.log('Submitting email:', emailInput.value);
// Hide the form section
subscriptionFormSection.classList.add('hidden');
// Show the thank-you message with animation
thankYouMessage.classList.remove('hidden');
thankYouMessage.classList.add('thank-you-animation'); // Add animation class
// Optionally, clear the input field after submission
emailInput.value = '';
});
// Function to reset the form and show it again
function resetForm() {
thankYouMessage.classList.add('hidden'); // Hide thank you message
thankYouMessage.classList.remove('thank-you-animation'); // Remove animation class for reset
subscriptionFormSection.classList.remove('hidden'); // Show the form again
emailInput.value = ''; // Clear the email input
emailInput.focus(); // Set focus back to the email input
}Final Output:
Conclusion:
Creating a newsletter template using HTML, CSS, and JavaScript is a great way to learn web design and improve your site's engagement. This simple form is mobile-friendly, easy to customize, and perfect for beginners. You can also connect it to tools like Mailchimp, Google Sheets, or your own backend.
Start with this basic design, and as you grow, you can add:
- Email validation
- API integration
- Database connection
- Animation libraries (like GSAP)
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 😊


