Issue
I'm building a text tracking (letter-spacing) demo and I have range sliders updating CSS props but I'd like to extend it so that the labels also update dynamically. It's sort of working but hacky. Is there a way to do it elegantly, so I'm not repeating output2.textContent = this.value; output2.textContent = this.value;
etc.?
Also, the UI janks when the values go from (eg) 0.09 -> 0.1 -> 0.11. Can I have it always output two decimals? Script is before the close.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Trax…text tracking tool</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Chivo&family=Chivo+Mono&family=Playfair+Display+SC:wght@700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
<meta name="description" content="description">
<style>
* {
outline: cornflowerblue dotted 0.5px;
}
* {
margin: 0;
}
:root {
--_trax-fontFamily-caps: 'Playfair Display', serif;
--_trax-fontFamily-scaps: 'Playfair Display SC', serif;
--_trax-fontFamily-body: 'Chivo', sans-serif;
--_trax-fontFamily-mono: 'Chivo Mono', monospace;
--_trax-textTracking-caps: var(--trax-textTracking-caps, 0.00cap);
--_trax-textTracking-scaps: var(--trax-textTracking-scaps, 0.00ex);
--_trax-textTracking-body: var(--trax-textTracking-body, 0.00em);
--_trax-textTracking-mono: var(--trax-textTracking-mono, 0.00ch);
--_trax-text-measure: var(--trax-text-measure, 66em);
}
body {
box-sizing: content-box;
margin-inline: auto;
text-align: center;
max-inline-size: var(--_trax-text-measure);
padding-inline-start: 1rem;
padding-inline-end: 1rem;
display: flex;
flex-direction: column;
align-items: center;
font-family: var(--_trax-fontFamily-mono);
}
h1 {
font-size: 5rem;
}
h1.caps {
font-family: var(--_trax-fontFamily-caps);
letter-spacing: var(--_trax-textTracking-caps);
text-transform: uppercase;
}
h1.scaps {
font-family: var(--_trax-fontFamily-scaps);
letter-spacing: var(--_trax-textTracking-scaps);
}
.align-self\:flex-start,
.asfs {
align-self: flex-start;
}
/* add range slider code */
</style>
</head>
<body>
<p class="align-self:flex-start">Capitals</p>
<h1 class="caps">Hamburgevons</h1>
<div class="controls">
<label for="trax-textTracking-caps" id="value-caps">0.00</label><span> cap</span>
<input name="trax-textTracking-caps" type="range" min="-0.30" max="0.30" value="0.00" step="0.01" data-uom="cap">
<button>CSS</button>
</div>
<p class="align-self:flex-start">Small Capitals</p>
<h1 class="scaps">Hamburgevons</h1>
<div class="controls">
<label for="trax-textTracking-scaps" id="value-scaps">0.00</label><span> ex</span>
<input name="trax-textTracking-scaps" type="range" min="-0.30" max="0.30" value="0.00" step="0.01" data-uom="ex">
<button>CSS</button>
</div>
<script>
const rangeSliders = document.querySelectorAll('input');
//const labels = document.querySelectorAll('label');
const output1 = document.querySelector('#value-caps');
const output2 = document.querySelector('#value-scaps');
function updateProp(event) {
const uom = this.dataset.uom || '';
document.documentElement.style.setProperty(`--_${this.name}`, this.value + uom);
output1.textContent = this.value;
output2.textContent = this.value;
}
rangeSliders.forEach(input => {
input.addEventListener('input', updateProp);
});
</script>
</body>
</html>
Solution
I don't think the repetition in this case is inelegant. It would likely be best to leave it as is for readability instead of going the route of trying to put together something clever that will essentially do the same thing.
As for the 2 decimals, I believe this would be the easiest way if you don't mind the textContent being a number:
output1.textContent = parseFloat(this.value).toFixed(2);
output2.textContent = parseFloat(this.value).toFixed(2);
Edit:
In response to the comment below, this may be an alternate route to take since more sliders/labels will be added:
const rangeSliders = document.querySelectorAll('input[type="range"]');
const labels = document.querySelectorAll('label');
function updateProp(event) {
const uom = this.dataset.uom || '';
document.documentElement.style.setProperty(`--_${this.name}`, this.value + uom);
const label = labels[Array.from(rangeSliders).indexOf(this)];
label.textContent = parseFloat(this.value).toFixed(2);
}
rangeSliders.forEach((input, index) => {
input.addEventListener('input', updateProp);
labels[index].textContent = parseFloat(input.value).toFixed(2);
});
This will only update the appropriate label based on the index of the current slider, and will fix the float length for you.
Answered By - colcheski
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.