← Front-End Developer — all chapters  ·  Kelick Tech Hub

Chapter 28 — Component Thinking

Section 1 — What a component is

A component is a self-contained piece of an interface, such as a button, a card, a navigation bar, or a comment, that can be described, built, and reused as a single unit. It bundles its markup, its styling, and often its behaviour together, so that wherever the component appears, it looks and acts the same way. Thinking in components means seeing a page not as one long document, but as a collection of such units fitted together. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Components help because interfaces repeat themselves. A site with twenty article cards does not need twenty separately invented designs; it needs one card design used twenty times. That reuse keeps the site consistent, makes changes cheap, and lets a team divide work by component rather than by page. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, an article card component might always contain an image, a heading, a short summary, and a link, arranged the same way each time. Change the card once, and every article listing on the site improves together. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is calling every element a component. A single heading is not a component; a card, a form field group, or a navigation bar is, because it combines several parts into a unit with a clear purpose. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 2 — Seeing a page as components

Seeing a page as components means drawing mental boxes around its parts before writing code: the header is one box, the hero is another, the list of cards is a repeated box, and the footer is another. Each box should have a name, a purpose, and a clear boundary: what belongs inside it, and what belongs outside it. This sketching step, often done on paper or in a design tool, prevents the common beginner pattern of writing markup top to bottom with no plan for reuse. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

The benefit appears when a design changes. If the header is a component, changing it once changes it everywhere, and a new page can be assembled from existing components instead of being built from scratch. Pages become compositions, not inventions, and that composition is faster and more reliable. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, sketch a blog homepage and box the header, the featured article, each article card, the sidebar, and the footer. The article cards are the same component repeated, while the featured article may be a larger variant of the same idea. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is drawing boxes that are too large, such as one box for a whole page, or too small, such as a box for every word. Aim for boxes that match a recognisable piece of the interface. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 3 — One job per component

A component should do one job well: a button triggers an action, a card presents an item, a search box collects a query. When a component tries to do several unrelated jobs, it becomes hard to understand, hard to test, and hard to reuse, because every use carries the baggage of jobs it does not need. This is the single-responsibility idea applied to interfaces, and it is one of the most useful rules in front-end work. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

One job does not mean one element. A card does several small things, such as showing an image and a title, but they all serve one job: presenting an item. The test is whether you can describe the component's job in one sentence without using the word and to join unrelated purposes. If the sentence needs several unrelated clauses, the component is probably doing too much. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a comment component's job is to present one comment: the author's name, the text, and the date. If it also handles moderation, reporting, and editing, those are separate jobs that deserve separate components or controls. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is letting a component grow by accretion, adding one more feature each time a new requirement appears, until the original job is buried. Split it before it becomes unmanageable. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 4 — Props: inputs to a component

Props, short for properties, are the inputs a component accepts so that one component definition can produce many different outputs. A card component might accept a title, an image, and a summary as props, and each use supplies different values. The component's structure stays the same, while its content changes, which is exactly how one card design serves twenty different articles. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Props make the boundary of a component explicit: to use it, you must know what inputs it needs and what it will do with them. Good components accept only the props they need, give them clear names, and behave sensibly when an optional prop is missing. That explicitness is what lets a teammate use your component without reading its internal code. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a button component might accept a label and a style variant as props, so <Button label="Save" variant="primary" /> and <Button label="Cancel" variant="secondary" /> produce two buttons from one definition, each with the correct wording and prominence. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is passing too many props, or props that the component merely forwards to another component without using them. That suggests the boundary is in the wrong place and the components need reorganising. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 5 — State: what a component remembers

State is the information a component remembers between interactions: whether a menu is open, what a user has typed, which tab is selected, or whether an item is marked as favourite. Unlike props, which come from outside, state lives inside the component and changes in response to user actions. When state changes, the component's appearance should update to match, so the screen always reflects the current state. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

Understanding state is essential because most interactive behaviour is state plus display. A toggle button is not two different buttons; it is one button whose state is on or off, and whose appearance follows that state. Designing in those terms keeps behaviour predictable: list every state a component can be in, decide what each state looks like, and make sure every action moves the component to the correct next state. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, an accordion section's state might be open or closed, and clicking its heading flips the state, showing or hiding its content. There are only two states to design and test, which is far simpler than treating open and closed as unrelated layouts. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is storing the same information in two places, so that one copy changes and the other does not, and the screen shows a contradiction. Keep each piece of state in exactly one place. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 6 — Composition: components inside components

Composition means building larger components from smaller ones, like nesting boxes inside boxes. A page is composed of sections, a section is composed of cards, and a card is composed of an image, a heading, and a button. Each level only needs to understand the level directly below it, which keeps any single component small enough to understand and test on its own. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Composition is more flexible than inheritance or copying, because the same small components can be combined in different ways for different pages. A button component can appear in a card, a form, a modal, and a navigation bar without being rewritten, and improving the button improves all of those places at once. That is the practical payoff of component thinking. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a product page might compose a gallery component, a details component, and a reviews component, where the reviews component itself composes many review components, each containing an author component and a rating component. The hierarchy mirrors the page's visual structure. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is composing so deeply that a simple page requires tracing through ten levels to find where text is rendered. Keep the hierarchy as shallow as the design allows. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 7 — Variants: one component, many forms

A variant is a recognised form of a component, such as a primary and a secondary button, a large and a small card, or an error and a success alert. Variants share the component's structure and behaviour but differ in appearance or emphasis, and they are chosen by a prop or a modifier class. Naming variants explicitly prevents the slow invention of near-duplicate components that differ only in colour or size. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

Variants should be few and meaningful. A button with primary, secondary, and danger variants covers most needs; a button with twelve variants suggests the design system has no hierarchy. Each variant should exist because a real use case needs it, not because it seemed possible. Document the variants and when to use each one, so a team chooses consistently. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a primary button is the main action on a view, a secondary button is an alternative action, and a danger button is a destructive action. Using those three consistently teaches users what to expect before they read the button's text. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is creating a variant for a single special case instead of asking whether the special case is really a different component, or whether the existing component already covers it. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 8 — Slots and children

Slots, also called children, are places inside a component where the user of the component can supply their own content. A modal component, for example, might define its frame, its close button, and its overlay, but leave the body as a slot that each use fills with different content. This makes the component flexible without making it complicated: the frame is fixed, the content varies. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

Slots are the answer to a common design tension. If a component accepts only fixed props, it cannot handle content that is itself made of components, such as a card body containing a list and a button. If it accepts arbitrary children, it can, while still guaranteeing the surrounding structure. Learning when to use a prop and when to use a slot is a key component skill: props for simple values, slots for rich, structured content. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a layout component might have a header slot, a main slot, and a footer slot, so different pages supply different headers while sharing the same overall structure. The layout guarantees the arrangement; the slots supply the content. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is making every part of a component a slot, which leaves the component with no identity of its own. A component should own its structure and delegate only the content that genuinely varies. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 9 — Presentational and container components

A useful distinction separates presentational components, which focus on how things look, from container components, which focus on data and behaviour. A presentational component receives data through props and renders it, without knowing where the data came from. A container component fetches or manages data and passes it down to presentational components, without caring much about the exact markup. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

This separation is not a strict rule, but a habit that keeps code understandable. Presentational components are easy to test and reuse, because they depend only on their props. Container components are easy to reason about, because their job is data and state, not layout details. When a component mixes both concerns heavily, changes to data logic risk breaking the layout, and vice versa. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a user list container might load a list of users and pass it to a presentational list component, which renders each user as a card. The card knows nothing about loading or errors; the container knows nothing about card spacing. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is treating this distinction as a law and creating a container for every tiny component. Use it where it clarifies the code, not as a ritual applied to everything. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 10 — Breaking a design into components

Breaking a design into components starts with the visual design, not with code. Look at the design and identify repeated elements first, because repetition is the strongest signal of a component. Then identify large, distinct regions, such as the header and footer, which are components even if they appear once, because they have a clear job and boundary. Then look for elements that change state, such as menus and tabs, because stateful pieces deserve their own components. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

A practical method is to draw boxes on the design, name each box, and list its props: what varies between uses, and what stays the same. If two boxes share most of their structure but differ in a few values, they are one component with props. If a box contains several distinct boxes, it is a composed component. This exercise, done before coding, prevents a great deal of rework. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, given a news homepage design, you might identify a header, a featured story, a story card used many times, a newsletter signup, and a footer. The story card is the obvious reusable component; the featured story may be a variant of it. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is starting to code before identifying components, and then discovering halfway through that a repeated pattern was built three different ways. Ten minutes of boxing saves hours of refactoring. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 11 — Component boundaries and APIs

A component's API is the set of props, slots, and events it offers to the rest of the system, and designing that API well is the heart of component thinking. A good API is small, clear, and hard to misuse: prop names say what they mean, required props are few, and the component behaves sensibly when optional props are omitted. A poor API is large, ambiguous, and full of special cases that only its author understands. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Think of a component API as a promise to future users, including yourself. Changing it later breaks every use, so invest thought early in names and defaults. Ask: what would a new team member expect this prop to be called? What is the most common use, and does it require the fewest props? Can this component be used without reading its source code? If the answers are unsatisfying, revise the API before the component spreads. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a modal component with props for title, content, and an on-close action is easy to use, while one that requires ten props for every use, including internal details, is not. The simpler API will be used correctly more often. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is exposing internal implementation details as props, such as a class name that only makes sense inside the component. Keep the API at the level of intention, not implementation. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 12 — Reusability versus over-abstraction

Reusability is valuable, but over-abstraction, extracting a component before a pattern has genuinely repeated, is a real cost. A component extracted too early often has an awkward API, because its designer guessed at what would vary instead of observing it. When the second use arrives, the abstraction may not fit, and the developer faces a choice between contorting the new use or rewriting the component. Both waste the time the abstraction was meant to save. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

A sensible rule is to wait until a pattern has appeared two or three times before extracting it, and to extract from real examples rather than from imagination. This is sometimes called the rule of three. It keeps components grounded in actual needs, and it means the first two uses can be simple and slightly duplicated, which is cheaper than a wrong abstraction. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, if two pages have similar but not identical banners, build both directly first. When a third banner appears, the common structure and the real variations will be obvious, and the extracted component will fit all three. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is building a grand, configurable component that can do everything, in anticipation of needs that never arrive. Flexibility that is never used is complexity that is always paid for. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 13 — Component naming

Component names matter because they are how a team talks about the interface. A good name says what the component is or does, in words the team already uses: ArticleCard, SearchBox, SiteHeader. A poor name is vague, such as Box or Wrapper, or technical, such as DivContainer, because it tells a reader nothing about the component's purpose. Names should be consistent in style, usually starting with a capital letter and using the project's language for the domain. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

Naming also reveals design problems. If you cannot name a component clearly, its job may be unclear, and it may be doing too much or too little. Renaming is cheap early and expensive late, so treat a naming struggle as a signal to rethink the boundary, not as a trivial wording problem. Keep a list of component names in the project, so new components do not duplicate an existing name with a different meaning. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, in a shop, ProductCard is a clear name, while Card is ambiguous once the site also has article cards and user cards. The qualifier prevents confusion and makes searching the codebase reliable. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is naming components after their appearance, such as BlueBox, which breaks when the design changes colour. Name for purpose, not for current styling. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 14 — Styling a component

Styling a component means deciding how its styles are scoped so that they affect the component and not the rest of the page. In plain HTML and CSS, this is done with class names that are specific to the component, such as prefixing classes with the component's name. In component frameworks, styles may be scoped automatically, so a rule written for a card cannot leak into a different card or a page header. Either way, the goal is the same: a component's styles should travel with it. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Scoped styles make components safe to move. A card taken from one page to another should look the same, without picking up stray rules from its new surroundings and without breaking the new page's layout. That safety depends on avoiding overly broad selectors, such as styling all headings globally when you only meant headings inside a card, and on keeping component styles in one place rather than scattered across files. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a card's styles might all begin with the card class, such as .card-title and .card-body, so that a heading elsewhere on the page is untouched. That naming convention is a simple form of scoping that works without any tooling. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is relying on global styles for component details and then discovering that a global change breaks components in unexpected places. Scope component styles to the component. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 15 — Component state in plain JavaScript

Even without a framework, you can practise component thinking in plain JavaScript by keeping each component's state in a small object and writing a function that renders the component from that state. When the state changes, the render function updates the display. This pattern, state plus render, is the seed of how frameworks work, and understanding it in plain code makes frameworks far less mysterious later. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

The discipline is to avoid scattering state across the document: do not read values from the page's text to decide what to do next, because the page's text is a display, not a reliable record. Keep the state in code, render it to the page, and let user actions change the state, which then re-renders. That one-way flow, from state to screen, is easier to debug than a tangle of direct page edits. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a counter component might hold a number in a variable, with a render function that writes that number into a span, and buttons that add or subtract and then call render. The number lives in one place, and the screen always shows it. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is updating the page directly in several event handlers without a single state object, so that the displayed value and the real value drift apart. Centralise the state, even in a tiny example. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 16 — Events: how components communicate

Components communicate through events: a child component announces that something happened, such as a button click, a form submission, or a selection, and a parent component decides what to do about it. The child does not need to know what the parent will do; it only needs to announce the event clearly. This separation keeps components independent: the same button component can be used to save, delete, or submit, depending on which handler the parent supplies. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Events flow in the opposite direction to props. Props flow down, from parent to child, carrying data and configuration. Events flow up, from child to parent, carrying news. Keeping those directions distinct prevents tangled dependencies where every component knows about every other component. When a component needs to affect a distant cousin, the event should travel up to a shared parent, which then passes new props down. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a search box component might announce a search event with the query text, and the parent page listens for that event and updates the results list. The search box does not fetch results itself; it only reports the query. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is letting a child component directly manipulate its parent's display, bypassing the event. That creates a hidden dependency that breaks as soon as the parent changes. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 17 — Lists of components

Lists are a common component pattern: a list component renders many item components from a collection of data, one per item. Each item needs a stable identity, usually an identifier from the data, so that the system can tell items apart when the list changes, for example when an item is added, removed, or reordered. Without a stable identity, updates can confuse items, showing the wrong content in the wrong row. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

The list component's job is to manage the collection: rendering each item, handling an empty list gracefully, and keeping the order correct. The item component's job is to render one item well. Separating those jobs means the item component can be tested alone with a single example, and the list component can be tested with empty, single, and many-item collections. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a comments list might render a comment component for each comment in an array, using each comment's identifier as its key. When a new comment arrives, it is added as a new item, and the existing comments remain untouched. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is using the item's position in the list as its identity, which breaks when the list is sorted or filtered, because positions change while items do not. Use a stable identifier from the data. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 18 — Conditional rendering

Conditional rendering means showing different content depending on state: a loading message while data is being fetched, an error message if fetching fails, and the real content when it succeeds. In component terms, the component's render output is a function of its state, and different states produce different outputs. Designing each state explicitly prevents the common bug where a page shows a blank area or a broken layout while it waits. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

The states to consider are usually: loading, empty, error, and success, plus any interaction states such as disabled or selected. For each state, decide what the user should see and what they can do. A loading state should reassure, not merely spin forever; an empty state should explain why there is nothing and suggest a next step; an error state should say what went wrong and how to retry. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a search results component might show a loading note while searching, a message such as no results for that query when the list is empty, and the list itself when results exist. Those three outputs are three states of one component. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is designing only the success state and leaving the others to chance, so users meet a blank page or a confusing error. Design all states, even if some are simple. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 19 — Component hierarchy and data flow

A component hierarchy is the tree of components that makes up a page, from the root page component down through sections to individual items. Data generally flows down this tree through props, and events flow up, which gives the system a predictable direction. When a piece of data changes at the top, the components below it re-render with the new values, and the screen updates consistently. Understanding this flow is what lets you trace a bug: follow the data from where it is stored to where it is displayed. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Problems arise when data is passed through many intermediate components that do not use it, merely to reach a distant descendant. That pattern, called prop drilling, makes the intermediate components harder to understand, because they carry props they do not need. It is a sign that the data might belong lower in the tree, or that a shared store or context mechanism is warranted, topics that later chapters introduce at concept level. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a user name stored at the page level might be passed through a layout component and a header component to reach an avatar component. If the intermediate components only forward it, the design deserves a second look. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is storing data at the very top of the tree by default, forcing every descendant to receive it. Store data as low as possible while still sharing it among the components that need it. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 20 — Atomic design in brief

Atomic design is a method for organising components by size and complexity, borrowing language from chemistry: atoms are the smallest elements, such as buttons and labels; molecules combine atoms into small functional groups, such as a search box made of an input and a button; organisms combine molecules into larger sections, such as a header; templates arrange organisms into page layouts; and pages are templates filled with real content. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

The method's value is not in its terminology but in its discipline: it forces you to build small pieces first, combine them deliberately, and notice when a large section is really a composition of smaller, reusable parts. It also gives a team a shared vocabulary for discussing a design, so that a conversation about a molecule is understood to be about a small combination, not a whole page. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a label atom and an input atom combine into a form field molecule, several fields combine into a form organism, and the form sits in a page template alongside a header organism and a footer organism. Each level is testable on its own. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is following the levels rigidly, creating atoms and molecules for everything even when a simple component would do. Use the levels as a thinking aid, not as a filing system that must be obeyed. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 21 — Design systems and components

A design system is a collection of components, guidelines, and tokens that together define how a product looks and behaves. It is larger than a component library, because it also includes rules: when to use each component, how to write for it, and what accessibility requirements apply. Companies build design systems so that many teams can build different parts of a product that still feel like one product. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

For a learner, the lesson is that components do not live alone: they belong to a system, and the system is what makes them valuable. A button that matches the system's spacing, colour, and typography is more useful than a beautiful button that matches nothing else. When you build practice projects, keeping a small set of shared components and using them consistently is a miniature design system, and it teaches the same discipline. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a design system might define one button component, one card component, and one form field component, each with documented variants and usage rules. Every product page is then built from those few components, and the product feels coherent. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is calling a folder of unrelated components a design system. Without shared tokens, guidelines, and a process for adding components, it is a collection, not a system. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 22 — Testing a component

Testing a component means checking it in isolation, with known props and states, before trusting it in a full page. For each component, test its common cases: typical content, long content, missing optional content, and each variant. Then test its interactive states: what happens on click, on keyboard use, and when it is disabled. A component that passes those checks alone is far less likely to surprise you when it is composed into a page. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

Isolated testing is efficient because failures are easy to locate: if a card looks wrong alone, the problem is in the card, not in the page around it. It also creates a catalogue of examples that serve as documentation: a new team member can see every variant and state of every component in one place, without hunting through pages. Many teams maintain such a catalogue as part of their design system. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, test a card component with a short title and a very long title, with and without an image, and in its default and highlighted variants. If the long title breaks the layout, fix the card, not the page that happened to reveal the problem. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is testing only the component's ideal case, with short, tidy content, and then discovering its failures in production with real, messy content. Test the edges. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 23 — Accessibility in components

Accessibility in component thinking means building accessibility into each component once, so that every use inherits it. A button component should be a real button element, keyboard-focusable, with a visible focus state and an accessible name. A modal component should manage focus and announce itself correctly. A form field component should associate its label with its input. When those behaviours live in the component, every page that uses it is more accessible without extra effort. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

This is one of the strongest arguments for components: accessibility work done once pays off everywhere. The reverse is also true: an inaccessible component spreads its failure to every page that uses it, so component accessibility deserves careful attention and testing with a keyboard and a screen reader, not merely a visual check. Check contrast for every variant, not just the default, because a variant can easily fail while the default passes. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a tab component should let keyboard users move between tabs with arrow keys, announce the selected tab, and show its associated panel. Those behaviours belong in the tab component, not in each page that uses tabs. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is building a component from generic elements with click handlers, such as a div pretending to be a button, and losing keyboard and screen reader behaviour. Use the semantic element that matches the job. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 24 — Performance and components

Components affect performance in both directions. Reuse reduces duplicated code and can reduce file size, because one component definition serves many uses. But a page composed of many small components can also carry overhead, especially if each component loads its own styles or scripts, or if a large component tree re-renders unnecessarily when a small piece of state changes. Good component design balances reuse against that overhead. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Practical performance habits include keeping components small and focused, avoiding unnecessary work in rendering, and being careful with lists: a list of thousands of items should not render thousands of components at once if only a few are visible. Techniques such as rendering only visible items exist for that reason, but they are optimisations to apply when measurement shows a problem, not defaults for every list. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a news feed that renders fifty cards at once is usually fine, while a feed that renders five thousand cards at once will be slow regardless of how well each card is built. Measure with realistic data volumes before optimising. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is optimising component performance prematurely, adding complexity to solve a slowness that does not exist. Build clearly first, measure with real data, then optimise the actual bottleneck. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 25 — Refactoring into components

Refactoring into components means taking a page that was built as one long piece of markup and reorganising it into reusable units, without changing its visible behaviour. The safe way to do this is one component at a time: identify a repeated or distinct section, extract it, test that the page looks and behaves identically, and then move to the next section. Changing behaviour and structure at the same time makes failures hard to trace. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

Refactoring is normal, not a sign of failure. The first version of a page is often built quickly to learn what it should be, and its structure reflects that exploration. Once the design is clear, refactoring into components is how the page becomes maintainable. Expect to refactor, plan time for it, and do it while the page is still small enough to understand fully. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a page with three similar product sections might be refactored by extracting a product section component, replacing all three sections with uses of it, and confirming the page is unchanged. The visible result is identical; the code is far easier to change. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is refactoring everything at once in a large change that cannot be tested step by step. Small, tested extractions are slower to describe but faster to finish. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 26 — Components and CSS frameworks

CSS frameworks and component thinking complement each other, but they are not the same thing. A framework supplies styles and sometimes components, while component thinking is a way of organising any interface, with or without a framework. You can build components using framework classes, by combining utilities or component classes into a named component, or you can build them with custom CSS. The framework accelerates the styling; the thinking organises the structure. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

The combination works best when the component's boundary is clear: the component's markup uses framework classes internally, but pages use the component, not the framework classes directly. That way, if the framework changes, only the component's internals need updating, and the pages remain untouched. This layer of indirection is a small cost that pays off when a framework is upgraded or replaced. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a site button component might be built from framework button classes internally, while pages simply use the button component with a label and a variant. Changing frameworks later means rewriting the button component, not every page. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is scattering framework classes through every page and calling that component thinking. Without a component boundary, there is nothing to reuse or replace cleanly. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 27 — Components in plain HTML and CSS

You do not need a framework to practise component thinking. In plain HTML and CSS, a component is a repeated block of markup with a consistent class naming pattern, such as a card block that appears several times with the same structure. You copy the block, change its content, and keep its classes consistent. The reuse is manual, which is less convenient than a framework's, but the thinking is identical, and the discipline transfers directly. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

Manual reuse has a cost: changing the component means editing every copy, which is error-prone. That cost is itself a lesson, because it shows why frameworks and templating exist: to define a component once and use it many times. Starting manually, feeling that cost on a small scale, and then moving to a tool that removes it is a better learning path than starting with the tool and never understanding the problem it solves. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a plain HTML site might repeat a card block five times, each with the same classes and a different image, title, and text. The pattern is visible in the markup, even though each copy must be edited separately. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is repeating a block but changing its classes slightly each time, so the copies drift apart and cease to be one component. Keep the structure and classes identical; vary only the content. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 28 — Thinking about empty and error states

Every component that depends on data needs an empty state, for when there is no data, and an error state, for when something goes wrong. These are not edge cases to ignore; they are states users will meet, and a component that handles them gracefully feels far more professional than one that shows a blank space or a broken layout. Design the empty state to explain the situation and suggest a next step, and design the error state to say what happened and how to recover. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

Empty and error states are component responsibilities, not page responsibilities, because the component knows what data it expected and why it is missing. A list component knows it is empty; a form component knows its submission failed. Putting that knowledge in the component means every use of it handles those states correctly, without each page reinventing the message. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, an empty shopping basket component might show a friendly message, an illustration, and a link to continue shopping, while an error state might explain that the basket could not be loaded and offer a retry button. Both are part of the basket component. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is showing a technical error message, such as a status code, to users who cannot act on it. Translate errors into plain language and a useful next step. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 29 — Component documentation

Component documentation is a short description of what a component does, what props it accepts, which variants exist, and an example of each variant in use. It does not need to be elaborate: a page showing the component, its variants, and its states, with brief notes, is enough for a small project. Its purpose is to let a developer use the component correctly without reading its source code, and to let a designer see what already exists before requesting a new component. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Documentation also prevents duplication. When a team can browse existing components, they reuse them instead of building near-duplicates. When they cannot, duplication grows silently, and the design system fragments. Keeping documentation close to the code, and updating it when the component changes, is part of maintaining the component, not an optional extra. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a button's documentation might show its primary, secondary, and danger variants, its small and large sizes, its disabled state, and a note that the primary variant should appear at most once per view. That page answers most questions a new developer would ask. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is documenting a component once and never updating it, so the documentation describes a version that no longer exists. Treat documentation as part of the component's definition. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 30 — When not to make a component

Not every repeated piece of markup deserves to become a component. A pattern that appears twice, with significant differences, may be two different things that happen to look similar, and forcing them into one component creates awkward props and special cases. A piece of markup that is unique to one page, with no prospect of reuse, is also not a component; it is page content, and extracting it adds indirection without benefit. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

The question to ask is not whether something repeats, but whether extracting it will make the code clearer and changes cheaper. If the extracted component's API is harder to understand than the original markup, extraction has failed, however reusable the result claims to be. Simplicity is a valid reason to leave markup inline, especially in a small project or a prototype that is still changing rapidly. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a one-off hero section with unique illustration and layout is page content, not a component, even if it contains a button and a heading that resemble other components. Its uniqueness is the point. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is extracting components from a prototype before the design has settled, and then refactoring them repeatedly as the design changes. Let the design settle first, then extract. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 31 — Component composition patterns

Several composition patterns recur in component work. A layout component wraps content in a shared structure, such as a page shell with a header and footer. A list component renders many items from data. A wrapper component adds behaviour, such as a tooltip or a collapsible section, around arbitrary content supplied as children. Recognising these patterns helps you choose the right structure instead of inventing a new one for each case. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Each pattern has a characteristic API: a layout component takes children and perhaps a title; a list component takes data and an item component; a wrapper component takes children and a few behaviour props. Learning to spot which pattern fits a situation is faster than reasoning from first principles every time, and it makes your components feel familiar to other developers who know the same patterns. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a collapsible wrapper might accept a heading and children, rendering the heading always and the children only when expanded. The same wrapper can hold text, a form, or a list, because it does not care what its children are. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is using a list pattern for a fixed set of unrelated sections, or a layout pattern for a single item. Match the pattern to the job, not to the first pattern you learned. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 32 — State ownership: lifting state up

Lifting state up means moving a piece of state from a child component to their shared parent, when more than one child needs to read or change it. For example, if two sibling components must stay in sync, neither can own the state alone, because the other would not see changes. The parent owns the state and passes it down as props, while the children announce changes through events. The parent becomes the single source of truth for that piece of information. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

This pattern is simple to state and important to practise, because it resolves a whole class of synchronisation bugs. When state lives in one place, there is no question of which copy is correct. The cost is that the parent becomes more involved, and data may pass through intermediate components, which is the prop drilling discussed earlier. That cost is acceptable when the shared state is genuinely shared, and it signals when a different state solution may be needed. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a tab container might own the selected tab state, passing the selection to each tab button and the corresponding panel, so that clicking a tab updates both the button's appearance and the visible panel together. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is lifting every piece of state to the top of the page by default, creating a parent that knows everything and children that know nothing. Lift only state that is genuinely shared. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 33 — Derived values and computed display

A derived value is information calculated from state, rather than stored as state itself: a total calculated from a list of prices, a filtered list calculated from a search query, or a label calculated from a status. Derived values should be computed when needed, not stored separately, because a stored copy can become stale when the underlying state changes, producing a screen that contradicts itself. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

The rule is: store the smallest set of facts that describe the situation, and compute everything else from them. If a value can be calculated from state, calculate it; do not store it. This keeps the state small, the logic clear, and the display always consistent with the facts. When a derived calculation becomes expensive, it can be cached, but that is an optimisation, not a reason to store it as independent state. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a basket component might store a list of items, and compute the total price by adding their prices whenever it renders. Changing an item's quantity automatically changes the total, because the total is never stored separately. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is storing a total, a count, or a filtered list as state alongside the data it derives from, and then forgetting to update it in one of the many places the data can change. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 34 — Component lifecycle in plain terms

A component's lifecycle is the sequence of stages it passes through: it is created, it appears on the page, it updates when its props or state change, and it is removed when it is no longer needed. Each stage may need work: creation may set up initial state, updates may recalculate display, and removal may clean up resources such as timers or listeners. Thinking in lifecycle terms helps you avoid bugs such as a timer that keeps running after its component has disappeared. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

In plain JavaScript, the lifecycle is managed by your own code: you create the element, insert it, update it in a render function, and remove it when done, cleaning up anything you set up. In frameworks, the lifecycle is managed for you, with named hooks for each stage, but the stages are the same. Learning them in plain terms first makes the framework versions recognisable rather than mysterious. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a clock component might start a timer when it appears and stop the timer when it is removed. Forgetting the stopping step leaves a timer running invisibly, wasting resources and potentially causing errors. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is setting up resources in a component without a corresponding cleanup step. Every setup should have a matching teardown, in the same component. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 35 — Controlled and uncontrolled inputs

A controlled input is one whose value is held in state and updated on every change, so the component always knows the current value and can validate or transform it as the user types. An uncontrolled input is one whose value lives in the page element itself, and the component reads it only when needed, such as on submission. Both approaches work, and the choice depends on what the component needs to do with the value while the user is typing. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

Controlled inputs suit live validation, character counts, and formatted input, because the component sees every change. Uncontrolled inputs suit simple forms where the value is only needed at submission, because they require less code. The important thing is to choose deliberately and consistently within a form, and to understand which approach you are using, because mixing them for the same input produces confusing behaviour. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a search box that filters results as the user types needs a controlled input, because the results depend on every keystroke. A contact form that is only read when submitted can use uncontrolled inputs without loss. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is switching an input between controlled and uncontrolled during its life, such as starting with no value in state and later supplying one. Decide the approach from the start and keep it. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 36 — Forms as components

A form is naturally a set of components: the form itself, field components for each kind of input, and a submit component. Each field component bundles its label, its input, its help text, and its error display, so that every field on every form looks and behaves consistently. The form component manages the collection: gathering values, validating them, and handling submission. That division makes forms far easier to build and test than a single long block of markup. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Field components also centralise accessibility: the label association, the error association, and the focus behaviour are implemented once and inherited by every field. Validation messages belong in the field component too, because it knows which field failed and can display the message next to it. The form's job is to coordinate, not to micromanage each field's display. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a text field component might accept a label, a value, an error message, and a change handler, rendering the label, the input, and the error together. Every text field on the site then shares that structure. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is building each form from scratch with slightly different field markup, so that labels, errors, and spacing vary across the site. Extract the field component early; forms are where component reuse pays off fastest. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 37 — Navigation as components

Navigation is a set of components: a navigation bar, a menu, a menu item, a breadcrumb, and a pagination control, each with a clear job. The navigation bar arranges its items and handles the responsive collapse; the menu item renders a link and its active state; the breadcrumb shows the path to the current page. Treating navigation as components, rather than as copied markup on each page, ensures that adding a link updates every page at once. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

Navigation components also carry state: which item is active, whether a menu is open, and which page of results is shown. That state belongs in the navigation component or its parent, depending on whether other parts of the page need to know it. The active state is particularly important: users rely on it to know where they are, and it should be derived from the current page, not set by hand on each page. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a navigation component might receive the current page as a prop and highlight the matching item automatically, so no page needs to remember to mark itself active. The highlight is a derived value, not stored state. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is copying navigation markup onto every page and editing each copy when a link changes, which guarantees that some pages will be missed. Navigation is one of the first components any site should extract. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 38 — Cards, lists, and grids as components

Cards, lists, and grids are the workhorses of component design, and they illustrate composition clearly: a grid component arranges items, a list component manages a collection, and a card component presents one item. The grid should not know what a card contains; the card should not know it is in a grid. That separation lets the same card appear in a grid on one page, a list on another, and a carousel on a third, without modification. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

Layout components and content components have different jobs, and keeping them separate is a recurring theme. A layout component decides arrangement: how many columns, what spacing, how items wrap. A content component decides presentation: what an item looks like. When those jobs mix, the content component becomes tied to one layout, and the layout component becomes tied to one kind of content, and both lose reusability. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a photo gallery might use a grid component for arrangement and a photo card component for each photo, where the grid accepts any children and the card accepts a photo's data. Swapping the grid for a list changes the arrangement without touching the card. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is building a grid that only works with one kind of card, by hard-coding card styles into the grid's rules. Keep layout and content components independent. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 39 — Modals as components

A modal is a component with a distinctive lifecycle and accessibility requirements: it appears above the page, takes focus, traps focus while open, and returns focus when closed. Encapsulating those behaviours in a modal component means every dialog on the site behaves correctly without each page reimplementing focus management. The modal component owns the overlay, the dialog box, the close behaviour, and the focus logic; the page supplies only the content and the open and close triggers. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Modal content should be supplied as children, because dialogs vary widely: a confirmation, a form, an image viewer, and an alert are all modals with different content but the same frame and behaviour. The modal's props should include whether it is open and what should happen when it closes, and its state, open or closed, should live where the decision to open it is made, usually the parent. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a delete confirmation might use the modal component with a heading, a question, and two buttons as children, while the parent holds the open state and handles the confirmed deletion. The modal itself knows nothing about deletion. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is letting a modal manage its own open state internally while the parent also tries to control it, producing two sources of truth that disagree. Decide who owns the open state and keep it in one place. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 40 — Component communication patterns

Beyond props down and events up, several communication patterns recur: a parent passing a handler to a child, siblings communicating through a shared parent, and distant components communicating through a shared store or context. Each pattern suits a different distance. Direct parent-child communication is simplest and should be the default. Sibling communication through a parent is the next step. Shared state is for data that many distant components need, and it should not be the first resort, because it makes data flow harder to trace. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

Choosing the simplest pattern that works is a discipline. A shared store used for a value that only two siblings need adds indirection and makes the code harder to follow than lifting state to their parent would. Conversely, passing a value through ten intermediate components to reach a distant descendant is a sign that a shared mechanism is warranted. Judge by the distance and the number of components involved, not by fashion. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a theme setting needed by every component on a site is a candidate for shared state, while a search query needed by a search box and its results list is best lifted to their shared parent. The two cases look similar but call for different patterns. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is adopting a shared state tool for an entire project before any component actually needs it. Start with props and events, and introduce shared state when prop passing becomes painful. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 41 — Thinking in states, not pages

A powerful shift in component thinking is to design states, not pages: for each component, list the states it can be in, and design each one. A button has default, hover, focus, active, disabled, and loading states. A form field has empty, filled, valid, and invalid states. A page is then a composition of components, each in one of its states, rather than a single static design. This shift makes interfaces more robust, because states that would otherwise be forgotten are designed deliberately. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Designing states also clarifies development: each state is a case to implement and test, and the set of states is a checklist for completeness. When a designer hands you a design showing only the success state, ask about the others: what does this look like while loading, when empty, when it fails? That question, asked early, prevents the most common kind of unfinished interface. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, a profile component might have loading, loaded, empty, and error states, each with its own display. Building all four takes more time than building one, but it produces a component that behaves well in the real world, not only in a design mock-up. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is treating a state as a separate component, such as a loading component and a loaded component with duplicated structure. States are variations of one component, sharing its structure. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 42 — Component-first project structure

A component-first project structure organises files by component, with each component's markup, styles, and behaviour kept together, rather than organising by file type, with all markup in one folder and all styles in another. When a component's parts live together, changing the component means opening one folder, not hunting across three. It also makes it obvious when a component is unused, because its folder can be removed cleanly. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

File organisation is not a cosmetic choice; it shapes how easily a project can be understood and changed. A structure organised by component mirrors the interface's own structure, so a developer looking for the card component finds everything about the card in one place. A structure organised by technology mirrors the tools, not the product, and it scatters each component's parts across the project. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a project might have a folder for each component, containing its template, its styles, and its script, with a shared folder for utilities used by many components. A new developer can explore the project by exploring its components, which matches how users experience the interface. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is organising by file type and then duplicating component styles across files because no single file owns the component. Organise by component, and let shared utilities be the exception, not the rule. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 43 — Refactoring a page into components: a walkthrough

A walkthrough makes the refactoring process concrete. Start with a page that contains a header, a list of articles, and a footer, all written as one long block of markup. First, identify the repeated article block and extract it as an article card component, replacing each copy with a use of the component. Test that the page is unchanged. Next, extract the header and footer, which are distinct regions even though they appear once. Test again. Finally, extract the article list itself, which manages the collection and renders a card per article. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

Each extraction follows the same steps: name the component, decide its props, move its markup, replace its occurrences, and test. The order matters: extract repeated patterns first, because they give the largest saving, then distinct regions, then containers that manage collections. At each step, the page should look and behave identically; refactoring changes structure, not behaviour, and any visible change is a sign that something went wrong. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, after extracting the article card, the page's markup shrinks dramatically, because twenty copies of card markup become twenty short component uses. The saving is visible in the file, and the next change to the card design will be a single edit. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is refactoring and redesigning at the same time, so that a visible change cannot be attributed to either step. Refactor first, verify, then redesign if needed. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 44 — Component thinking without a framework

Component thinking does not require a framework, and practising it without one builds understanding that frameworks later reward. In plain HTML, CSS, and JavaScript, you can identify components, name them, keep their markup consistent, scope their styles with class prefixes, and manage their state with small objects and render functions. The work is manual, but the concepts, props, state, composition, and events, are the same concepts frameworks formalise. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

The manual version also teaches the costs that frameworks remove: updating every copy of a component by hand, keeping class names consistent without tooling, and managing state without automatic re-rendering. Feeling those costs on a small project gives you a grounded appreciation for what a framework does, and a realistic sense of when it is worth adopting. It also ensures that if a framework is unavailable, you can still build a well-organised page. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a plain JavaScript tab component might be a function that builds tab buttons and panels from data, tracks the selected tab in a variable, and re-renders on click. That is a component, even though no framework is involved. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is believing that component thinking only applies to framework projects, and therefore writing unstructured markup in plain projects. Structure is a habit, not a tool feature. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 45 — Sharing components across projects

Sharing components across projects means extracting a component that is genuinely generic, such as a button or a form field, into a shared library that several projects can use. The benefit is consistency across products and less duplicated work. The cost is coordination: a change to a shared component affects every project that uses it, so changes need versioning, testing, and communication. Shared components should therefore be stable, well-tested, and changed cautiously. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

Not every component deserves sharing. A component tied to one product's domain, such as a product card with product-specific fields, is not generic, and forcing it into a shared library creates awkward props for every other project. Share only components whose job is truly general, and keep product-specific components in their own projects. A shared library that grows too fast, with components added before they are proven, becomes a burden rather than a help. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, a button, an input, and a modal are good candidates for sharing, because their jobs are the same in almost any product. A checkout summary, with its product-specific rules, is usually not. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is sharing a component too early, before its API has settled, and then breaking several projects with each change. Prove a component in one project first, then share it. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Section 46 — Component versioning and change

When a component is used in many places, changing it is a decision with consequences: every use will change, for better or worse. Small, backward-compatible changes, such as adding an optional prop, are safe. Breaking changes, such as renaming a prop or removing a variant, require updating every use, and they should be planned, communicated, and tested across all affected pages. This is why component APIs deserve care: a careless API becomes expensive to fix once it spreads. In plain terms, this idea exists because real projects grow. A page that starts with a handful of styles can end up with hundreds, and without a clear approach the stylesheet becomes hard to read, hard to change, and easy to break by accident. The idea in this section gives you a rule you can apply consistently, so that a change in one place does not produce a surprise somewhere else on the site.

Versioning helps manage this: a shared component library releases versions, and projects adopt new versions deliberately, after testing, rather than receiving changes silently. Even within a single project, thinking in versions, noting when a component's API changed and why, helps a team understand the component's history. Change logs for components are short documents with outsized value. In practice, start small and observe the result before adding more. Build one component or one page section, apply the idea there, open the page in a browser, and resize the window to see how it behaves. Small, observable steps make it obvious which change caused which effect, and that feedback loop is how good front-end judgement is formed.

For example, renaming a button's variant prop from type to variant would break every button use until updated, so such a rename should be done as a planned change with a search through all uses, not as a casual edit. A deprecation period, supporting both names temporarily, can ease the transition. A common mistake is to copy a solution without understanding what each part does, then to be stuck when it needs adjusting. Avoid that by reading the example line by line and asking what would happen if each part were removed. The lines you cannot explain are the lines most likely to cause trouble later.

A common mistake is changing a widely used component casually, fixing the one page in front of you, and leaving other pages broken. Search for all uses before changing a shared component. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

Try it now: make a tiny page with two or three elements, apply this idea to them, and compare the result with a version that does not use it. Notice what got easier, what got harder, and what you would want to change next time. That comparison is the real lesson, and it will guide your choices on larger pages.

Check: Explain, in your own words, the main idea of this section and give one example.

Section 47 — Designing for change

Designing for change means anticipating that requirements will shift, and building components that can shift with them without a rewrite. The main techniques are keeping components small, keeping their APIs focused on intention rather than implementation, and separating content from presentation so that either can change independently. A component that is small, well-named, and loosely coupled to its surroundings is easier to change than a large, entangled one, even if both work today. Think of this as a working habit rather than a piece of trivia. You will use it on almost every page you build, and the benefit appears gradually: files stay shorter, decisions become easier to explain to a teammate, and fixing a visual bug takes minutes instead of an afternoon of hunting through unrelated rules.

Change also comes from design: colours, spacing, and typography evolve, and components built from design tokens adapt by changing token values, while components with hard-coded values require editing everywhere. Similarly, content changes: a card that accepts any title and image adapts to new content, while a card with hard-coded content does not. Designing for change is therefore mostly about avoiding hard-coded assumptions in favour of props, tokens, and composition. When you apply this idea, keep the surrounding code in mind. A front-end page is a system: markup, styles, and behaviour interact, and a choice that looks good in isolation can create a problem elsewhere, such as overflowing content on a narrow screen or a colour that fails a contrast check. Test the whole page, not just the fragment you edited.

For example, a banner component that accepts a heading, a message, and an action as props can serve a sale, an announcement, or a warning, while a banner with fixed text can serve only one. The flexible version costs little more to build and far less to reuse. Another frequent mistake is to mix approaches in the same file without a reason: part of the page follows one convention and part follows another. That inconsistency makes the code harder to scan and harder to maintain, because a reader cannot predict which convention applies where. Pick one approach for a given job and use it consistently.

A common mistake is designing for imaginary future changes, adding props and options for needs that never arrive. Design for plausible change, not for every conceivable change. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

For practice, take an existing practice page and rework one section using this idea, keeping the visible result the same. If the page looks identical but the code is clearer or shorter, the rework was worthwhile. If the result changed unexpectedly, you have found a gap in your understanding worth closing before you rely on the idea in a bigger project.

Check: When would you use the idea in this section, and when would you choose a different approach?

Section 48 — Chapter 28 in one paragraph

This chapter has argued that component thinking is a way of seeing interfaces as compositions of small, purposeful, reusable units, each with a clear job, a clear API of props and events, and a set of states it can be in. You have seen how to break a design into components, how to compose them, how to manage state and data flow, and how to handle variants, lists, and empty and error states. You have also seen the cautions: avoid over-abstraction, keep APIs small, and do not extract a component before its pattern has genuinely repeated. The reason this matters for a beginner is that early choices compound. If you adopt a messy approach on a small practice page, the same approach will feel natural on a larger project, where its cost is much higher. Learning the disciplined version now saves you from having to unlearn a habit later, when a real deadline is involved.

The through-line is that components are an organising discipline before they are a tool feature. Whether you build in plain HTML and CSS or in a framework, the same questions apply: what is this component's job, what does it accept, what does it announce, what states can it be in, and where does its state live? Answering those questions consistently is what turns a collection of markup into a maintainable interface. A practical test is to change one thing deliberately. Alter a value, remove a class, or rename something, then refresh and watch what breaks. That experiment teaches you what actually depends on the idea, which is far more useful than memorising a definition. Undo the change afterwards and confirm the page returns to normal.

For example, a good final test of this chapter is to take a page you have already built, draw boxes around its components, name them, list their props and states, and then refactor one repeated pattern into a component. That exercise, done honestly, will teach you more than any further reading. Watch out for overuse. A technique that helps in moderation can hurt when applied everywhere: too many classes, too many wrappers, or too many overrides all add weight and confusion. If a page feels complicated, look for the simplest version that still meets the design, and prefer that version.

A common mistake is ending a chapter like this with an opinion but no practice. Draw the boxes, name the components, and refactor one pattern before moving on. Keep a small practice file where you try each idea in isolation. A tiny page with a single component is a better laboratory than a large project, because there is nothing else to confuse the result. Once the idea works there, carry it into a real page with confidence.

A helpful exercise is to build the same small component twice: once with this approach and once without it. Put the two versions side by side and judge them on readability, ease of change, and behaviour on a narrow screen. There is rarely one winner for every situation, and learning when each approach wins is the skill that matters.

Check: What goes wrong if you ignore the advice in this section? Give a concrete example.

Section 49 — Component thinking and teamwork

Component thinking helps teams because it gives them a unit of work that can be assigned, reviewed, and tested independently. One developer can build the card component while another builds the header, and both can work against an agreed API: the props each component accepts and the events it announces. When the components meet in a page, they fit, because the agreement was made before the code was written, not discovered afterwards. A useful way to judge this idea is to ask what happens when the design changes. Clients and designers change colours, spacing, and layouts often. An approach that survives those changes without a rewrite is a good one; an approach that forces you to edit dozens of files for one small change is a warning sign.

Teamwork also benefits from a shared component catalogue. When every developer can see the components that already exist, with their variants and examples, they reuse instead of duplicating, and the product stays consistent even as the team grows. Reviews become more focused too: a review of a component checks its API, its states, and its accessibility, which is a clearer checklist than a review of a whole page. Do not adopt this idea blindly on every element. Ask whether it earns its place in this particular case: does it make the code clearer, the page faster, or the design more consistent? If the answer is no, plain hand-written code may be the better choice. Good developers choose tools for a reason they can state.

For example, a team building a shop might agree that the product card accepts a product's name, price, image, and rating, and announces a selection event. Developers can then build the card, the list, and the basket independently, confident that the pieces will combine. A subtler mistake is to optimise for the first screen you test and forget the rest. Check a narrow phone width, a large desktop width, and a zoomed-in view. Many front-end bugs only appear at an extreme, and catching them early is much cheaper than explaining them to a user who has already encountered them.

A common mistake is dividing work by page rather than by component, so that two developers build the same card twice, differently. Divide by component where the interface repeats. To check your own work, open the page, inspect the relevant element in developer tools, and confirm that the styles you expect are actually applied rather than overridden or ignored. Then change the browser width, reload, and confirm nothing has broken. Write down anything surprising; those notes become your personal checklist for the next project.

To make this stick, add the idea to your next practice project in exactly one place, and keep a short note about why you chose it there. Later, when you review the project, that note will tell you whether the choice paid off. Over several projects, those notes become a reliable personal guide to what works for you.

Check: How would you check your own work after applying the idea in this section?

Section 50 — Putting component thinking into practice

Putting component thinking into practice starts with a habit, not a tool: before writing markup for a new page, sketch its components, name them, and list their props and states. Then build the smallest components first, test them alone with typical and edge-case content, and compose them into larger sections. Keep a note of each component's job in one sentence, because that sentence is the test of whether the component is well-defined. This idea also affects how other people read your work. A teammate, a future version of yourself, or a reviewer judging a portfolio project should be able to open your code and understand the intention quickly. Clear, consistent choices communicate professionalism even before anyone runs the page.

As you practise, expect your first component boundaries to be imperfect. A component may turn out to do too much, or two components may turn out to be one. That is normal, and refactoring a boundary is a skill in itself, not a failure. The goal is not a perfect first decomposition, but a habit of thinking in components that improves with each project, until it becomes the natural way you approach an interface. Remember accessibility while you work. Visual changes are not only about appearance; they affect whether text remains readable, whether interactive elements remain reachable by keyboard, and whether a screen reader still announces content in a sensible order. Check those things as you go, not as an afterthought at the end.

For example, take any page from an earlier chapter, sketch its components, and rebuild one section from components rather than from a single block of markup. Compare the two versions on readability and ease of change, and keep the version that is clearer. Finally, do not confuse looking finished with being finished. A page can look correct in one browser and fail in another, or look correct with short sample text and break with a long real heading. Test with realistic content, realistic text lengths, and at least one other browser before you call the work done.

A common mistake is treating component thinking as a framework topic to be learned later. It is a design habit to practise now, in plain HTML and CSS, before any framework makes it feel automatic. A good self-check is to explain the idea aloud in one or two sentences without looking at this section. If you can do that and give a correct example, you understand it well enough to use it. If you cannot, re-read the example and try building a tiny version from scratch before moving on.

Practice deliberately: create a small test page, apply the idea, break it on purpose by changing one value, and then fix it. The break-and-fix cycle teaches you the boundaries of the idea far faster than reading alone, and it builds the calm debugging habit that professional work depends on.

Check: Describe a situation from a real project where the idea in this section would matter.

Practical task

Take a page you built in an earlier chapter and redraw it as components on paper: name each component, list its props, and list the states it can be in. Then rebuild one repeated pattern, such as a card or a form field, as a single consistent block used everywhere it appears, and test the rebuilt page with long titles, missing images, and an empty list to confirm its states behave sensibly.

Chapter questions

  1. What is the difference between props and state, and why does that distinction matter for debugging?
  1. A component is used in two places with different content. Should that difference be handled with props, with children, or by making two components? Explain your reasoning.
  1. Why is it risky to extract a component before its pattern has repeated, and what rule of thumb helps you decide when to extract?
  1. Two sibling components must stay in sync. Where should their shared state live, and why?
  1. A list reorders incorrectly when sorted. What is the most likely cause, and how would you fix it?