Structure & style the app
Lesson 1 of 4 — the markup and CSS the rest of the course brings to life.
Semantic structure for a small app and how a stylesheet turns bare markup into something you would actually use.
Prerequisites
None. If you can open a file, you can do this lesson.
Step 112 min
Lay down the markup and the look
GoalA static todo layout exists and looks finished — before a line of behaviour.
Good apps are built shape-first. We write the index.html structure (a form, a <ul>, a footer with filter buttons) and a styles.css that makes it calm and dark. Two rows are hard-coded so you can see the design; lesson 2 replaces them with real, JavaScript-driven items.
<!doctype html><html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Todo</title> <link rel="stylesheet" href="styles.css" /> </head> <body> <main class="app"> <h1>Today</h1> <form id="new-todo"> <input id="title" name="title" placeholder="What needs doing?" autocomplete="off" /> <button type="submit">Add</button> </form> <ul id="list" class="list"> <li><span class="check"></span><span class="title">Read the brief</span><button class="remove" aria-label="Delete">×</button></li> <li class="done"><span class="check"></span><span class="title">Open the editor</span><button class="remove" aria-label="Delete">×</button></li> </ul> <footer class="bar"> <span id="count">1 left</span> <span class="filters"> <button data-filter="all" class="active">All</button> <button data-filter="active">Active</button> <button data-filter="done">Done</button> </span> </footer> </main> <script src="app.js"></script> </body></html>* { box-sizing: border-box; }body { margin: 0; min-height: 100vh; display: grid; place-items: start center; padding: 6vh 16px; font-family: system-ui, -apple-system, sans-serif; background: #0b0e14; color: #e7ecf3;}.app { width: 100%; max-width: 460px; }h1 { font-size: 22px; letter-spacing: -0.01em; margin: 0 0 16px; }#new-todo { display: flex; gap: 8px; margin-bottom: 18px; }#title { flex: 1; padding: 11px 14px; border-radius: 10px; border: 1px solid #232a36; background: #11151c; color: inherit; font-size: 15px;}#title:focus { outline: none; border-color: #6ea8fe; }#new-todo button { padding: 0 18px; border-radius: 10px; border: 1px solid #2b3340; background: #6ea8fe; color: #0b0e14; font-weight: 600; cursor: pointer;}.list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }.list li { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 10px; background: #11151c; border: 1px solid #1c2330;}.check { width: 18px; height: 18px; flex: none; border-radius: 999px; border: 1.5px solid #3a4456; cursor: pointer;}.list li.done .check { background: #4ade80; border-color: #4ade80; }.list li.done .title { color: #5b6675; text-decoration: line-through; }.title { flex: 1; }.remove { border: none; background: none; color: #5b6675; font-size: 20px; line-height: 1; cursor: pointer;}.remove:hover { color: #f87171; }.bar { display: flex; justify-content: space-between; align-items: center; margin-top: 16px; font-size: 13px; color: #8b93a3;}.filters { display: flex; gap: 4px; }.filters button { border: 1px solid transparent; background: none; color: inherit; padding: 4px 10px; border-radius: 8px; cursor: pointer;}.filters button.active { border-color: #2b3340; color: #e7ecf3; }// Step 2 brings this page to life.// For now the rows in index.html are hard-coded so you can see the design.Before lesson 2
In Code, change the <h1> from "Today" to your own list name and re-run the preview.
Concepts covered · 1
More like this
Persist & filter
Save the list to localStorage so it is still there tomorrow, and wire the All / Active / Done filters. This is the lesson that turns a toy into something you would actually use.
Write the spec the model can hit
A prompt is a specification. The difference between a junior and a senior prompt is the constraints a senior names that a junior leaves to chance. This lesson turns your architecture sketch into a prompt that produces reviewable code.
Add todos with JavaScript
Wire the form so typing and pressing Add creates a real item. You will hold the todos in an array and render the list from it — the pattern every UI framework formalises later.
Liked this one?
Pass it on
Discussion
Be the first to ask
Your questions stay private with the team. We can pin answers to share with everyone.
Sign in to ask a question privately on this tutorial.
Sign inNo pinned answers yet for this tutorial.