JavaScript Basics
HTML gives your page structure. CSS gives it style. JavaScript gives it behavior — it responds to what the user does. When someone clicks a button, scrolls the page, or types into a field, JavaScript is what makes something happen in response.
Key Concepts
The DOM
When a browser loads your HTML, it builds an internal map of every element on the page — the headings, paragraphs, buttons, divs. This map is called the DOM (Document Object Model). JavaScript uses the DOM to find elements and change them. When you see code like document.getElementById('my-button'), that's JavaScript reaching into the DOM to grab a specific element so it can do something with it.
Variables
A variable stores a value so you can refer to it by name later. In the snippets you'll see const, which creates a variable that won't be reassigned:
const button = document.getElementById('my-button');
Now button refers to that element, and you can use it throughout the rest of the script without searching for it again.
Selecting Elements
There are two common ways to grab an element from the DOM:
document.getElementById('my-button') // finds the element with id="my-button"
document.querySelector('article') // finds the first element matching a CSS selector
For either to work, the element needs to exist in your HTML with a matching id or tag/class.
Event Listeners
An event listener watches for something to happen — a click, a scroll, a keypress — and runs a block of code when it does. The pattern is always the same:
button.addEventListener('click', function () {
// code that runs when the button is clicked
});
Read it as: "When button gets a click, run this function." You'll see this pattern in almost every snippet.
Functions
A function is a named block of code you can run on demand. You define it once and call it when needed:
function doSomething() {
// code goes here
}
doSomething(); // calling the function runs the code inside
Some functions in the snippets are anonymous (no name) and passed directly into an event listener. Others are named and call themselves repeatedly — you'll see both.
Comments
Any line starting with // is a comment — ignored by the browser, written for the human reading the code. The snippets use comments to explain what each section does. Read them before you start adapting the code.
// This is a comment — the browser ignores it
const headline = document.getElementById('headline'); // this part runs
Snippet Library
Each snippet below is a self-contained interactive element ready to add to your impact article. Pick one for Part 1. Use them as a starting point or inspiration for Part 3.
For each snippet:
- Add the HTML where indicated
- Paste the CSS into your stylesheet
- Paste the JavaScript before the closing
</body>tag - Customize the parts marked ← change this
1. Reading Time Estimator
Displays an estimated reading time at the top of your article — like you see on Medium.
What to customize: The selector for your article text, and where the estimate appears.
HTML — add this where you want the reading time to appear (e.g., inside your <header> or below your article headline):
<p id="reading-time"></p>
CSS:
#reading-time {
font-size: 0.9rem;
color: #666; /* ← change to match your color scheme */
margin-bottom: 1rem;
}
JavaScript:
// Reading Time Estimator
// Counts words in your article and estimates reading time at 200 words per minute
const articleText = document.querySelector('article'); // ← change if your article uses a different selector
const readingTimeDisplay = document.getElementById('reading-time');
if (articleText && readingTimeDisplay) {
const words = articleText.innerText.trim().split(/\s+/).length; // count words
const minutes = Math.ceil(words / 200); // 200 words per minute
readingTimeDisplay.textContent = `${minutes} min read`;
}
2. Dark Mode Toggle
A button that switches your page between light and dark mode. Your visitors choose how they want to read.
What to customize: The dark mode colors, and the button's placement and label.
HTML — add a toggle button somewhere visible, like your header:
<button id="dark-mode-toggle">Dark mode</button>
CSS:
/* Dark mode styles — applied when <body> has the "dark" class */
body.dark {
background-color: #121212; /* ← choose your dark background */
color: #e0e0e0; /* ← choose your dark text color */
}
#dark-mode-toggle {
cursor: pointer;
padding: 0.4rem 0.8rem;
border: 1px solid currentColor;
background: transparent;
color: inherit;
border-radius: 4px;
font-size: 0.9rem;
}
JavaScript:
// Dark Mode Toggle
// Adds or removes a "dark" class on the body when the button is clicked
const toggleButton = document.getElementById('dark-mode-toggle');
toggleButton.addEventListener('click', function () {
document.body.classList.toggle('dark'); // adds "dark" if missing, removes if present
// Update button label based on current mode
if (document.body.classList.contains('dark')) {
toggleButton.textContent = 'Light mode'; // ← change label text if you want
} else {
toggleButton.textContent = 'Dark mode'; // ← change label text if you want
}
});
3. Scroll Progress Bar
A thin bar at the top of the page that fills as the user scrolls down — shows how far through the article they are.
What to customize: The bar's color and height.
HTML — add this as the very first element inside <body>:
<div id="progress-bar"></div>
CSS:
#progress-bar {
position: fixed; /* stays at the top as you scroll */
top: 0;
left: 0;
height: 4px; /* ← adjust thickness */
width: 0%; /* starts empty — JavaScript fills it */
background-color: #0066cc; /* ← change to your accent color */
z-index: 100;
transition: width 0.1s ease;
}
JavaScript:
// Scroll Progress Bar
// Updates the bar width as a percentage of how far down the page the user has scrolled
const progressBar = document.getElementById('progress-bar');
window.addEventListener('scroll', function () {
const scrollTop = window.scrollY; // how far scrolled
const docHeight = document.body.scrollHeight - window.innerHeight; // total scrollable height
const progress = (scrollTop / docHeight) * 100; // percentage
progressBar.style.width = progress + '%';
});
4. Copy Link Button
A button that copies your article's URL to the clipboard — handy for sharing. Shows a brief confirmation when it works.
What to customize: The button label and confirmation message.
HTML — add wherever you'd like the button to appear (footer is a natural spot):
<button id="copy-link">Copy link</button>
CSS:
#copy-link {
cursor: pointer;
padding: 0.4rem 0.8rem;
border: 1px solid currentColor;
background: transparent;
color: inherit;
border-radius: 4px;
font-size: 0.9rem;
}
JavaScript:
// Copy Link Button
// Copies the current page URL to the clipboard and briefly changes the button label
const copyButton = document.getElementById('copy-link');
copyButton.addEventListener('click', function () {
navigator.clipboard.writeText(window.location.href).then(function () {
copyButton.textContent = 'Copied!'; // ← change confirmation message if you want
// Reset label after 2 seconds
setTimeout(function () {
copyButton.textContent = 'Copy link'; // ← must match your original label above
}, 2000);
});
});
5. Typewriter Effect
Your article headline types itself out letter by letter when the page loads.
What to customize: Which element gets the effect, and how fast it types.
HTML — no changes needed. The snippet targets your existing headline. Make sure your <h1> has an id:
<h1 id="headline">Your Article Title Here</h1>
CSS:
/* The cursor that blinks after the text */
#headline::after {
content: '|';
animation: blink 0.7s step-end infinite;
}
@keyframes blink {
50% { opacity: 0; }
}
JavaScript:
// Typewriter Effect
// Clears the headline text, then types it back out one character at a time
const headline = document.getElementById('headline'); // ← change if your h1 has a different id
const fullText = headline.textContent; // saves the original text
const typingSpeed = 60; // ← milliseconds per character (lower = faster)
headline.textContent = ''; // clear the headline so we can type it back
let index = 0;
function typeNextCharacter() {
if (index < fullText.length) {
headline.textContent += fullText[index]; // add one character
index++;
setTimeout(typeNextCharacter, typingSpeed); // schedule the next character
}
}
typeNextCharacter(); // start typing