* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'DM Sans', sans-serif;
background: #ffffff;
color: #1a1a1a;
}
.calculator-container {
max-width: 940px;
margin: 0 auto;
background: #ffffff;
border-radius: 16px;
box-shadow: 0 4px 24px rgba(33, 158, 65, 0.08);
padding: 36px;
border: 2px solid #219e41;
}
h1 {
font-family: 'Space Mono', monospace;
color: #219e41;
text-align: center;
margin-bottom: 6px;
font-size: 28px;
letter-spacing: -0.5px;
}
.subtitle {
text-align: center;
color: #555;
margin-bottom: 32px;
font-size: 14px;
}
.step {
margin-bottom: 28px;
}
.step-header {
background: #219e41;
color: white;
padding: 12px 20px;
border-radius: 8px;
margin-bottom: 18px;
font-size: 16px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.step-number {
background: rgba(255,255,255,0.25);
width: 28px;
height: 28px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 700;
flex-shrink: 0;
}
.appliance-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 14px;
margin-bottom: 18px;
}
.appliance-card {
background: #fafbfc;
border: 2px solid #e4e8ec;
border-radius: 10px;
padding: 16px;
transition: all 0.2s;
}
.appliance-card:hover {
border-color: #219e41;
box-shadow: 0 2px 12px rgba(33, 158, 65, 0.12);
}
.appliance-card.custom-appliance {
background: #fff;
border: 2px dashed #219e41;
}
.appliance-name {
color: #219e41;
font-weight: 600;
margin-bottom: 12px;
font-size: 15px;
}
.input-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin-bottom: 6px;
}
.input-cell {
display: flex;
flex-direction: column;
gap: 3px;
}
.input-cell label {
color: #666;
font-size: 11px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.input-cell input, .input-cell select {
padding: 7px 10px;
border: 1.5px solid #d0d5db;
border-radius: 6px;
font-size: 14px;
font-family: 'DM Sans', sans-serif;
color: #1a1a1a;
background: #fff;
transition: border-color 0.2s;
}
.input-cell input:focus, .input-cell select:focus {
outline: none;
border-color: #219e41;
box-shadow: 0 0 0 3px rgba(33, 158, 65, 0.08);
}
.runtime-toggle {
display: flex;
gap: 6px;
margin-top: 8px;
}
.runtime-toggle label {
font-size: 11px;
color: #666;
text-transform: uppercase;
letter-spacing: 0.3px;
font-weight: 500;
margin-bottom: 3px;
display: block;
}
.toggle-group {
display: flex;
gap: 0;
border-radius: 6px;
overflow: hidden;
border: 1.5px solid #d0d5db;
}
.toggle-btn {
padding: 5px 10px;
font-size: 11px;
font-family: 'DM Sans', sans-serif;
border: none;
background: #fff;
color: #666;
cursor: pointer;
font-weight: 500;
transition: all 0.15s;
}
.toggle-btn.active {
background: #219e41;
color: #fff;
}
.toggle-btn:not(:last-child) {
border-right: 1px solid #d0d5db;
}
.btn {
background: #219e41;
color: white;
border: none;
padding: 14px 28px;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
font-family: 'DM Sans', sans-serif;
transition: all 0.2s;
width: 100%;
}
.btn:hover {
background: #1a7d33;
transform: translateY(-1px);
box-shadow: 0 4px 16px rgba(33, 158, 65, 0.3);
}
.btn-secondary {
background: white;
color: #219e41;
border: 2px solid #219e41;
padding: 10px 20px;
border-radius: 25px;
font-size: 14px;
}
.btn-secondary:hover {
background: #f0f8f3;
transform: none;
box-shadow: none;
}
.add-custom-btn {
float: right;
}
.config-section {
background: #fafbfc;
padding: 20px;
border-radius: 10px;
margin-bottom: 14px;
border: 2px solid #e4e8ec;
}
.config-section label.config-label {
display: block;
color: #219e41;
font-weight: 600;
margin-bottom: 8px;
font-size: 14px;
}
.config-section input {
width: 100%;
padding: 10px 14px;
border: 1.5px solid #d0d5db;
border-radius: 6px;
font-size: 15px;
font-family: 'DM Sans', sans-serif;
color: #1a1a1a;
}
.config-section input:focus {
outline: none;
border-color: #219e41;
box-shadow: 0 0 0 3px rgba(33, 158, 65, 0.08);
}
.config-hint {
font-size: 12px;
color: #888;
margin-top: 6px;
line-height: 1.4;
}
.config-hint i {
color: #219e41;
}
.config-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.remove-btn {
background: #ef4444;
color: white;
border: none;
padding: 5px 12px;
border-radius: 5px;
cursor: pointer;
font-size: 12px;
font-family: 'DM Sans', sans-serif;
margin-top: 8px;
transition: background 0.15s;
}
.remove-btn:hover {
background: #dc2626;
}
/* Results Styles */
.results {
background: linear-gradient(145deg, #219e41 0%, #176e2e 100%);
color: white;
padding: 32px;
border-radius: 14px;
margin-top: 28px;
}
.results h2 {
margin-bottom: 18px;
font-size: 20px;
font-family: 'Space Mono', monospace;
color: #fff;
letter-spacing: -0.3px;
}
.result-item {
background: rgba(255, 255, 255, 0.1);
padding: 16px;
border-radius: 10px;
margin-bottom: 12px;
backdrop-filter: blur(10px);
}
.result-label {
font-size: 13px;
opacity: 0.85;
margin-bottom: 4px;
}
.result-value {
font-family: 'Space Mono', monospace;
font-size: 22px;
font-weight: 700;
}
.result-sub {
font-size: 13px;
margin-top: 6px;
opacity: 0.85;
line-height: 1.4;
}
.battery-options {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
margin-top: 18px;
}
.battery-option {
background: rgba(255, 255, 255, 0.12);
padding: 18px;
border-radius: 10px;
text-align: center;
border: 2px solid rgba(255, 255, 255, 0.2);
transition: all 0.2s;
}
.battery-option:hover {
background: rgba(255, 255, 255, 0.18);
border-color: rgba(255, 255, 255, 0.4);
}
.battery-option h3 {
font-size: 14px;
margin-bottom: 8px;
opacity: 0.85;
color: #fff;
}
.battery-option .value {
font-family: 'Space Mono', monospace;
font-size: 26px;
font-weight: 700;
}
.battery-option .kwh-val {
margin-top: 6px;
font-size: 13px;
opacity: 0.8;
}
.warning-box {
background: rgba(255, 193, 7, 0.15);
border: 2px solid rgba(255, 193, 7, 0.4);
border-radius: 10px;
padding: 16px;
margin-bottom: 12px;
}
.warning-box .result-label {
color: #ffd54f;
opacity: 1;
}
.info-box {
background: rgba(255,255,255,0.08);
border-radius: 10px;
padding: 16px;
margin-top: 18px;
font-size: 13px;
line-height: 1.6;
opacity: 0.85;
}
.info-box strong {
opacity: 1;
}
table {
width: 100%;
border-collapse: collapse;
background: rgba(255,255,255,0.08);
border-radius: 10px;
overflow: hidden;
}
thead tr {
background: rgba(0,0,0,0.2);
}
th, td {
padding: 10px 14px;
text-align: left;
font-size: 13px;
color: #fff;
}
td:last-child, th:last-child {
text-align: right;
}
tbody tr {
border-top: 1px solid rgba(255,255,255,0.08);
}
tbody tr:hover {
background: rgba(255,255,255,0.05);
}
.peak-load-section {
background: rgba(255,255,255,0.12);
border-radius: 10px;
padding: 18px;
margin-top: 18px;
border: 2px solid rgba(255,255,255,0.2);
}
.peak-load-section h3 {
font-size: 16px;
margin-bottom: 10px;
color: #fff;
}
.peak-val {
font-family: 'Space Mono', monospace;
font-size: 28px;
font-weight: 700;
}
.formula-note {
background: rgba(255,255,255,0.06);
border-radius: 8px;
padding: 14px;
margin-top: 16px;
font-size: 12px;
line-height: 1.7;
opacity: 0.75;
}
@media (max-width: 768px) {
.appliance-grid {
grid-template-columns: 1fr;
}
.config-grid {
grid-template-columns: 1fr;
}
.calculator-container {
padding: 18px;
border-radius: 10px;
}
h1 {
font-size: 22px;
}
.battery-options {
grid-template-columns: 1fr 1fr;
}
.result-value {
font-size: 18px;
}
.results {
padding: 22px;
}
}
@media (max-width: 480px) {
.battery-options {
grid-template-columns: 1fr;
}
.input-row {
grid-template-columns: 1fr;
}
}
const defaultAppliances = [
{ name: 'Ceiling Fan', watts: 75, quantity: 1, hours: 8, runtime: 'mixed', icon: 'fa-fan' },
{ name: 'LED Bulb', watts: 10, quantity: 1, hours: 6, runtime: 'night', icon: 'fa-lightbulb' },
{ name: 'LED TV', watts: 100, quantity: 1, hours: 5, runtime: 'mixed', icon: 'fa-tv' },
{ name: 'Refrigerator', watts: 150, quantity: 1, hours: 24, runtime: '24hr', icon: 'fa-temperature-low' },
{ name: 'AC (1.5 Ton)', watts: 1500, quantity: 1, hours: 6, runtime: 'mixed', icon: 'fa-snowflake' },
{ name: 'Washing Machine', watts: 500, quantity: 1, hours: 1, runtime: 'day', icon: 'fa-shirt' },
{ name: 'Water Motor', watts: 750, quantity: 1, hours: 1, runtime: 'day', icon: 'fa-water' },
{ name: 'Iron', watts: 1000, quantity: 1, hours: 0.5, runtime: 'day', icon: 'fa-fire' }
];
let appliances = JSON.parse(JSON.stringify(defaultAppliances));
let customIdCounter = 0;
function renderAppliances() {
const grid = document.getElementById('applianceGrid');
grid.innerHTML = '';
appliances.forEach((appliance, index) => {
const card = document.createElement('div');
card.className = appliance.custom ? 'appliance-card custom-appliance' : 'appliance-card';
const icon = appliance.icon || 'fa-plug';
const rt = appliance.runtime || 'mixed';
card.innerHTML = `
${appliance.custom ? `` : ''}
`;
grid.appendChild(card);
});
}
function updateAppliance(index, field, value) {
if (field === 'runtime') {
appliances[index][field] = value;
} else {
appliances[index][field] = parseFloat(value) || 0;
}
}
function addCustomAppliance() {
const customName = prompt('Enter device name:');
if (customName && customName.trim()) {
const customWatts = prompt('Enter power consumption (Watts):', '100');
if (customWatts) {
appliances.push({
name: customName.trim(),
watts: parseFloat(customWatts) || 100,
quantity: 1,
hours: 5,
runtime: 'mixed',
custom: true,
icon: 'fa-plug',
id: customIdCounter++
});
renderAppliances();
}
}
}
function removeAppliance(index) {
if (confirm('Remove this device?')) {
appliances.splice(index, 1);
renderAppliances();
}
}
function calculateLoad() {
const backupDays = parseFloat(document.getElementById('backupDays').value) || 1;
const solarGenerationKWh = parseFloat(document.getElementById('solarGeneration').value) || 0;
const solarHours = parseFloat(document.getElementById('solarHours').value) || 5;
const inverterEff = (parseFloat(document.getElementById('inverterEfficiency').value) || 90) / 100;
const nightHours = 24 - solarHours;
const solarWh = solarGenerationKWh * 1000;
let totalDailyWh = 0;
let dayLoadWh = 0; // Load during solar hours
let nightLoadWh = 0; // Load during non-solar hours
let peakWatts = 0;
let breakdown = [];
appliances.forEach(appliance => {
if (appliance.quantity > 0 && appliance.hours > 0) {
const totalWatts = appliance.watts * appliance.quantity;
const dailyWh = totalWatts * appliance.hours;
totalDailyWh += dailyWh;
// Split load into day vs night based on runtime setting
let appDayWh = 0;
let appNightWh = 0;
const rt = appliance.runtime || 'mixed';
if (rt === 'day') {
// Runs only during solar hours
appDayWh = dailyWh;
appNightWh = 0;
} else if (rt === 'night') {
// Runs only at night
appDayWh = 0;
appNightWh = dailyWh;
} else if (rt === '24hr') {
// Runs 24 hours โ split proportionally
const dayFraction = solarHours / 24;
appDayWh = dailyWh * dayFraction;
appNightWh = dailyWh * (1 - dayFraction);
} else {
// mixed โ split hours proportionally between day/night
if (appliance.hours 0 ? Math.min(100, (solarWh / totalDailyWh) * 100) : 0;
displayResults({
totalDailyWh,
dayLoadWh,
nightLoadWh,
solarWh,
solarCoverage,
solarSurplus,
unmetDayLoad,
batteryDailyDrawWh,
batteryDailyWithLosses,
totalBatteryWhNeeded,
adjustedWh,
battery12V,
battery24V,
battery48V,
battery51_2V,
peakWatts,
inverterEff,
backupDays,
solarHours,
breakdown
});
}
function displayResults(d) {
const resultsDiv = document.getElementById('results');
const runtimeLabels = {
'day': 'โ๏ธ Day',
'night': '๐ Night',
'mixed': '๐ Mixed',
'24hr': 'โฐ 24hr'
};
let breakdownHTML = d.breakdown.map(item => `
${item.name}
${item.watts}W ร ${item.quantity} ร ${item.hours}h
${runtimeLabels[item.runtime] || item.runtime}
${(item.dayWh / 1000).toFixed(2)}
${(item.nightWh / 1000).toFixed(2)}
${(item.dailyWh / 1000).toFixed(2)}
`).join('');
resultsDiv.innerHTML = `
${d.solarWh > 0 ? `
` : `
`}
`;
resultsDiv.style.display = 'block';
resultsDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
// Initialize
renderAppliances();
Solar Battery Calculator
Accurate battery sizing with inverter losses, day/night load splitting & peak load analysis
1
Configure Your Appliances
2
Solar Generation & System Settings
Total energy your panels produce per day. This offsets daytime loads only.
Hours of effective solar generation per day (typically 4โ6 hrs in Pakistan).
Number of days the battery should last without any solar input.
Typical inverter efficiency is 85โ95%. Accounts for DC to AC conversion losses.
${appliance.name}
โ๏ธ Day Only
๐ Night Only
๐ Day+Night
โฐ 24 Hours
Energy Requirements
Daily Total Load
${(d.totalDailyWh / 1000).toFixed(2)} kWh
โ๏ธ Daytime load: ${(d.dayLoadWh / 1000).toFixed(2)} kWh |
๐ Nighttime load: ${(d.nightLoadWh / 1000).toFixed(2)} kWh
Daily Solar Generation
${(d.solarWh / 1000).toFixed(2)} kWh
Covers ${d.solarCoverage.toFixed(1)}% of total daily load
${d.solarSurplus > 0 ? ` | Surplus for battery charging: ${(d.solarSurplus / 1000).toFixed(2)} kWh` : ''}
${d.unmetDayLoad > 0 ? ` | Unmet daytime load (battery needed): ${(d.unmetDayLoad / 1000).toFixed(2)} kWh` : ''}
No Solar Generation Entered
Battery will cover 100% of load. Enter your solar generation for accurate sizing.
Daily Battery Draw (before losses)
${(d.batteryDailyDrawWh / 1000).toFixed(2)} kWh
Night load + any unmet daytime load that solar can't cover
Daily Battery Draw (with ${((1 - d.inverterEff) * 100).toFixed(0)}% inverter loss)
${(d.batteryDailyWithLosses / 1000).toFixed(2)} kWh
Adjusted for ${(d.inverterEff * 100).toFixed(0)}% inverter efficiency (DCโAC conversion loss)
Total Battery Energy for ${d.backupDays} Day(s) Backup
${(d.totalBatteryWhNeeded / 1000).toFixed(2)} kWh
Recommended Battery Capacity
Adjusted for 80% Depth of Discharge (DoD) to protect battery lifespan
Total Required Battery Capacity
${(d.adjustedWh / 1000).toFixed(2)} kWh
12V System
${d.battery12V.toFixed(0)} Ah
${(d.adjustedWh / 1000).toFixed(2)} kWh
24V System
${d.battery24V.toFixed(0)} Ah
${(d.adjustedWh / 1000).toFixed(2)} kWh
48V System
${d.battery48V.toFixed(0)} Ah
${(d.adjustedWh / 1000).toFixed(2)} kWh
51.2V System
${d.battery51_2V.toFixed(0)} Ah
${(d.adjustedWh / 1000).toFixed(2)} kWh
Peak Load / Minimum Inverter Size
${(d.peakWatts / 1000).toFixed(2)} kW
(${d.peakWatts.toFixed(0)}W) โ If all devices run simultaneously. Your inverter/UPS must handle at least this wattage.
Consider motor starting surges (2โ3ร rated watts for motors, ACs, and washing machines).
Load Breakdown
| Appliance | Usage | Runs | Day kWh | Night kWh | Total kWh |
|---|---|---|---|---|---|
| TOTAL | ${(d.dayLoadWh / 1000).toFixed(2)} | ${(d.nightLoadWh / 1000).toFixed(2)} | ${(d.totalDailyWh / 1000).toFixed(2)} | ||
How this is calculated:
1. Each appliance's daily energy = Watts ร Quantity ร Hours
2. Load is split into daytime (solar hours) and nighttime based on when each device runs
3. Solar generation offsets daytime load first; any surplus can charge the battery
4. Battery must cover: nighttime load + any unmet daytime load
5. Inverter efficiency loss (${((1 - d.inverterEff) * 100).toFixed(0)}%) is added to account for DCโAC conversion
6. Multiplied by backup days (${d.backupDays})
7. Divided by 80% DoD to protect battery lifespan
8. Final capacity = Battery energy รท system voltage = Ah rating
1. Each appliance's daily energy = Watts ร Quantity ร Hours
2. Load is split into daytime (solar hours) and nighttime based on when each device runs
3. Solar generation offsets daytime load first; any surplus can charge the battery
4. Battery must cover: nighttime load + any unmet daytime load
5. Inverter efficiency loss (${((1 - d.inverterEff) * 100).toFixed(0)}%) is added to account for DCโAC conversion
6. Multiplied by backup days (${d.backupDays})
7. Divided by 80% DoD to protect battery lifespan
8. Final capacity = Battery energy รท system voltage = Ah rating