Frontend Development, UX Engineering
B2B Marketplace
2024
A power-curve range slider for a €0 to €50M price filter.
A B2B marketplace needed a price filter that covered five orders of magnitude, from a few hundred euros up to €50 million. The built-in linear slider was essentially broken: 99% of the track belonged to the upper end, so picking anything in the most common price brackets was nearly impossible.
A Linear Slider in a Non-Linear World
Linear mapping meant the entire €0 to €500k range, where most listings sat, was crammed into roughly 10 pixels on a 1,000px slider. You couldn't land on a value even if you tried. The client wanted something that felt natural across the full range without resorting to multiple inputs or a manual number field.
99% of the slider track belonged to the upper end. Picking anything in the most common price range was essentially guesswork.
A Configurable Power Curve
Rather than a logarithmic scale with its own quirks, I went with a power curve. The slider position is normalized to 0-1 and raised to a configurable steepness exponent. At steepness 5, the lower half of the track covers about 3 % of the total range, so you get fine control exactly where it counts. Because the exponent lives in a data attribute, each slider instance can ship a different curve shape, and A/B tests don't need a single line of code.
Maps a slider position (0 to resolution) to a real value via the power curve:
const toLogValue = (position, maxValue, resolution, steepness) => {
if (position === 0) return 0;
const normalized = position / resolution;
return Math.round(Math.pow(normalized, steepness) * maxValue);
};Interactive Demo
Tweak the curve parameters and watch the effect in real time, including a steepness comparison and step-size visualization.
The slider position (0 to resolution) is normalized to 0-1, then raised to the steepness exponent. This gives fine control at the low end and increasingly large jumps toward the top. At steepness 5, the first 50 % of the slider maps to roughly 3 % of the value range; the last 10 % covers about 40 %. roundToNiceStep() then rounds values to clean, human-readable numbers.
The inverse: given a real value, compute the matching slider handle position:
const toSliderPosition = (value, maxValue, resolution, steepness) => {
if (value === 0) return 0;
const normalized = Math.pow(value / maxValue, 1 / steepness);
return normalized * resolution;
};Invisible Precision
Once the power-curve slider went live, filter usage went up noticeably. People who had been ignoring the price filter started using it. Support tickets about "the slider not working" dropped to zero. The whole thing is under 30 lines with no performance overhead.
Snaps raw values to human-friendly numbers that scale with magnitude:
const roundToNiceStep = (num) => {
if (num === 0) return 0;
const magnitude = Math.floor(Math.log10(num));
const step = Math.pow(10, magnitude) / 20;
return Math.round(num / step) * step;
};