如何实现四个百分比输入框动态调整总和至100%的交互功能
Here's a clean, vanilla JS implementation that does exactly what you need—four percentage inputs starting at 25% each, with automatic balancing whenever any input is modified. I’ve included validation and edge-case handling to make it robust:
HTML Structure
First, a straightforward layout with labeled inputs. Users just type numbers, and we show the % symbol separately to avoid parsing headaches:
<div class="percentage-inputs"> <div class="input-group"> <label for="percent1">Percentage 1:</label> <input type="number" id="percent1" min="0" max="100" value="25"> <span>%</span> </div> <div class="input-group"> <label for="percent2">Percentage 2:</label> <input type="number" id="percent2" min="0" max="100" value="25"> <span>%</span> </div> <div class="input-group"> <label for="percent3">Percentage 3:</label> <input type="number" id="percent3" min="0" max="100" value="25"> <span>%</span> </div> <div class="input-group"> <label for="percent4">Percentage 4:</label> <input type="number" id="percent4" min="0" max="100" value="25"> <span>%</span> </div> </div>
Basic Styling
A quick CSS snippet to make the inputs look organized (adjust this to fit your app's design):
.percentage-inputs { display: flex; flex-direction: column; gap: 1rem; max-width: 350px; margin: 2rem; } .input-group { display: flex; align-items: center; gap: 0.5rem; } input[type="number"] { width: 70px; padding: 0.4rem; border: 1px solid #ddd; border-radius: 4px; } label { width: 120px; }
Core JavaScript Logic
This handles input validation, recalculation, and balancing. Here's the breakdown:
- We listen for
inputevents on every field - When a field is changed, we first clamp its value to 0-100 to avoid invalid numbers
- We calculate the remaining percentage (100 minus the changed value)
- Distribute that remaining percentage equally among the other three fields, rounded to 1 decimal place (matching your 26.6% example—we can tweak rounding if needed)
- Handles edge cases (e.g., if someone types 150, we set that field to 100 and the rest to 0)
const percentInputs = document.querySelectorAll('input[type="number"]'); function updateRemainingInputs(changedInput) { // Validate and clamp the changed value to 0-100 const changedValue = Math.max(0, Math.min(100, parseFloat(changedInput.value) || 0)); changedInput.value = changedValue; // Get all inputs except the one that was just changed const otherInputs = Array.from(percentInputs).filter(input => input !== changedInput); // Calculate remaining percentage to split const remainingPercentage = 100 - changedValue; // Handle edge case where changed value is 100 if (remainingPercentage <= 0) { otherInputs.forEach(input => input.value = 0); return; } // Split remaining equally, truncate to 1 decimal place (matches your example) const equalShare = remainingPercentage / otherInputs.length; otherInputs.forEach(input => { input.value = Math.floor(equalShare * 10) / 10; }); } // Attach event listeners to all inputs percentInputs.forEach(input => { input.addEventListener('input', () => updateRemainingInputs(input)); });
If you prefer rounding instead of truncating (e.g., 26.7% instead of 26.6%), just replace Math.floor(equalShare * 10) / 10 with equalShare.toFixed(1). Either way, the core logic keeps the total at 100% automatically.
内容的提问来源于stack exchange,提问作者AutDev

