How to make a Font Size Slider in React with Material UI
Wondering how to code a slider/toggle to change the font size on the screen? This feature can be seen on sites like the Wall Street Journal (and cough cough, the blog we sell). This article will show you how, step-by-step.
Live Demo of Finished Product
Approach
The goal is to end up with a slider that controls the size of the font displayed on the screen. We’ll be using Material-UI for the slider and React as the framework. For its simplicity, we’ll use React.useState in this demo. You can easily extrapolate the code to use useReducer/useContext. Helpful links:
Note: If using a static-site generator you will run in to some issues. A few extra steps are required. We have a tutorial on how to make a Font Size Slider in Gatsby which you can read here: (coming soon)
Setup — The Slider
The slider itself is your boilerplate slider. Make sure you have MUI installed, npm install @material-ui/core
Next, the slider:
import React from “react”;import { withStyles, makeStyles } from “@material-ui/core/styles”;import Slider from “@material-ui/core/Slider”;import Typography from “@material-ui/core/Typography”;const marks = [{ value: 0},{ value: 25},{ value: 50},{ value: 75},{ value: 100}];const IOSSlider = withStyles({ root: { color: “#3880ff”, height: 2, padding: “15px 0” },})(Slider);export default function CustomizedSlider() { const classes = useStyles(); return ( <Typography gutterBottom>Font Size Slider</Typography> <IOSSlider aria-label=”Font Size Slider” defaultValue={25} marks={marks} step={25} />);}
Note that we set step={25} so that the slider snaps to either 0%, 25%, 50%, 75%, or 100% (the marks we set above).
Setup — React State Values
We’ll need two pieces of state to control our font size and our slider.
const [userFontSize, setUserFontSize] = React.useState(“1rem”);const [sliderTracker, setSliderTracker] = React.useState(0);
- userFontSize will track the preferred font size. We’ll set it to 1rem by default
- sliderTracker tracks the “mark” that the slider is currently set to. We’ll need to track this in conjunction with the fontSize to make sure the slider displays the accurate font size
Setup — The Text
Last but not least, we need to set up the font with some way to change it dynamically based on the users preference. This is where our state comes in. We just need to add an inline style referencing our state value. We’re left with the following:
import React from “react”;import { withStyles, makeStyles } from “@material-ui/core/styles”;import Slider from “@material-ui/core/Slider”;import Typography from “@material-ui/core/Typography”;const marks = [ … ];const IOSSlider = withStyles({ root: { color: “#3880ff”, height: 2, padding: “15px 0” },})(Slider);export default function CustomizedSlider() { const classes = useStyles(); const [userFontSize, setUserFontSize] = React.useState(“1rem”); const [sliderTracker, setSliderTracker] = React.useState(0); return ( <> <Typography gutterBottom>Font Size Slider</Typography> <IOSSlider aria-label=”Font Size Slider” defaultValue={25} marks={marks} step={25} /> <Typography variant=”body1" style={{ fontSize: `${userFontSize}` }}> Sartorial dolore iPhone veniam art party, edison bulb seitan tofu swagmumblecore velit glossier. </Typography> </> );}
The Action — Updating the Font Size
Now for the main event — how do we change the font size when the user updates the slide? Well, all we need to do is update our pieces of state to track the font size and the step that the slider is at. For this, we’ll set up a simple switch statement:
const handleChange = (e, newValue) => { switch (newValue) { case 0: { setUserFontSize(“1rem”); setSliderTracker(0); break; } case 25: { setUserFontSize(“1.19rem”); setSliderTracker(25); break; } case 50: { setUserFontSize(“1.37rem”); setSliderTracker(50); break; } case 75: { setUserFontSize(“1.55rem”); setSliderTracker(75); break; } case 100: { setUserFontSize(“1.75rem”); setSliderTracker(100); break; } default: { break; }}};
Then, we’ll update our slider to call the function when the user releases the slider:
<IOSSlideraria-label=”Font Size Slider”onChangeCommitted={handleChange}defaultValue={sliderTracker}key={sliderTracker}marks={marks}step={25}valueLabelDisplay=”off”/>
- onChangeCommited updates our userFontSize and sliderTracker state
- defaultValue={sliderTracker} sets the sliders default position to our state value
- Importantly, We add a key to the slider to tell React that it’s a controlled component. If you don’t do this, you’ll get an annoying error message that looks like this:
Material-UI: A component is changing the default value state of an uncontrolled Slider after being initialized. To suppress this warning opt to use a controlled Slider.
Wrapup — You’re done!
That’s all it takes! You can check out the final code here
You can extend this to setting the preferred font size in local storage, like: localStorage.setItem('preferred-font-size', '1.1')
and set a useEffect function to read the local storage and set the initial state as that. However, we've excluded that in this post for the sake of simplicity.
Here’s the final product: