DEV Community

Cover image for The Frontend works.. until it doesn't
Mayuri Jha
Mayuri Jha

Posted on

The Frontend works.. until it doesn't

Your UI looks Perfect… Until it meets real users

What Real-World Data Taught Me About Building Resilient Frontends

Design files are clean.
Components are reusable.
Everything aligns perfectly.

And still — things break.

Not because the code is bad.
Not because the implementation is careless.

But because the system was built around assumptions that don’t hold in production.


A Quick Context

These scenarios come from issues I’ve recently encountered while building UI.

The implementations were solid:

  • components were well-structured
  • states were handled
  • layouts matched design

Everything worked — for the expected data and expected environment.

But production doesn’t operate on expectations.

It operates on variability.


A Pattern I Keep Noticing

Across multiple UI issues, one pattern kept repeating:

Happy Path Bias

We design and build for:

  • expected data
  • expected layouts
  • expected timing

But real systems behave differently:

  • data is incomplete or malformed
  • layouts are stressed beyond design assumptions
  • rendering is asynchronous and unpredictable

Most frontend bugs don’t come from logic errors.

They come from the gap between ideal conditions and real-world variability.


Scenario 1: Product Title Overflow

Assumption

Titles will fit within design constraints

Reality

Content expands beyond expected bounds and starts influencing layout.

Failure Mode

  • Layout shifts
  • Adjacent components lose alignment
  • Vertical rhythm breaks

Fix

.product-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
Enter fullscreen mode Exit fullscreen mode

Insight

This isn’t just about truncation.

It’s about containing variability so it doesn’t propagate through the layout.


Scenario 2: “+X More” — A Simple Pattern That Isn’t

Assumption

Show first 3 items, collapse the rest

Reality

  • Items vary in length
  • Layout wraps inconsistently
  • Edge cases emerge at boundaries

Failure Mode

  • Visual inconsistency
  • Logic tied to layout behavior
  • Unpredictable rendering

Fix

maxVisible = 3;

get visibleItems() {
  return this.isExpanded ? this.items : this.items.slice(0, this.maxVisible);
}

get hiddenCount() {
  return Math.max(0, this.items.length - this.maxVisible);
}
Enter fullscreen mode Exit fullscreen mode

Insight

This shifts the system from:

layout-driven behavior

to:

deterministic state-driven behavior


Scenario 3: Skeleton Loaders That Break UX

Assumption

Any loading shimmer improves UX

Reality

If skeletons don’t match structure:

  • layout shifts when content loads
  • perceived performance degrades

Fix

.skeleton-title {
  height: 20px;
  width: 80%;
}

.skeleton-chip {
  height: 32px;
  width: 90px;
  border-radius: 16px;
}
Enter fullscreen mode Exit fullscreen mode

Insight

Skeletons are not placeholders.

They are contracts for layout stability.


Scenario 4: ExpressionChangedAfterItHasBeenCheckedError

Assumption

UI updates naturally when data arrives

Reality

Angular enforces a strict rendering contract.

When violated, it exposes instability.


Failure Mode

ExpressionChangedAfterItHasBeenCheckedError
Enter fullscreen mode Exit fullscreen mode

Fix

<div *ngIf="product">
  {{ product.name }}
</div>
Enter fullscreen mode Exit fullscreen mode

or

{{ product$ | async }}
Enter fullscreen mode Exit fullscreen mode

Insight

This is not just an Angular quirk.

It highlights a deeper principle:

Rendering must be predictable within a given cycle


Scenario 5: Resize Logic That Lies

Assumption

Screen size determines layout

Reality

Viewport ≠ device size

  • browser not maximized
  • dev tools open
  • split-screen usage

Fix

@HostListener('window:resize')
onResize() {
  this.isCompact = window.innerWidth < 1280;
}
Enter fullscreen mode Exit fullscreen mode

Insight

Responsive systems should react to:

available space, not theoretical capacity


Scenario 6: Missing or Null Data

Assumption

API contracts are reliable

Reality

Data is often:

  • incomplete
  • null
  • inconsistent

Fix

{{ product?.name || '—' }}
Enter fullscreen mode Exit fullscreen mode

Insight

Frontend is not just a rendering layer.

It is a resilience layer over imperfect systems.


Scenario 7: Button Alignment Drift

Assumption

Buttons will naturally stay aligned regardless of content


Reality

Content is not uniform.

  • Some cards have more text
  • Some have shorter descriptions
  • Heights vary dynamically

And suddenly:

👉 Buttons no longer align across cards

Button misalignment

❌ What breaks

  • Inconsistent vertical alignment of CTAs
  • Poor scannability across items
  • Visual hierarchy feels off

✅ Fix

The solution is not about the button itself — it’s about the layout structure.

HTML

<div class="card">
  <div class="content">
    <!-- dynamic content -->
  </div>

  <div class="actions">
    <button>Add to Cart</button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

CSS

.card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.actions {
  margin-top: auto;
}

.actions button {
  width: 100%;
  height: 44px;
}
Enter fullscreen mode Exit fullscreen mode

💡 Insight

This ensures:

  • Content takes natural space
  • Actions are always pushed to the bottom
  • All buttons align consistently across cards

🧠 Deeper Principle

This is not just a styling fix.

It’s about decoupling layout stability from content variability.

Instead of letting content dictate layout:

We design layouts that remain stable despite content differences


Scenario 8: Async + Partial Rendering

Assumption

Data arrives as a complete unit

Reality

Rendering is incremental.


Fix

<div *ngIf="product; else loading">
  <!-- content -->
</div>

<ng-template #loading>
  <!-- skeleton -->
</ng-template>
Enter fullscreen mode Exit fullscreen mode

Insight

UI should be designed as a set of states:

  • loading
  • partial
  • complete

Not a single static snapshot.


What This Really Points To

All of these scenarios are symptoms of the same underlying issue:

We design systems around ideal inputs, but run them in non-ideal environments.


A Shift in Thinking

Instead of asking:

“Does this work?”

A more useful question is:

“What happens when assumptions fail?”


Principles I Now Default To

  • Treat all external data as unreliable
  • Design for extremes, not averages
  • Prefer deterministic rendering over implicit behavior
  • Build UI as a system of states, not static screens
  • Contain variability instead of letting it propagate

Final Thought

Frontend engineering was never just about building interfaces.

But that realisation doesn’t come all at once — it builds gradually, through real-world scenarios and edge cases.

A significant amount of analytical and future-proof thinking goes into frontend systems. When engineered well, they don’t just render data — they absorb inconsistencies, handle unpredictability, and even mask underlying data flaws.

And this is just the surface.

There are countless such scenarios, many of which only emerge after long hours of building, debugging, and reflecting on how systems behave under real-world conditions.

Because in production:

Variability is the only constant.


These observations come from recent hands-on work where well-built components still failed under real-world conditions — not due to lack of effort, but due to assumptions that didn’t scale beyond the happy path.

Top comments (0)