Create a Fully Functional Currency Converter with HTML, CSS, and Vanilla JavaScript (2026 Beginner Tutorial)
3 days ago

Wouldn’t it be cool to add a real-time currency converter to your website or portfolio project? In this step-by-step tutorial, you’ll learn how to build a clean, responsive, and fully functional currency converter app using only HTML, CSS, and vanilla JavaScript — no frameworks required.
By the end of this guide, you’ll have a professional-looking app that fetches live exchange rates from a free API and converts currencies instantly.
What We’ll Build
Our currency converter will include:
- An input field for the amount
- Two dropdowns to select “From” and “To” currencies
- A prominent “Convert” button
- Real-time conversion result display
- Error handling for invalid inputs or API issues
- Responsive design that works beautifully on mobile and desktop
We’ll use the free ExchangeRate-API for live rates and the REST Countries API for currency flags and names.
Prerequisites
You only need:
- A modern code editor (Visual Studio Code recommended)
- A web browser (Chrome, Firefox, or Edge)
- A free API key from exchangerate-api.com
Step 1: Project Setup and HTML Structure
Create a new folder for your project and add an index.html file.
Here’s the complete HTML structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Currency Converter</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="currency-converter">
<h1>Currency Converter</h1>
<div class="input-box">
<label for="amount">Enter Amount</label>
<input type="number" id="amount" placeholder="100" min="1" required>
</div>
<div class="currency-row">
<div class="currency-box">
<select id="fromCurrency" class="currency-select"></select>
</div>
<div class="swap">
<span>TO</span>
</div>
<div class="currency-box">
<select id="toCurrency" class="currency-select"></select>
</div>
</div>
<button id="convertBtn" class="convert-button">Convert</button>
<p id="result" class="result"></p>
<p id="error" class="error"></p>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Step 2: Styling with Modern CSS
Create a style.css file with clean, modern styling:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Bricolage Grotesque', sans-serif;
background: linear-gradient(135deg, #202020, #121212);
color: #fff;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
max-width: 480px;
width: 100%;
padding: 2rem;
}
.currency-converter {
background: #7cb889;
border-radius: 40px;
padding: 3rem 2.5rem;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
color: #040203;
}
h1 {
font-size: 3.2rem;
font-weight: 700;
text-align: center;
margin-bottom: 2rem;
line-height: 1.1;
}
.input-box {
margin-bottom: 2rem;
text-align: center;
}
label {
display: block;
font-size: 1.4rem;
margin-bottom: 0.8rem;
font-weight: 600;
}
#amount {
width: 100%;
padding: 1.2rem 1.5rem;
font-size: 2.8rem;
border: 4px solid #040203;
border-radius: 30px;
background: transparent;
color: #040203;
text-align: center;
}
#amount:focus {
outline: none;
border-color: #fff;
}
.currency-row {
display: flex;
align-items: center;
justify-content: center;
gap: 1.5rem;
margin: 2rem 0;
}
.currency-box {
flex: 1;
}
.currency-select {
width: 100%;
padding: 1.2rem;
font-size: 1.1rem;
font-weight: 700;
border: 4px solid #040203;
border-radius: 25px;
background: #fff;
color: #040203;
appearance: none;
cursor: pointer;
}
.swap {
font-size: 1.4rem;
font-weight: 700;
color: #040203;
}
.convert-button {
width: 100%;
padding: 1.4rem;
font-size: 1.5rem;
font-weight: 700;
background: #040203;
color: #fff;
border: none;
border-radius: 30px;
cursor: pointer;
margin: 1.5rem 0;
transition: all 0.3s ease;
}
.convert-button:hover {
background: #222;
transform: translateY(-2px);
}
.result {
font-size: 2.4rem;
font-weight: 700;
text-align: center;
margin: 1.5rem 0;
min-height: 3.2rem;
}
.error {
color: #c62828;
text-align: center;
font-size: 1rem;
margin-top: 1rem;
}
Step 3: JavaScript Functionality
Create script.js with the following code:
// Your Exchange Rate API Key (get free at exchangerate-api.com)
const API_KEY = 'YOUR_API_KEY_HERE'; // Replace with your actual key
const fromCurrency = document.getElementById('fromCurrency');
const toCurrency = document.getElementById('toCurrency');
const amountInput = document.getElementById('amount');
const convertBtn = document.getElementById('convertBtn');
const resultEl = document.getElementById('result');
const errorEl = document.getElementById('error');
// Fetch currency data and populate dropdowns
async function loadCurrencies() {
try {
const response = await fetch('https://restcountries.com/v3.1/all?fields=currencies,flag,name');
const data = await response.json();
const currencies = [];
data.forEach(country => {
if (country.currencies) {
const code = Object.keys(country.currencies)[0];
const currency = country.currencies[code];
currencies.push({
code: code,
name: currency.name,
flag: country.flag || '🌍'
});
}
});
// Sort alphabetically by code
currencies.sort((a, b) => a.code.localeCompare(b.code));
// Populate both dropdowns
currencies.forEach(currency => {
const option1 = document.createElement('option');
option1.value = currency.code;
option1.textContent = `${currency.flag} ${currency.code} - ${currency.name}`;
if (currency.code === 'USD') option1.selected = true;
fromCurrency.appendChild(option1);
const option2 = document.createElement('option');
option2.value = currency.code;
option2.textContent = `${currency.flag} ${currency.code} - ${currency.name}`;
if (currency.code === 'EUR') option2.selected = true;
toCurrency.appendChild(option2);
});
} catch (error) {
console.error('Failed to load currencies:', error);
errorEl.textContent = 'Failed to load currency list. Please refresh the page.';
}
}
// Convert currency
async function convertCurrency() {
const amount = parseFloat(amountInput.value);
const from = fromCurrency.value;
const to = toCurrency.value;
// Clear previous messages
resultEl.textContent = '';
errorEl.textContent = '';
if (!amount || amount <= 0) {
errorEl.textContent = 'Please enter a valid amount';
return;
}
if (from === to) {
resultEl.textContent = `${amount} ${from} = ${amount} ${to}`;
return;
}
convertBtn.disabled = true;
convertBtn.textContent = 'Converting...';
try {
const url = `https://v6.exchangerate-api.com/v6/${API_KEY}/pair/${from}/${to}`;
const response = await fetch(url);
const data = await response.json();
if (data.result === 'success') {
const rate = data.conversion_rate;
const convertedAmount = (amount * rate).toFixed(2);
// Format with commas
const formatted = convertedAmount.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
resultEl.textContent = `${amount} ${from} = ${formatted} ${to}`;
} else {
errorEl.textContent = 'Conversion failed. Please try again.';
}
} catch (error) {
console.error(error);
errorEl.textContent = 'Network error. Please check your connection.';
} finally {
convertBtn.disabled = false;
convertBtn.textContent = 'Convert';
}
}
// Event listeners
convertBtn.addEventListener('click', convertCurrency);
// Allow pressing Enter in input field
amountInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
convertCurrency();
}
});
// Initialize the app
loadCurrencies();
Important: Replace 'YOUR_API_KEY_HERE' with your actual free API key from exchangerate-api.com.
Final Result
You now have a beautiful, responsive currency converter that:
- Fetches real-time exchange rates
- Supports 160+ currencies with flags
- Provides instant conversion
- Handles errors gracefully
- Looks modern and professional
Next Steps & Improvements
You can enhance this project by adding:
- Currency swap button (↔)
- Automatic conversion on input change
- Dark/light mode toggle
- Favorite currencies list
- Historical rate charts
This project is perfect for your portfolio and demonstrates strong HTML, CSS, and JavaScript skills.
Would you like me to add any of the suggested improvements or create a version using Tailwind CSS? Just let me know!
FAQ: Currency Converter Web App (HTML, CSS & JavaScript)
1. What is this currency converter project built with?
This project is built using HTML, CSS, and vanilla JavaScript without any frameworks.
2. Does the currency converter use real-time exchange rates?
Yes, it fetches live exchange rates using the ExchangeRate-API.
3. Do I need a backend to run this project?
No, this is a fully frontend project and runs directly in the browser.
4. How do I get an API key for exchange rates?
You can get a free API key from ExchangeRate-API by signing up on their official website.
5. Can I use this currency converter in my portfolio?
Yes, it is a great beginner-to-intermediate project for showcasing JavaScript skills.
6. Does this project support multiple currencies?
Yes, it supports 160+ currencies depending on the API data source.
7. Why is REST Countries API used in this project?
It is used to fetch currency names and flags for better UI experience.
8. Is this currency converter mobile responsive?
Yes, the layout is designed to work smoothly on both mobile and desktop devices.
9. What happens if the API fails?
The app includes error handling to show user-friendly messages if the API request fails.
10. Can I add more features to this project?
Yes, you can extend it with features like dark mode, swap button, and historical charts.
11. Is JavaScript required for this project to work?
Yes, JavaScript handles API calls and currency conversion logic.
12. Can I convert offline without internet?
No, since it relies on live API data, an internet connection is required.

Leave a Reply