For the last couple of years we kept flexbox mostly to component-level layout — centering things, evenly spacing a row of buttons — while leaving the overall page grid to floats or an existing framework's grid classes, out of caution about older browser support. With IE10/11 and evergreen browsers all handling the stable flexbox spec well at this point, we have shifted almost all new layout work, page-level grids included, over to flexbox.
What actually got simpler
The difference in day-to-day development is real. Vertical centering, which used to mean a small ritual of table-display hacks or absolute positioning tricks with negative margins calculated by hand, is now `align-items: center` and done. Equal-height columns, which used to require either JavaScript to measure and set heights or a faux-column background-image trick, now fall out naturally from flexbox's default `stretch` behavior. Sidebar layouts that reflow into a stacked mobile layout, sticky footers that stay at the bottom of a short page without being pinned with `position: fixed`, and evenly distributed navigation items — all of it gets simpler, and more importantly, all of it gets more predictable across the handful of edge cases (an unusually long word, an empty state with no content) that used to break our old float-based approach.
Reordering without touching markup
One capability that has quietly changed how we build responsive layouts is the `order` property. A card layout that needs its call-to-action button visually first on mobile but last on desktop used to mean either duplicating markup or reaching for JavaScript to physically move DOM nodes around at different breakpoints. With flexbox, the markup order can match whatever makes sense for source order and accessibility, and `order` handles the purely visual rearrangement per breakpoint. We use this often enough now that it has become one of the first tools we reach for when a designer's mobile mockup rearranges content relative to the desktop version.
A few gotchas we ran into along the way
- `flex-shrink` defaults to allowing items to shrink below their content's natural size, which caused a couple of unexpected text-truncation bugs before we learned to set `min-width: 0` on flex children containing long unbroken strings
- Browser rendering differences between older flexbox spec drafts (which some older Android browsers still implement) and the final spec occasionally show up as subtle spacing differences, worth a manual check on a real device rather than trusting a desktop browser alone
- `justify-content: space-between` behaves differently than most people expect with only one or two items, which has tripped up more than one of our own developers mid-project, usually surfacing as a button that looks fine with three items in a row but jumps to a strange position once a fourth is removed
- Nesting flex containers several levels deep can produce sizing behavior that is genuinely hard to reason about without opening dev tools, particularly when `flex-grow` values interact across levels — we now try to keep nesting shallow and reach for explicit widths at the point where a layout would otherwise need three or four nested flex containers to express
How we are training the team on it
Because flexbox's mental model is different enough from float-based layout that old habits do not transfer cleanly, we put together a short internal reference covering the handful of properties that cover ninety percent of real layout needs — `display: flex`, `flex-direction`, `justify-content`, `align-items`, and `flex-wrap` — rather than trying to get everyone fluent in the full spec at once. New developers pick up the basics from that reference in an afternoon, and the deeper properties like `flex-basis` and `align-self` come up naturally in code review when a specific layout actually calls for them.
Where we still reach for floats
We still keep an eye on the handful of older Android browsers some clients care about, and for genuinely legacy projects we are only patching rather than rebuilding, we leave the existing float-based layout alone rather than introducing flexbox halfway through a codebase that was not built around it — mixing the two approaches in one layout has burned us before, usually in the form of a float that does not clear correctly next to a flex container that assumes it is the only layout mechanism in play.
For the bulk of our new work, though, floats are officially retired, and onboarding a new developer onto a flexbox-based layout has been noticeably faster than walking them through the accumulated float-clearing conventions — clearfix hacks, explicit width percentages, `overflow: hidden` used purely as a clearing trick — of an older project. It is rare that a change to how we write CSS pays for itself this quickly and this broadly across nearly every project we touch.
Combining flexbox with existing grid frameworks
Several of our client projects still run on a Bootstrap-derived grid system that predates our flexbox adoption, and rather than ripping that grid out wholesale, we have generally let it continue to handle the coarse, page-level column structure while using flexbox freely inside individual grid cells for anything needing more nuanced alignment. This hybrid approach is not architecturally pure, but it has let us adopt flexbox incrementally across a large existing codebase rather than requiring a disruptive full rewrite of every template just to start benefiting from it, which would have been a hard sell to any client not otherwise budgeting for a layout overhaul.
Testing across real devices, not just breakpoint resizing
One habit we picked up specifically because of a couple of flexbox surprises: resizing a desktop browser window to simulate a mobile breakpoint does not reliably catch every rendering quirk, particularly around how certain older mobile browsers implement `flex-wrap` and minimum sizing differently than their desktop counterparts. We added a short manual pass on two or three real physical devices — a mix of iOS and a mid-range Android phone — to our pre-launch checklist specifically to catch this category of issue, after a launched project shipped with a flexbox row that wrapped correctly in every desktop browser's responsive mode but broke unexpectedly on one specific popular Android phone's stock browser.
Where flexbox has changed how we brief designers
The shift to flexbox has also changed conversations with the designers we work with, since a layout that would have needed careful, explicit pixel measurements to hand off cleanly for a float-based build can often be described more loosely — "these three cards should always be equal height and evenly spaced" — and translated directly into flexbox properties without the back-and-forth clarification that a more rigid layout technique used to require. Designers who have picked up even a rough sense of how flexbox thinks about space distribution tend to hand off cleaner, more implementation-aware mockups as a result, which has quietly improved our whole design-to-development handoff process beyond just the CSS itself.
Performance impact worth calling out
We did not expect a CSS layout change to show up in performance numbers, but it did, modestly. Float-based layouts on a couple of our older, more complex templates relied on JavaScript-driven height-matching scripts to fake equal-height columns, running on every window resize event. Replacing that with native flexbox `align-items: stretch` behavior removed the JavaScript entirely, along with its resize-listener overhead, which showed up as a small but measurable improvement in scripting time on our performance profiling for those specific pages. It is a minor point in isolation, but a useful reminder that a "purely visual" CSS change can remove real runtime cost that had been quietly compensating for CSS's previous limitations.
Documentation we now keep alongside the codebase
Because flexbox introduces new vocabulary — main axis, cross axis, flex basis — that does not map cleanly onto the float-and-position vocabulary most of the team grew up with, we keep a short glossary alongside our internal style guide specifically defining these terms with visual examples rather than assuming everyone absorbs them the same way from documentation alone. It is a small thing, but code review comments referencing "cross-axis alignment" land a lot better when there is an agreed, shared definition of what that phrase means sitting one click away, rather than everyone privately hoping they remember the MDN diagram correctly.
We keep the glossary short and example-driven rather than exhaustive, on the theory that a reference nobody opens because it is too long to skim helps nobody, and we update it whenever a code review comment reveals that a term is still causing genuine confusion across the team.