Skip to main content
Dublin Library

The Publishing Project

Configurable Reading Options

 

In Using Sliders in Javascript we saw how we can use sliders to control aspects of a user interface.

This post will expand on the content from the previous post and build a full configuration panel for a long-form reading application.

We'll look at what elements we should customize, how to customize them and finally, provide a script that accomplishes the customization.

What to customize #

Text and background colors
Think of dark mode
It may be good to provide preset color combinations in addition to let users create their own, maybe with a select menu
Input type to use: Color
Font size
Depending on the device and reader conditions readers may want to change the size of the font beyond the default we provide
Input type to use: Slider
Width (measure)
The prefered width of printed text is 75 to 80 characters but, depending on the screen size and orientation we may want to adjust the measure of the text in addition to the line height for the text
Input type to use: Slider
Line Height
Depending on the size of the text and the measure we choose, we may need different line height for users to be comfortable reading
Input type to use: Slider
Hyphenation
Most browsers now support native hyphenation so it shouldn't bee too hard to set it up as long as we remember to set the default language in the root of the document
Input type to use: Checkbox
Font-stack (maybe)
Add default font stacks to use beyond browser defaults
Input type to use: Select Pulldown Menu

How to do it? #

Most of the options are configured based on sliders like we did in the previous post.

Since we don't know what specific values the user will choose, we can't add / remove / toggle classes. Instead we add inline styles to the content section of the page.

As usually, we first capture references to all the HTML elements we want to work with

// Capture all element references
const textContent = document.querySelector('.text-content');
const textParagraph = document.querySelector('.text-content p');
const bgColorInput = document.getElementById('bg-color');
const textColorInput = document.getElementById('text-color');
const fontSizeInput = document.getElementById('font-size');
const widthInput = document.getElementById('width');
const lineHeightInput = document.getElementById('line-height');
const hyphenationInput = document.getElementById('hyphenation');
const fontStackSelect = document.getElementById('font-stack');

There are two kinds of sliders. The first one (fontSize and width) use template literals to interpolate the value we get from the form with the appropriate unit string.

const handleFontSizeChange = (e) => {
    textContent.style.fontSize = `${e.target.value}px`;
};

const handleWidthChange = (e) => {
    textContent.style.width = `${e.target.value}%`;
};

The second type of sliders (lineHeight) is unitless so we can just use the value on its own.

const handleLineHeightChange = (e) => {
    textContent.style.lineHeight = e.target.value;
};

The color inputs (backgroundColor and color)

const handleBgColorChange = (e) => {
    textContent.style.backgroundColor = e.target.value;
};

const handleTextColorChange = (e) => {
    textContent.style.color = e.target.value;
};

The Hypenation toggle takes a little more explanation. Since it's a checkbox we use a ternary operator to set the value of the hyphens attribute.

const handleHyphenationToggle = (e) => {
    textParagraph.style.hyphens = e.target.checked ? 'auto' : 'none';
};

The font selection process uses a select element.

The fonts we use must be available to the user either downloaded by the operating system or loaded with @font-face at-rules.

We should also list the fonts to use in the select element.

const handleFontStackChange = (e) => {
    textContent.style.fontFamily = e.target.value;
};

Finally, we attach the events to the respective elements we captured earlier.

bgColorInput.addEventListener('input', handleBgColorChange);
textColorInput.addEventListener('input', handleTextColorChange);
fontSizeInput.addEventListener('input', handleFontSizeChange);
widthInput.addEventListener('input', handleWidthChange);
lineHeightInput.addEventListener('input', handleLineHeightChange);
hyphenationInput.addEventListener('change', handleHyphenationToggle);
fontStackSelect.addEventListener('change', handleFontStackChange);

A future enhancement would be to check if a property is stored in session storage: if it exists then we use it to set the property for the document and, if it's not, set the property up.

Edit on Github