I’m working on a little typography app and have hit a blocker. I’ve extracted to core code into a pen, i.e., there are other inputs, buttons in the UI. Hence, why I’m using querySelectorAll(‘input[type="number"]’), etc.
Goal is for the draggable element to update the text measure (line length) and BIND to the number input, by updating the CSS prop:
--_typecsset-text-measure
I have a resize observer logging the draggable element to console but I’m way out of my depth at this point!
I set up a Pen: https://codepen.io/timpish/full/abMdBay
// font, leading, measure (line length) input resizers
const numberInputs = document.querySelectorAll('input[type="number"]');
function updateProp(event) {
const uom = this.dataset.uom || '';
document.documentElement.style.setProperty(`--_${this.name}`, this.value + uom);
}
numberInputs.forEach((input, index) => {
input.addEventListener('input', updateProp);
});
// measure drag (.resizable) an update #measure
let observeMeasure = new ResizeObserver(function (mutations) {
const sizeInRem = mutations[0].contentRect.width / parseInt(getComputedStyle(document.documentElement).fontSize); document.documentElement.style.setProperty('--_typecsset-text-measure', sizeInRem + 'rem');
const input = document.getElementById('measure');
input.value = sizeInRem.toFixed(1);
});
let drag = document.querySelector(".resizable");
observeMeasure.observe(drag);
/* globals */
*,
*::before,
*::after {
box-sizing: border-box;
}
*:not(main p) {
margin: 0;
padding: 0;
}
:where(html) {
--_typecsset-body-fontSize: var(--typecsset-base-fontSize, 1rem);
--_typecsset-body-lineHeight: var(--typecsset-base-lineHeight, 1.5);
--_typecsset-color-dark: var(--typecsset-color-dark, hsl(0, 0%, 0%));
--_typecsset-color-light: var(--typecsset-color-light, hsl(0, 0%, 100%));
--_typecsset-color-neutral: var(--typecsset-color-neutral, hsl(0, 0%, 50%));
--_typecsset-recursive-caslAxis: var(
--typecsset-recursive-caslAxis,
"CASL" 0
);
--_typecsset-recursive-crsvAxis: var(
--typecsset-recursive-crsvAxis,
"CRSV" 0.5
);
--_typecsset-recursive-monoAxis: var(
--typecsset-recursive-monoAxis,
"MONO" 0
);
--_typecsset-recursive-slntAxis: var(
--typecsset-recursive-slntAxis,
"slnt" 0
);
--_typecsset-recursive-wghtAxis: var(
--typecsset-recursive-wghtAxis,
"wght" 400
);
--_typecsset-text-measure: var(--typecsset-text-measure, 80rem);
font-variation-settings: var(--_typecsset-recursive-monoAxis),
var(--_typecsset-recursive-caslAxis), var(--_typecsset-recursive-wghtAxis),
var(--_typecsset-recursive-crsvAxis), var(--_typecsset-recursive-slntAxis);
font-family: Recursive, sans-serif;
line-height: 1;
}
body {
background-color: var(--_typecsset-color-light);
color: var(--_typecsset-color-dark);
margin-top: 1rem !important;
}
#measure {
inline-size: var(--_typecsset-text-measure);
/* width: var(--_typecsset-text-measure); */
}
/* dark mode */
@media (prefers-color-scheme: dark) {
body {
background-color: var(--_typecsset-color-dark);
color: var(--_typecsset-color-light);
}
}
main {
font-family: "Alegreya", serif;
font-size: var(--_typecsset-body-fontSize);
line-height: var(--_typecsset-body-lineHeight);
}
/* elements */
h2,
h4,
input,
main {
padding-left: 0.2rem !important;
padding-right: 0.2rem !important;
}
input {
padding-right: 0 !important;
}
h1,
h2,
h3,
h4 {
line-height: 0.9 !important;
}
h2,
h4 {
color: var(--_typecsset-color-neutral) !important;
font-size: 15px;
}
h2 {
/* 'cap' unit for capital letters. Safari's jank. */
letter-spacing: 0.06cap;
text-transform: uppercase;
--_typecsset-recursive-wghtAxis: var(
--typecsset-recursive-wghtAxis,
"wght" 600
);
font-variation-settings: var(--_typecsset-recursive-wghtAxis);
}
/* sub header below inputs/buttons */
h4 {
font-weight: normal;
text-transform: none;
}
/* drag */
h4 + h4 {
color: currentColor !important;
padding-bottom: 0.1rem;
}
input {
background-color: inherit;
color: inherit;
font: inherit;
font-size: 0.95rem;
border-top: 1.618px solid var(--_typecsset-color-neutral);
border-bottom: 1.618px solid var(--_typecsset-color-neutral);
border-right: none;
border-left: none;
border: 1.618px solid var(--_typecsset-color-neutral);
border-radius: 3px;
/* box-shadow: inset 0.25rem 0.25rem 0 var(--_typecsset-color-neutral) */
padding: ;
}
/* blockquote inside main */
blockquote {
hanging-punctuation: first last;
&::before {
content: "201C";
}
&::after {
content: "201D";
}
&::before,
&::after {
color: var(--_typecsset-color-neutral);
}
}
/* layout primitives */
.center {
box-sizing: content-box;
margin-inline: auto;
max-inline-size: var(--_typecsset-text-measure);
padding-inline-start: 1rem;
padding-inline-end: 1rem;
}
.cluster {
display: flex;
flex-wrap: wrap;
gap: var(--space, 0.618rem);
/* use scale */
justify-content: space-between;
align-items: center;
}
.icon-ruler {
background-image: url("icons.svg#icon-ruler-view");
background-origin: content-box;
background-position: top left;
background-repeat: repeat-x;
background-size: 3.1rem 1rem;
}
.rhythm {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
[class^="rhythm"] > * {
margin-block: 0;
}
.rhythm-xs > * + * {
margin-block-start: 0.2rem;
}
.rhythm-s > * + * {
margin-block-start: 0.309rem;
}
.rhythm-m > * + * {
margin-block-start: 0.618rem;
}
.rhythm-l > * + * {
margin-block-start: 1.236rem;
}
.rhythm-xl > * + * {
margin-block-start: 1.857rem;
}
/* utils */
.typeface-alegreya {
font-family: "Alegreya", serif;
}
.color:neutral {
color: var(--_typecsset-color-neutral);
}
.cursor:crosshair {
cursor: crosshair;
}
.resizable {
resize: inline;
overflow: scroll;
}
.width:100% {
width: 100% !important;
}
/*debugger */
* {
outline: cornflowerblue dotted 0.5px;
}
<body class="center">
<nav class="rhythm-m">
<section class="resizable">
<label class="rhythm-xs">
<h2>Text Measure</h2>
<input id="measure" class="icon-ruler steppers-none" type="number" value="80" step="1" min="10" max="150" data-uom="rem" name="typecsset-text-measure">
<div class="cluster">
<h4>rem</h4>
<h4>drag ↘ </h4>
</div>
</label>
</section>
</nav>
<main class="typeface-alegreya">
<p>
<blockquote>The density of texture in a written or types<span title="45th character" class="color:neutral cursor:crosshair">¦</span>et page is called it<span title="66th character" class="color:neutral cursor:crosshair">¦</span>s <em>color</em>.<span title="75th character" class="color:neutral cursor:crosshair">¦</span> This has nothing to do with red or green ink; it refers only to the darkness or blackness of the letterforms in mass. Once the demands of legibilty and logical order are satisfied, <em>eveness of color</em> is the typographer's normal aim. And color depends on four things: the design of the type, the spacing between the letters, the spacing between the words, and the spacing between the lines. None is independent of the others.</blockquote>
</p>
<p>
<blockquote>Anything from <em>45 to 75</em> characters is widely regarded as a satisfactory length of line for a single-column page set in a serifed text face in a text size. The 66-character line (counting both letters and spaces) is widely regarded as ideal. For multiple column work, a better average is 40 to 50 characters.</blockquote>
</p>
</main>
</body>
</html>
2
Answers
Refactored but still blocked on this one bit!
Steps:
Result: everything (body, main) BUT #text-measure-resize (label) and #text-measure-rem (input) resizes! --_text-measure CSS prop is defined at :root and applied to body and main 😖😖😖
This will update the CSS variable to the width of the draggable element in px:
Demo:
To convert to rem and set the input to the same value:
Obviously you’ll have to figure out how to actually get a reference to the input instead of just querying for the first one, but this should give you the idea. I’m guessing you’ll also want to set the draggable element’s size when updating the input, which I’m sure you can figure out.
Demo: