skip to Main Content

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&nbsp;&searr;&nbsp;</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">&brvbar;</span>et page is called it<span title="66th character" class="color:neutral cursor:crosshair">&brvbar;</span>s <em>color</em>.<span title="75th character" class="color:neutral cursor:crosshair">&brvbar;</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


  1. Chosen as BEST ANSWER

    Refactored but still blocked on this one bit!

    Steps:

    1. Resize measure (line length) with the draggable handle
    2. 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);
    
            function updateMeasure(event) {
                document.documentElement.style.setProperty(
                    "--_text-measure",
                    `${textMeasureRemInput.value}rem`
                );
            }
    
            // draggable label (parent) container and reactive text measure input
            const textMeasureResize = document.getElementById("text-measure-resize");
            // textMeasureResize.addEventListener("input", functionName);
    
            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>&#8198;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>&#8198;px</h4>
            </label>
    
            <label class="vertical-rhythm">
                <h2>Ground</h2>
                <button id="invert">Invert</button>
                <h4>Dark&ratio;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 (EW) &nbsp;&searr;&nbsp;</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>


  2. This will update the CSS variable to the width of the draggable element in px:

    let observeMeasure = new ResizeObserver(function (mutations) {
      document.documentElement.style.setProperty(
        "--_typecsset-text-measure",
         mutations[0].contentRect.width + "px"
      );
    });
    

    Demo:

    // font and lead resizers
    const numberInputs = document.querySelectorAll('input[type="number"]');
    //const measure = document.getElementById("measure");
    //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(3);
    }
    numberInputs.forEach((input, index) => {
      input.addEventListener("input", updateProp);
      //labels[index].textContent = parseFloat(input.value).toFixed(3);
    });
    
    // measure (line length)
    let observeMeasure = new ResizeObserver(function (mutations) {
      document.documentElement.style.setProperty(
        "--_typecsset-text-measure",
         mutations[0].contentRect.width + "px"
      );
    });
    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);
    }
    
    /* 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>Measure</h2>
            <input id="measure" class="width:100% 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&nbsp;&searr;&nbsp;</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">&brvbar;</span>et page is called it<span title="66th character" class="color:neutral cursor:crosshair">&brvbar;</span>s <em>color</em>.<span title="75th character" class="color:neutral cursor:crosshair">&brvbar;</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>

    To convert to rem and set the input to the same value:

    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.querySelector('input');
      input.value = sizeInRem;
    });
    

    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:

    // font and lead resizers
    const numberInputs = document.querySelectorAll('input[type="number"]');
    //const measure = document.getElementById("measure");
    //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(3);
    }
    numberInputs.forEach((input, index) => {
      input.addEventListener("input", updateProp);
      //labels[index].textContent = parseFloat(input.value).toFixed(3);
    });
    
    // measure (line length)
    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.querySelector('input');
      input.value = sizeInRem;
    });
    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);
    }
    
    /* 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>Measure</h2>
            <input id="measure" class="width:100% 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&nbsp;&searr;&nbsp;</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">&brvbar;</span>et page is called it<span title="66th character" class="color:neutral cursor:crosshair">&brvbar;</span>s <em>color</em>.<span title="75th character" class="color:neutral cursor:crosshair">&brvbar;</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>

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search