Frontend Repair Tasks
Three original HTML, CSS, and JavaScript editing exercises with starter files, worked solutions, and browser checks.
Research checked: 13 November 2026. Internship candidates describe modifying supplied HTML/CSS/JavaScript rather than building a React application. The exercises below are original practice, not copied assessment files.
The minimum you need
HTML defines elements and attributes: an id identifies one element; a class can be shared. A boolean attribute such as disabled is active whenever present: disabled="false" still disables the button. Remove the attribute to enable it.
CSS selects elements: #save matches an ID, .action matches a class. Know color, background, padding, margin, border, and the box model. Padding is inside the border; margin is outside it. Match the requested selector so existing elements get the style.
JavaScript selects a DOM element with document.getElementById() or querySelector(). Read input through .value; render plain text with .textContent. Use addEventListener('input', ...) for changes while typing and 'click' for buttons. Create a node with createElement, then append it; register handlers after the elements exist, as these files do by placing scripts at the end. Number(input.value) converts a numeric input string; + on two strings concatenates.
How to practise: copy a starter block into an .html file and open it in a browser. All three languages are included in one file for convenience; if the OA supplies separate HTML, CSS, and JS files, make the corresponding edits in those files. Preserve existing IDs and unrelated behavior. Use developer tools to catch syntax errors. Answers are complete replacement files.
F1 — Live word counter
- Give the textarea class
editorand style it withpadding: 8px. - On every input event, show the number of whitespace-separated words in
#words. - Empty and whitespace-only input must show zero; repeated spaces and newlines are separators.
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Word counter</title>
<style>/* TODO: .editor padding */</style>
<label for="draft">Draft</label><textarea id="draft"></textarea>
<output id="words" aria-live="polite">0</output>
<script>
const draft = document.getElementById('draft');
const words = document.getElementById('words');
// TODO: update the output as the user types.
</script></html>F1 solution and browser checks
Trim first, then special-case an empty result. Splitting an empty string directly would produce an array with one empty entry and falsely count one word.
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Word counter</title>
<style>.editor { padding: 8px; }</style>
<label for="draft">Draft</label><textarea id="draft" class="editor"></textarea>
<output id="words" aria-live="polite">0</output>
<script>
const draft = document.getElementById('draft');
const words = document.getElementById('words');
draft.addEventListener('input', () => {
const text = draft.value.trim();
words.textContent = String(text === '' ? 0 : text.split(/\s+/).length);
});
</script></html>Type hello → 1, hello world → 2, then use a newline and tabs. Clear the input and try spaces only: both must show 0. Check computed padding is 8px. Hyphenated words and punctuation are part of a token under this exercise's whitespace rule.
- Complete F1 and test whitespace-only input and deletion.
F2 — Password visibility toggle
- Enable the existing toggle button by removing
disabled. - Give it class
actionwith background#5b21b6and white text. - Clicking toggles the input type between
passwordandtext, changes the label between Show and Hide, and updatesaria-pressedto reflect visibility. Preserve the typed value.
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Password toggle</title>
<style>/* TODO: .action colors */</style>
<label for="password">Password</label><input id="password" type="password">
<button id="toggle" type="button" disabled aria-pressed="false">Show</button>
<script>
// TODO: toggle visibility, label, and pressed state.
</script></html>F2 solution and browser checks
Calculate the next state from the current input type. Setting type preserves .value; do not replace the whole input node.
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Password toggle</title>
<style>.action { background: #5b21b6; color: white; }</style>
<label for="password">Password</label><input id="password" type="password">
<button id="toggle" class="action" type="button" aria-pressed="false">Show</button>
<script>
const password = document.getElementById('password');
const toggle = document.getElementById('toggle');
toggle.addEventListener('click', () => {
const show = password.type === 'password';
password.type = show ? 'text' : 'password';
toggle.textContent = show ? 'Hide' : 'Show';
toggle.setAttribute('aria-pressed', String(show));
});
</script></html>Type a value, click twice, and confirm the value remains unchanged. Empty input can still toggle. Confirm the button is enabled, has the requested colors, and is keyboard-operable.
- Complete F2 and verify repeated toggles preserve the password.
F3 — Add and remove tasks
- Give the task list class
taskswithpadding-left: 24px. - On form submission, trim the input; ignore a blank value. Append a list item containing that text and a Remove button, then clear and refocus the input.
- Remove must delete only its own list item. Display user-entered text literally, including characters such as
<and>.
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Tasks</title>
<style>/* TODO: .tasks padding-left */</style>
<form id="task-form">
<label for="task">Task</label><input id="task">
<button type="submit">Add</button>
</form>
<ul id="list"></ul>
<script>
// TODO: handle form submit; create and append elements.
</script></html>F3 solution and browser checks
Prevent the form's navigation, use textContent for text, and capture each item's node in its own Remove handler. innerHTML would interpret markup and is unnecessary here.
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Tasks</title>
<style>.tasks { padding-left: 24px; }</style>
<form id="task-form">
<label for="task">Task</label><input id="task">
<button type="submit">Add</button>
</form>
<ul id="list" class="tasks"></ul>
<script>
const input = document.getElementById('task');
const list = document.getElementById('list');
document.getElementById('task-form').addEventListener('submit', (event) => {
event.preventDefault();
const text = input.value.trim();
if (!text) return;
const item = document.createElement('li');
const label = document.createElement('span');
label.textContent = text;
const remove = document.createElement('button');
remove.type = 'button';
remove.textContent = 'Remove';
remove.addEventListener('click', () => item.remove());
item.append(label, ' ', remove);
list.append(item);
input.value = '';
input.focus();
});
</script></html>Add two tasks, remove the first, and check the second remains. Try Enter and the Add button, blank input, and a literal string such as <b>read</b>. It should display those characters without creating a bold element. Check the input clears and regains focus after adding.
- Complete F3 and test blank input, Enter, literal markup, and removing one of two tasks.
Targeted resources
- MDN scripting basics: choose variables, conditionals, functions, and DOM scripting; avoid a framework detour.
- MDN introduction to events: focus on
addEventListener, event objects, andpreventDefault. - MDN CSS box model: review padding, border, and margin before styling drills.
Next: save the two additional frontend tasks in the mixed mocks for your timed practice.