View on GitHub


a bunch of vanilla JS practice projects based on JavaScript 30 by WesBos.


demo gif

Back to home page

User stories


Setting up the dropdown options

When speechSynthesis load up, it fires a voiceschanged event. Set up the dropdown options when it loaded.

//create an instance
const message = new SpeechSynthesisUtterance();
//array of all the voice options
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
//select two range sliders, buttons and a text box
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector("#btn_speak");
const stopButton = document.querySelector("#btn_stop");
const displayOption = document.querySelector("#option_display"); //the option we display inside the dropdown
message.text = document.querySelector('[name="text"]').value; //text in the textbox is the content of our speech

function populateVoices() {
 //get all the voice options that browser supports and put them into the array
 voices = this.getVoices();
 //set each of them as option inside the dropdown
 voicesDropdown.innerHTML = voices
  // .filter(voice => voice.lang.includes("en"))
  .map(voice => `<option value="${}">${}(${voice.lang})</option>`)
 //display the current in the dropdown box
 displayOption.value =;

speechSynthesis.addEventListener("voiceschanged", populateVoices);

Select and change the voice

When user picks another voice, we replay the speech with their input value.

function setVoice() {
 message.voice = voices.find(voice => === this.value); //set the voice to user's pick

function toggle(startOver = true) {
 speechSynthesis.cancel(); //stop everything
 if (startOver) {

voicesDropdown.addEventListener("change", setVoice);

Adjust the pitch and rate

options can be the text, the rate or the pitch.

function setOption() {
 message[] = this.value;

options.forEach(option => option.addEventListener("change", setOption));

Play and stop the voice

We use startOver as a flag in toggle.

speakButton.addEventListener("click", toggle);
stopButton.addEventListener("click", () => toggle(false)); //another way: toggle.bind(null,false)