CSS Code Review Checklist
What You Learn From This Page
- How to review the requirement and rendered result before discussing CSS syntax.
- How to evaluate selector clarity, cascade authority, naming, component ownership, and design tokens.
- How to review Flexbox, Grid, sizing, overflow, positioning, typography, images, and responsive behavior.
- How to protect keyboard access, focus, contrast, touch interaction, motion preferences, themes, and RTL.
- How to assess browser compatibility, production output, performance cost, test coverage, and cleanup.
- How to distinguish useful abstraction from clever or premature architecture during a pull-request review.
Introduction
A CSS code review checklist helps a team judge more than whether the current screenshot looks correct. Good CSS must remain understandable, responsive, accessible, reusable, performant, and compatible with the project's supported browsers. It must also fit the existing architecture so the next feature does not require stronger selectors, additional exceptions, or another parallel component system.
A strong review begins with product intent, examines the rendered result and markup, then follows the code through ownership, cascade, layout, states, and production output. It asks whether the solution works with long content, narrow space, zoom, keyboard input, dark mode, right-to-left direction, and browser differences. Review comments should identify observable risks and propose an appropriate direction rather than enforcing personal style preferences.
The central principle is to protect long-term interface behavior, not merely approve today's appearance. Reviewers should reward clear intent and predictable constraints, while automated tools should handle formatting, syntax, and repeatable policy checks wherever possible.
Understand the Requirement First
Before reading selectors, establish what the change must achieve. Review the expected layout, component states, responsive behavior, supported themes, accessibility requirements, browser matrix, content range, and interaction model. A clean implementation of the wrong behavior is still wrong.
Ask for missing acceptance criteria early. Should a panel stack or scroll when space is narrow? Can its title wrap? Does it appear inside multiple containers? What happens during loading and error states? Clear requirements turn review from subjective preference into evaluation against agreed outcomes.
Compare the Design with the Browser Result
Read the source and exercise the rendered feature. Static code cannot reveal every cascade conflict, intrinsic sizing decision, browser default, font metric, or runtime state. Compare the intended design with representative desktop, mobile, zoomed, and interactive results.
Visual similarity is only one dimension. Confirm content order, state communication, focus visibility, target size, reading flow, overflow behavior, and interaction. A screenshot can look correct while text is clipped, a menu is unreachable by keyboard, or a loading label expands outside a fixed button.
Review the HTML Context
CSS cannot be reviewed safely in isolation from markup. Confirm that headings, lists, links, buttons, labels, form controls, tables, and landmarks use appropriate elements. Semantic HTML supplies reliable browser behavior and frequently removes custom CSS and JavaScript.
<button type="button" class="button">Save</button>
A clickable <div> styled like a button still lacks the native element's keyboard activation, disabled semantics, focus behavior, and accessibility mapping unless substantial behavior is recreated. The best CSS review comment may therefore recommend correcting the HTML.
Check Selector Clarity
A selector should communicate what owns the rule. Classes such as .product-card and .product-card__title are easier to understand than a chain such as body main .page .content section .card. The class-based form also survives harmless wrapper changes.
Ask whether every selector segment contributes necessary scope. Remove incidental ancestors, tag qualifiers, and repeated context when the component class already provides identity. Short selectors are not automatically good, but unnecessary depth is a strong signal of DOM coupling.
Review Selector Stability
Selectors based on child position, exact wrapper depth, or generic element combinations can break when markup changes for accessibility or product needs. A rule such as .sidebar > div > ul > li > a encodes structure rather than responsibility.
Prefer stable component roles such as .side-nav__link. State selectors can use meaningful native or ARIA attributes, for example [aria-expanded="true"], when the attribute is already the authoritative behavioral state.
Keep Specificity Predictable
Review IDs, repeated classes, long descendant chains, inline styles, and unnecessary pseudo-class weight. High specificity makes future variants and consumer overrides expensive and often begins an escalation toward important declarations.
/* Hard to override and reuse */
#app .dashboard .card .card__title { color: #155eef; }
/* Clear component ownership */
.card__title { color: #155eef; }
Evaluate specificity after origin, importance, and cascade layer. A stronger selector is not the right answer when the actual problem is a misplaced layer or unlayered rule.
Question Every Important Declaration
An !important declaration should have an architectural reason. It may be justified for a defined utility contract, an accessibility override, or a contained third-party correction, but it should not compensate for unclear ownership.
Reject important escalation in which one important rule is answered by another stronger important selector. Request evidence, scope, and documentation. If the declaration addresses legacy or vendor CSS, include the removal condition so a temporary exception does not become permanent debt.
Review Cascade Layer Placement
When the project uses layers, confirm that reset, base, component, utility, override, and third-party rules enter the intended layer. An accidental unlayered author rule normally outranks layered normal declarations and can silently defeat the architecture.
@layer reset, base, components, utilities;
@layer components {
.card { padding: var(--space-md); }
}
Check import order and production output as well as source. Remember that important declarations reverse normal layer priority, so review important behavior separately.
Follow the Project Naming Convention
Whether the repository uses BEM, CSS Modules, utility classes, scoped components, or another documented system, new CSS should follow that system unless the change intentionally updates architecture. Mixing naming models makes ownership and search harder.
Reject ambiguous names such as .box, .new, .style2, and .red-button. Prefer responsibility and semantic variation: .checkout-summary, .button--danger, and .card--featured. Semantic names survive visual redesign better than location or appearance names.
Review Component Boundaries
A component should generally own its internal arrangement, spacing, appearance, and states. The parent layout should decide where that component sits relative to siblings. A card with margin-left: 200px is coupled to one page; a dashboard Grid should place the card.
Ask whether the component can move to another route or container without page-specific overrides. Explicit variants or input tokens are clearer than repeated selectors such as .sidebar .button, .modal .button, and .footer .button.
Evaluate Reuse Without Over-Abstraction
Search for an existing component or utility before accepting .new-blue-button. Duplicate systems create inconsistent states and multiply maintenance. If the existing primary button satisfies the behavior, reuse it.
However, identical values do not automatically justify a shared abstraction. Two unrelated components can both use one rem of padding today and diverge tomorrow. Extract a token, utility, or base component when the concepts share meaning and are expected to evolve together, not merely because text is duplicated.
Review Design Token Use
When the project defines semantic colors, spacing, radii, typography, shadows, and motion, components should consume those decisions rather than repeat equivalent raw values. Tokens support themes, consistency, and controlled updates.
.card {
padding: var(--space-md);
border-radius: var(--radius-md);
background: var(--color-surface);
color: var(--color-text);
}
Choose the right semantic level. A component surface should usually consume --color-surface rather than a primitive such as --gray-100. Do not turn every one-off declaration into a custom property; variables should express meaningful reuse, configuration, or cascade-driven variation.
Check Spacing and Gap Ownership
Review unexplained values that fall outside the project's spacing scale. A unique value can be legitimate when geometry requires it, but repeated arbitrary values often indicate visual drift. Ask the author to connect exceptions to a design requirement.
Use gap when a Flexbox or Grid parent owns spacing between children. This avoids last-child corrections and keeps placement responsibility with the layout. Child margins remain appropriate when the spacing belongs intrinsically to the child rather than the sibling relationship.
Review the Box Model and Sizing
Check width, padding, border, minimum and maximum sizes, and the active box-sizing model. A fixed width plus large padding may overflow under content-box, while a minimum size can prevent an apparently fluid item from shrinking.
Prefer intrinsic and bounded sizing when content and viewport can vary. For example, inline-size: min(100%, 31.25rem) protects a maximum while allowing a narrow container. Confirm that the surrounding layout, not only the component declaration, permits that shrinkage.
Avoid Fixed Heights for Text
A fixed-height card, button, heading, or navigation item may clip at higher zoom, with a fallback font, larger user text, or a longer translation. Content-driven block size is the safer default. Use minimum height when a consistent control target is needed while allowing expansion.
If truncation is a product requirement, ensure the full information remains available and the clipping pattern is complete. Do not hide unknown overflow to make a single test string fit.
Question Overflow Hiding
overflow: hidden can intentionally crop media or establish a visual boundary, but it can also hide focus rings, menus, shadows, long text, and underlying layout defects. Ask what content is expected to exceed the box and how users can access it.
Global overflow-x: hidden on the body deserves particular scrutiny. It often masks a wide child instead of fixing it. Identify fixed widths, unbreakable text, oversized images, transforms, Flexbox minimums, or Grid tracks that created the overflow.
Review Flexbox Intentionally
Confirm that the component needs one-dimensional distribution and that main and cross axes are understood. Review wrapping, gap, alignment, free-space behavior, and the meaning of each item's grow, shrink, and basis values.
The shorthand flex: 1 changes all three components and should reflect actual intent. For flexible children containing long text, verify whether min-inline-size: 0 is needed to permit shrinking. Test narrow widths instead of assuming the declaration works from a desktop screenshot.
Review Grid Tracks and Placement
For Grid, inspect explicit and implicit tracks, gaps, item placement, auto-fit versus auto-fill, and intrinsic sizing. A responsive pattern such as repeat(auto-fit, minmax(min(100%, 16rem), 1fr)) may replace several arbitrary media queries.
.comparison {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: var(--space-md);
}
Use minmax(0, 1fr) when tracks should shrink below intrinsic content minimums. Confirm that long text and media behave as expected rather than applying the pattern everywhere automatically.
Review Positioning and Containing Blocks
Absolute positioning is appropriate for badges, overlays, and decorative items, but it is fragile for ordinary page layout. Confirm which ancestor creates the containing block and whether the positioned item remains correct when content wraps or the container resizes.
Review fixed elements on mobile with browser chrome, safe areas, and the virtual keyboard. Review sticky elements inside their actual scroll containers, with an inset such as top: 0, sufficient scroll range, and ancestor overflow taken into account.
Review Z-Index as a Layering System
Large arbitrary values such as 999999 usually indicate that stacking contexts are not understood. Inspect transforms, opacity, filters, isolation, containment, positioned ancestors, and the project's intended overlay hierarchy.
Prefer a small semantic scale for dropdowns, sticky navigation, modals, and urgent messages. The value should express a relationship, not win an unbounded numeric contest. If a child is trapped in a lower ancestor context, increasing its local z-index cannot solve the architectural problem.
Evaluate the Responsive Strategy
New queries should follow the project's mobile-first or documented responsive approach. Introduce breakpoints where content and layout require a structural change, not because a common device label suggests 768 pixels.
Look for clusters of near-identical media queries. Flexible tracks, wrapping, clamp(), min(), max(), intrinsic sizing, and container queries may express the requirement with fewer states. Do not replace clear step changes with fluid values merely because the functions are modern.
Consider Container Queries for Portable Components
A component reused in a narrow sidebar and a wide main area may need to respond to its container rather than the viewport. Container queries reduce page coupling when the component's composition depends on available inline space.
.card-shell { container-type: inline-size; }
@container (min-width: 30rem) {
.card { grid-template-columns: 10rem 1fr; }
}
Verify that the intended ancestor establishes containment and that a useful stacked baseline exists. Container queries introduce context and should simplify reuse rather than make ordinary layout harder to trace.
Prefer Logical Properties Where Intent Is Directional
When spacing, borders, positioning, or alignment should follow language direction, prefer logical properties such as margin-inline-start, padding-block, and text-align: start. Physical left and right values remain valid when the design truly refers to a physical side.
Test the rendered component with dir="rtl". Also review directional icons, Flexbox ordering, absolute offsets, and asymmetric radii. Replacing one margin does not make the whole interaction bidirectional.
Review Typography for Real Content
Check the font stack, loaded weights, size, line height, letter spacing, wrapping, fallback behavior, and readable measure. A requested weight may be synthesized if no matching font file exists. Very tight line height that looks acceptable in a short heading may become unreadable in multi-line content.
Test long names, translated labels, URLs, multiline buttons, and font-loading failure. Avoid pixel-perfect text boxes. If ellipsis is used, confirm constrained width, overflow behavior, white-space rules, and a way to access essential hidden information.
Review Images and Media
Large images should not exceed their containers. Confirm responsive sizing, intrinsic width and height, aspect ratio, loading behavior, and whether object-fit: cover crops meaningful content. An aspect ratio can reserve space and reduce layout shift, but it must match the media or an intentional display frame.
img {
max-inline-size: 100%;
block-size: auto;
}
Review background images at different content lengths and zoom levels. Decorative assets should not carry information that disappears when CSS or images fail.
Review Form Controls Conservatively
Inputs, textareas, selects, checkboxes, radios, buttons, date fields, and file inputs have valuable native behavior. A typography baseline such as font: inherit can improve consistency without discarding platform affordances.
If the change uses appearance: none, confirm that focus, disabled state, selected state, touch area, keyboard operation, high contrast, and recognizable control cues are rebuilt. Prefer native state selectors such as :disabled over duplicate visual modifier classes when HTML already represents the truth.
Require Visible Focus
Every interactive element needs a visible keyboard focus state. Reject outline: none unless an equally clear replacement exists in all themes and states. Ensure the indicator is not clipped by overflow or obscured by sticky content.
:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 3px;
}
Review the complete Tab order and activate controls with Enter or Space as appropriate. CSS can visually reorder content without changing focus sequence, so compare visual and DOM order when order or Grid placement is used.
Review Hover, Touch, and Target Size
Essential information and actions cannot depend only on hover. Provide focus and touch-compatible alternatives. Hover styling may be restricted to hover-capable devices when it is purely decorative.
Compact controls must remain practical to tap and must not overlap adjacent targets. Test multi-line labels and localized text because a target that is large enough with one English word may collapse or overflow with real content.
Check Contrast and Non-Color Communication
Measure contrast for body text, secondary text, links, buttons, focus indicators, validation messages, disabled states, and interactive boundaries. Existing tokens do not automatically guarantee that every foreground-background combination is compliant.
Success, warning, selection, and error should not be communicated through color alone. Preserve labels, icons, patterns, semantic attributes, or other cues. Review forced-color modes where browser-controlled colors may replace authored ones.
Review Themes as Complete States
Test light and dark themes across surfaces, text, borders, links, controls, focus, disabled states, shadows, images, and overlays. Hardcoded white or black commonly escapes a partial theme review.
Prefer semantic theme tokens that change at a theme boundary rather than repeating .dark .component rules throughout the codebase. Inspect custom-property scope and fallbacks so a reusable component remains legible outside its usual page.
Review Motion Purpose and Control
Motion should communicate state, continuity, or feedback. Specify the properties to transition instead of using transition: all, which can animate new properties unintentionally. Keep durations responsive to the interaction and justify continuous animation.
Large movement, parallax, flashing, and repeated animation need a reduced-motion alternative. Transforms and opacity are often efficient, but performance should be measured. Width, height, top, and left can cause repeated layout work, while large filters and shadows can create expensive paint.
Question Performance Hints and Effects
Reject universal or widespread will-change. It can allocate compositing resources and consume memory even when no animation occurs. Use it narrowly and temporarily when profiling demonstrates a measurable benefit.
Review large blur filters, backdrop filters, multiple shadows, fixed backgrounds, and huge painted regions on representative devices. A visually attractive effect needs a reasonable fallback and should not make scrolling or interaction unreliable.
Check CSS Bloat and Dead Code
Ask whether a small feature adds duplicate utilities, near-identical components, repeated theme blocks, one-off classes, or a large dependency. Inspect generated production size rather than source lines alone, because tooling can multiply or eliminate rules.
When new CSS replaces an old component, include deletion in the change or track a short migration with an owner and deadline. Do not preserve commented-out CSS; version control already stores history. A permanent old-plus-new system increases every future review cost.
Review Utility and BEM Usage
In a utility-first project, confirm that values follow the design system and that arbitrary values such as 13, 17, and 347 pixels are justified. Repeated long utility combinations may deserve a component, but extraction should follow repository conventions.
In BEM, keep block, element, and modifier ownership clear. Avoid chains such as block__element__subelement when a simpler block boundary communicates responsibility. Modifiers should describe semantic variation, while native attributes and ARIA state should remain the source of truth where possible.
Review Nesting and Relational Selectors
Keep CSS nesting shallow and mentally flatten every nested rule. A convenient source format can generate deep selectors and hidden specificity. Verify the difference between &.active, which targets the same element, and .active, which targets a descendant.
Use :is(), :where(), and :has() when they make intent clearer. Remember their specificity behavior and browser requirements. A direct state class can be more maintainable than an intricate relational selector that future developers need to decode.
Verify Browser Compatibility
Review modern features against the project's explicit browser matrix. Container queries, native nesting, :has(), new viewport units, anchor positioning, and view transitions may need progressive enhancement or a baseline. Support percentages cannot replace knowledge of the actual audience.
Prefer feature queries and fallback declaration order to browser-specific hacks. Let automated tooling manage required prefixes from centralized targets. Test significant layout and form changes in Chromium, Firefox, and Safari or WebKit, with real mobile checks for viewport, fixed, sticky, keyboard, and safe-area behavior.
Inspect Fallback Quality
An unsupported enhancement should leave a coherent interface. Place broadly understood declarations first, then modern alternatives. The fallback does not need identical visuals, but it must preserve content, actions, focus, and state.
.title {
font-size: 2rem;
font-size: clamp(2rem, 1.4rem + 2vw, 4rem);
}
Review both paths. A feature query is useful only if the baseline was actually tested and does not depend on declarations inside the query.
Check Linting, Formatting, and Comments
Automate invalid values, unknown properties, duplicate declarations, naming rules, ordering, supported-feature checks, and formatting. Review time is better spent on architecture and behavior than indentation debates.
Comments should explain intent, constraints, or non-obvious tradeoffs. A browser workaround needs affected versions, a reason, supporting issue, owner, and removal condition. A comment that says "make color blue" merely repeats the declaration.
Review File and Module Placement
Confirm that tokens, resets, utilities, components, and page composition live in their expected files and layers. Do not place a component fix randomly in a global stylesheet because it happens to load last.
Keep component states discoverable. Splitting one component into base, mobile, dark, and fixes files can make the final cascade impossible to understand unless the architecture intentionally organizes those dimensions. Global selectors and reset changes deserve broader testing because their blast radius is much larger.
Inspect Source Order and Dependencies
If a stylesheet works only because it happens to load after another unspecified file, make that dependency explicit through imports, layers, or build architecture. Fragile source-order assumptions often fail during bundling or route-level code splitting.
Question new external dependencies. Importing an entire UI framework for one component adds network, cascade, security, and maintenance costs. Inspect the production bundle to ensure a small source change did not generate thousands of unused classes or duplicate a library.
Demand Complete State Testing
Review default, hover, focus-visible, active, disabled, loading, empty, error, success, selected, and expanded states where applicable. State combinations matter: a disabled button in dark mode or a focused invalid input may expose a defect hidden in separate screenshots.
Use long content, missing media, delayed fonts, and asynchronous updates. CSS that works with ideal sample data may fail immediately when production content arrives.
Test Responsive Extremes and Zoom
Inspect narrow and wide layouts, then drag between them to find content-driven failure points. Large screens can expose excessive line length and over-stretched tracks just as small screens reveal overflow and cramped controls.
Test at 100, 150, and 200 percent browser zoom. Look for clipping, hidden navigation, overlapping labels, inaccessible controls, and two-dimensional scrolling. Zoom can change the effective CSS viewport and trigger responsive rules; the result must remain usable.
Test RTL, Keyboard, Touch, and Print Where Relevant
Set the page to right-to-left direction and inspect logical spacing, alignment, icon direction, ordering, and positioned elements. Navigate with Tab and Shift+Tab, activate controls from the keyboard, and verify that focus remains visible.
Use touch or device testing for target size, hover assumptions, fixed controls, and scrolling. Content-heavy or document products should also check print output when it is a supported workflow. Review effort should follow product requirements, not a universal test list detached from users.
Protect the Existing Architecture
Technically valid CSS can still be inappropriate if it introduces a second architecture. A project using BEM, tokens, and layers should not gain an isolated custom utility system, inline-style strategy, or CSS-in-JS dependency for one feature without a deliberate migration decision.
Consistency usually provides more value than a reviewer's favorite technique. Recommend modernization when it removes real complexity or meets a requirement, not because Grid, nesting, container queries, or :has() are fashionable.
Prefer Readability Over Cleverness
Ask whether another developer can understand ownership, state, and layout intent in about thirty seconds. Dense combinations of :is(), :not(), and :has() may be valid yet harder to maintain than one explicit component class.
Explicit code is not necessarily verbose code. It names the concept, places it in the correct layer, uses a small predictable selector, and keeps related states nearby. A review should reduce the amount of hidden knowledge needed to change the component safely.
Write Actionable Review Comments
A useful comment identifies the risk, explains when it appears, and suggests an appropriate direction. Instead of "do not use overflow hidden," say that the declaration clips the keyboard focus ring at 200 percent zoom and recommend moving clipping to the media wrapper.
Distinguish blocking issues from optional suggestions. Accessibility failures, broken supported browsers, hidden content, architecture violations, and untested global changes may block approval. Naming preferences that are not in project standards should not.
Common Review Red Flags
| Red Flag | Likely Risk | Review Direction |
|---|---|---|
!important | Cascade or ownership conflict | Find the real authority problem |
z-index: 999999 | Stacking-context misunderstanding | Inspect ancestor contexts and layer scale |
| Deep selector chain | DOM coupling and high specificity | Use a stable component role |
| Body overflow hidden | Masked wide child | Identify the overflowing element |
| Fixed text height | Clipping at zoom or translation | Use content-driven size |
| Repeated raw colors | Missing semantic tokens | Use established theme decisions |
| Many page overrides | Weak component boundary | Create explicit variants or inputs |
| Near-identical breakpoints | Responsive rule bloat | Consider intrinsic layout or functions |
transition: all | Unexpected animation and work | Name intentional properties |
outline: none | Invisible keyboard focus | Require an accessible replacement |
| Large arbitrary utility list | Design-system drift | Use scale values or a component |
| Browser-specific hack | Fragile compatibility debt | Prove and document the engine issue |
A Practical Review Workflow
Read the requirement and inspect the rendered feature. Verify semantic markup, then review file placement, naming, component boundaries, selectors, cascade layers, specificity, tokens, and state ownership. Examine sizing, spacing, overflow, layout mode, positioning, and responsive behavior.
Exercise accessibility, themes, RTL, content extremes, zoom, and supported browsers according to risk. Inspect production output, dependency cost, generated size, and removed code. Run automated checks, record any intentional exception, and approve only when behavior and architecture are both clear.
Common Interview Questions
What should be checked during a CSS code review? Requirements, markup, selectors, cascade, architecture, layout, responsiveness, accessibility, themes, compatibility, performance, test evidence, and cleanup.
Why avoid high-specificity selectors? They make variants and future changes harder, encouraging escalating selectors and important declarations.
Why should outline removal be reviewed carefully? It can remove the visible keyboard focus indicator and make controls unusable for keyboard users.
Why review hardcoded colors? They can duplicate design decisions, break themes, and produce inconsistent state contrast.
Why are fixed heights risky? Text growth, fallback fonts, translations, and zoom can clip content or create overlap.
Why question overflow hidden? It can conceal content, focus indicators, menus, shadows, and the actual source of a sizing defect.
Why is rendered testing required? Many cascade, intrinsic sizing, state, font, and browser problems cannot be proven from static source alone.
When should modern CSS be introduced? When it simplifies the requirement, improves resilience, and fits the browser policy, not solely because it is newer.
Practical CSS Review Checklist
- Confirm the requirement, supported environments, states, and content range.
- Review rendered output together with the HTML and CSS source.
- Use semantic markup and preserve native behavior wherever possible.
- Keep selectors stable, shallow, class-oriented, and low in specificity.
- Question important declarations, inline styles, unlayered rules, and source-order dependence.
- Follow the repository's naming, file, module, token, and cascade-layer architecture.
- Keep parent placement separate from component internal layout.
- Reuse meaningful components and tokens without abstracting accidental similarity.
- Prefer intrinsic and bounded sizes over fragile fixed dimensions.
- Inspect overflow, long content, images, Flexbox minimums, and Grid tracks.
- Use absolute, fixed, sticky, and z-index behavior with clear containing contexts.
- Base breakpoints on content and consider fluid or container-aware alternatives.
- Use logical properties and test right-to-left direction.
- Verify typography, font fallbacks, wrapping, ellipsis, media cropping, and layout shift.
- Preserve form semantics, visible focus, keyboard interaction, touch targets, and contrast.
- Test themes, reduced motion, forced colors, state combinations, and long translations.
- Check browser support, real multi-engine behavior, and functional fallback paths.
- Measure expensive effects and avoid broad performance hints.
- Inspect generated production CSS, dependencies, utility output, and bundle growth.
- Remove dead rules, temporary diagnostics, old components, and obsolete workarounds.
Key Takeaway
A weak CSS review asks whether the default desktop screenshot looks correct. A strong review asks whether the cascade remains predictable, the component owns the right responsibilities, content can grow, responsive behavior follows real constraints, interaction stays accessible, themes and browsers remain supported, and the code will still make sense to another developer.
The goal is not maximum abstraction or the newest syntax. It is a clear, standards-based solution that fits the repository, handles complete states, and introduces no unexplained authority or hidden debt. Review behavior and source together, automate repeatable checks, make comments evidence-based, and approve CSS that protects both the current interface and the next change.