Issue
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>
Solution
Refactored but still blocked on this one bit!
Steps:
- Resize measure (line length) with the draggable handle
- Resize measure (line length) via input
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 😖😖😖
// main element for typesetting output
const typesetOutput = document.getElementById("typesetting");
// font size input and sub label
const textSizeRemInput = document.getElementById("text-size-rem");
textSizeRemInput.addEventListener("input", updateTextSize);
const textSizePxOutput = document.getElementById("text-size-px");
function updateTextSize(event) {
typesetOutput.style.setProperty(
"--_text-size",
`${textSizeRemInput.value}rem`
);
textSizePxOutput.textContent = parseFloat(textSizeRemInput.value * 16).toFixed(1);
}
// font leading input and sub label
const textLeadingInput = document.getElementById("text-leading");
textLeadingInput.addEventListener("input", updateLeading);
const textLeadingPxOutput = document.getElementById("text-leading-px");
function updateLeading(event) {
typesetOutput.style.setProperty(
"--_text-leading",
`${textLeadingInput.value}`
);
textLeadingPxOutput.textContent = parseFloat(textLeadingInput.value * 16).toFixed(1);
}
// text measure input
const textMeasureRemInput = document.getElementById("text-measure-rem");
textMeasureRemInput.addEventListener("input", updateMeasure);
// draggable label (parent) container and reactive text measure input
const textMeasureResize = document.getElementById("text-measure-resize");
function updateMeasure(event) {
document.documentElement.style.setProperty(
"--_text-measure",
`${textMeasureRemInput.value}rem`
);
textMeasureResize.style.width = `${textMeasureRemInput.value}rem`;
}
let observeMeasure = new ResizeObserver(function (mutations) {
const sizeInRem =
mutations[0].contentRect.width /
parseInt(getComputedStyle(document.documentElement).fontSize);
document.documentElement.style.setProperty('--_text-measure', sizeInRem + 'rem');
textMeasureRemInput.value = sizeInRem.toFixed(1);
});
let draggable = textMeasureResize;
observeMeasure.observe(draggable);
// theme switcher
const body = document.body;
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
const invertButton = document.getElementById("invert");
invertButton.addEventListener("click", invertTheme);
function invertTheme(event) {
if (prefersDarkScheme.matches) {
body.classList.toggle("light-theme");
} else {
body.classList.toggle("dark-theme");
}
};
// get code functions
// const copyButton = document.getElementById("copy");
// copyButton.addEventListener("click", functionName);
* {
/* layout debugger */
outline: deeppink dotted 0.5px;
}
:where(html),
:root {
--_text-size: var(--text-size, 1rem);
--_text-leading: var(--text-leading, 1.5);
--_text-measure: var(--text-measure, 80rem);
--_color-light: var(--color-light, white);
--_color-dark: var(--color-dark, black);
--_color-neutral: var(--color-neutral, gray);
--_space: var(--space, 1rem);
font-family: sans-serif;
}
body {
background-color: var(--color-light);
color: var(--_color-dark);
}
@media (prefers-color-scheme: dark) {
body {
background-color: var(--_color-dark);
color: var(--_color-light);
}
}
body.dark-theme {
background-color: var(--_color-dark);
color: var(--_color-light);
}
body.light-theme {
background-color: var(--_color-light);
color: var(--_color-dark);
}
.resizable {
/* inline-size: var(--_text-measure); */
resize: inline;
overflow: scroll;
}
button,
input {
font: inherit;
}
.center {
box-sizing: content-box;
margin-inline: auto;
max-inline-size: var(--_text-measure);
padding-inline-start: 3rem;
padding-inline-end: 3rem;
}
main {
font-size: var(--_text-size);
line-height: var(--_text-leading);
inline-size: var(--_text-measure);
/* width: var(--_text-measure); */
}
.cluster {
display: flex;
flex-wrap: wrap;
gap: var(--_space);
justify-content: flex-start;
align-items: baseline;
}
.vertical-rhythm {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.vertical-rhythm * {
margin-block: 0;
}
.vertical-rhythm *+* {
margin-block-start: calc(var(--_space)/3.14)
}
.justify-content\:space-between {
justify-content: space-between;
}
<body class="center vertical-rhythm">
<nav class="cluster">
<label class="vertical-rhythm">
<h2>Size</h2>
<input id="text-size-rem" type="number" value="1.00" step="0.01" min="0.5" max="3.0">
<h4>rem: <span id="text-size-px">16.0</span> px</h4>
</label>
<label class="vertical-rhythm">
<h2>Leading</h2>
<input id="text-leading" type="number" value="1.50" step="0.01" min="0.01" max="10">
<h4>Unitless: <span id="text-leading-px">24.0</span> px</h4>
</label>
<label class="vertical-rhythm">
<h2>Ground</h2>
<button id="invert">Invert</button>
<h4>Dark∶Light</h4>
</label>
<label class="vertical-rhythm">
<h2>Code</h2>
<button id="copy">Copy</button>
<h4>CSS</h4>
</label>
</nav>
<label id="text-measure-resize" class="resizable vertical-rhythm">
<h2>Measure</h2>
<input id="text-measure-rem" type="number" value="80" step="0.1" min="10" max="150">
<div class="cluster justify-content:space-between">
<h4>rem</h4>
<h4>drag ↘ </h4>
</div>
</label>
<main id="typesetting">
<p>The density of texture in a written or typeset page is called it*s <em>color</em>. 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.</p>
<p>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.</p>
</main>
</body>
Answered By - randomname
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.