Skip to main content
How-To11 min read·2,002 words

Flexbox Generator: Mobile Layouts Without Queries

Use a flexbox generator or manual CSS to build a 320–440px mobile screen with stable header, scrolling content, tabs, and no media queries with testable rules.

#how-to#mobile app design#layout#flexbox mobile layout#css flexbox app#ios#android
floow.design Team

floow.design Team

Mobile Design·

Use a flexbox generator to define one column screen shell, then set flex-direction, justify-content, and align-items before styling anything else. Support widths from 320px to 440px with fluid widths, gap for internal spacing, and a flex: 1 content region between fixed header and tab bar. Add min-width: 0 to row children containing text so they can truncate instead of forcing horizontal overflow. Test the same layout at 320px, 375px, 390px, 414px, and 440px without adding media queries.

Key takeaways

  • flex-directionchooses the main axis;justify-contentdistributes it;align-items` controls the cross axis.
  • Use gap: 12px on a flex container instead of sibling margin rules.
  • flex: 1` makes the centre region fill space between fixed header and tab bar.
  • min-width: 0` allows a flex child containing text to shrink and truncate.
  • Treat 320px as the narrowest phone width worth supporting for this layout exercise.

This guide is for mobile UI/UX designers and engineers who can read basic CSS and need to translate a phone screen structure into implementation-ready layout rules.

Time: 25 minutes · You'll need: A code editor with CSS syntax highlighting, A browser or mobile web preview with width controls, A 320px, 375px, 390px, 414px, and 440px viewport test list, Optional: floow.design Flexbox Generator at /free-tools/flexbox-generator

What's on this page

  1. Define the responsive mobile layout shell
  2. Set the three flexbox decisions per region
  3. Replace margin hacks with gap spacing
  4. Make the centre region scroll with flex 1
  5. Allow text rows to shrink at 320px
  6. Reference table

Build a flexbox mobile layout, step by step

1. Define the responsive mobile layout shell

Create one screen-level container with a vertical main axis. Use width: 100%, max-width: 440px, min-height: 100dvh, and margin-inline: auto for a centred mobile preview. Set display: flex and flex-direction: column on this container.

flex-direction is the first decision because it defines the main axis. In a column, vertical space is the main axis and horizontal space is the cross axis. justify-content therefore controls vertical distribution, while align-items controls horizontal alignment. Set align-items: stretch on the screen shell so the header, content region, and tab bar occupy the available width without fixed width values.

Do not design the shell around a 390px screenshot. Start at 320px, then verify 375px, 390px, 414px, and 440px. A layout that only survives at one reference width is not a responsive mobile layout; it is a static artboard.

Tip: Use 100dvh rather than 100vh when the screen must react to mobile browser UI changing the visible viewport height.

2. Set the three flexbox decisions per region

For each nested region, name the three layout decisions before choosing colours, type, or icons: flex-direction, justify-content, and align-items. A common phone screen has a vertical shell, then horizontal rows inside it. For a top app bar, use display: flex, flex-direction: row, justify-content: space-between, and align-items: center.

That configuration puts the navigation control at one end, the trailing action at the other, and centres both controls on the row’s cross axis. For a profile row, use justify-content: flex-start and align-items: center; reserve space-between for elements that must deliberately separate. space-between is a poor substitute for a defined content gap because the visual distance changes as the container widens from 320px to 440px.

In a CSS flexbox app, default flex-direction is row. Write the direction explicitly anyway. It prevents a future component wrapper from silently changing the visual hierarchy when someone assumes the wrong axis.

Tip: When a row has three visual groups, wrap the centre group rather than relying on space-between to make three unrelated items appear balanced.

3. Replace margin hacks with gap spacing

Put spacing ownership on the flex container. For a vertical list, use display: flex, flex-direction: column, and gap: 12px. For an icon-and-label row, use flex-direction: row and gap: 8px. gap creates spacing only between flex items, so the first and last item do not acquire accidental outer margins.

Avoid rules such as .item + .item { margin-top: 12px; }, margin-right: 8px on every icon, or negative margins to compensate for the last child. Those patterns break when item order changes, when an item becomes hidden, or when the layout changes from a row to a column. They also make component boundaries unclear: the child appears to own space that actually belongs to its parent.

Use padding for the distance from a screen edge, and use gap for the distance between peer items. For example, a content section can use padding-inline: 16px and gap: 12px; the resulting rhythm remains identical at 320px and 440px.

Tip: Keep a 12px list gap separate from 16px screen-edge padding; combining them into child margins makes reusable list rows harder to place.

4. Make the centre region scroll with flex 1

Place three direct children inside the vertical screen shell: a header, a content region, and a bottom tab bar. Keep the header and tab bar at their content height with flex: 0 0 auto. Give the content region flex: 1, min-height: 0, and overflow-y: auto.

flex: 1 allows the content region to take the remaining height after the fixed header and fixed tab bar have been laid out. min-height: 0 is necessary in many column layouts because a flex item otherwise uses an automatic minimum size based on its content and may refuse to become smaller than a long list. The expected result is one scrolling area: the header and tab bar stay visible while cards, rows, or messages scroll beneath them.

Use this structure instead of positioning the tab bar with position: fixed for an ordinary app screen. Fixed positioning can require manual bottom padding and can overlap content. A flex column keeps all three regions in the same height calculation.

Tip: If the list still pushes the tab bar off-screen, inspect the content region first: it usually lacks min-height: 0 or has an inner element with a fixed height.

5. Allow text rows to shrink at 320px

Add min-width: 0 to every flex child that contains flexible text. In a typical message or settings row, the avatar or leading icon should use flex: 0 0 auto, while the text wrapper uses flex: 1 and min-width: 0. Apply overflow: hidden, text-overflow: ellipsis, and white-space: nowrap to a one-line title when truncation is the intended behaviour.

Without min-width: 0, a flex child can preserve its content-based minimum width. A long account name, medication title, or payment reference then expands the row beyond a 320px viewport even though the child has flex: 1. This is a common reason a layout looks correct at 440px but produces horizontal overflow at 320px.

Test with a deliberately long string of at least 40 characters, not a short placeholder name. The correct result is a stable leading control, a stable trailing control, and text that wraps or truncates according to the product rule. Do not solve this with a media query that shrinks every label at 320px.

Tip: For two-line descriptions, use wrapping rather than ellipsis, but keep min-width: 0 on the text wrapper so the trailing action remains visible.

Reference table

Viewport and layout checks

Viewport widthRequired checkExpected result
320pxNarrowest supported widthNo horizontal overflow
375pxReference phone widthSame spacing rules
390pxCommon phone widthRows remain aligned
414pxWide phone widthNo stretched gaps
440pxMaximum test widthFluid content width

Do it with the free Flexbox Generator

Build a flex layout visually, then export it as CSS, Tailwind, SwiftUI, Compose, React Native or Flutter.

Open the Flexbox Generator → — free, no sign-up.

Common mistakes

Using justify-content: space-between as the standard spacing system.

Use gap for peer spacing. Reserve space-between for deliberate edge-to-edge distribution, such as leading and trailing app-bar actions.

Giving every list item a bottom margin.

Put gap: 12px on the list container. The container owns the relationship between list items; the row owns its internal padding.

Using flex: 1 on the scroll region without min-height: 0.

Add min-height: 0 and overflow-y: auto to the middle region. This permits the region to shrink to the space left by the header and tab bar.

Fixing a long-title overflow problem with a smaller font at 320px.

Set min-width: 0 on the flexible text wrapper and define wrapping or truncation. Preserve type scale unless the product’s typography system calls for a different style.

Frequently asked questions

How do I build a flexbox mobile layout without media queries?

Build a flexbox mobile layout without media queries by using a column screen shell, fluid widths, gap, a flex: 1 content region, and min-width: 0 on shrinkable text children. Test the same rules at 320px through 440px. Add a breakpoint only when the information architecture changes, not to repair spacing caused by fixed widths or margins.

Why does my flex child overflow on a 320px phone screen?

A flex child often overflows at 320px because its automatic minimum width is based on its text or intrinsic content size. Add min-width: 0 to the flexible child, then choose text wrapping or ellipsis. Also check for fixed widths, non-wrapping labels, and nested rows that lack gap or shrink rules.

What should scroll in a CSS flexbox app screen?

Only the centre content region should scroll in a standard CSS flexbox app screen with a persistent header and bottom tab bar. Set the screen to flex-direction: column, use flex: 1, min-height: 0, and overflow-y: auto on the centre region, and keep the other two regions at flex: 0 0 auto.

Can I use the same flex layout idea in SwiftUI, Compose, React Native, and Flutter?

Yes, the same main-axis, cross-axis, grow, shrink, and gap decisions map to native mobile layout systems even though their APIs differ. In SwiftUI, stacks express vertical and horizontal grouping; in Jetpack Compose, Column and Row express the same structure. Verify each framework’s safe-area and scroll-container behaviour instead of copying CSS properties literally.

Where this leaves you

A phone screen can hold together from 320px to 440px without media queries when its structure does the work. Declare the axis first, use gap for peer spacing, let the centre region claim remaining height with flex: 1, and allow text wrappers to shrink with min-width: 0. These rules prevent the common failures: horizontal overflow, floating tab bars, inconsistent list spacing, and rows that only work on one device width. Build the layout manually in CSS first, then use floow.design’s Flexbox Generator to recreate the same decisions visually and export the implementation format your team needs.

Design the screens first

Describe the screen you need in plain English and floow.design generates production-ready iOS and Android layouts you can iterate on by chat, then export to Figma or code. Design your mobile app screens in floow.design first, then build.

Start designing free →

Related

Sources

Design your mobile app with AI

Generate pixel-perfect iOS & Android screens in seconds. Export to Figma and ship faster.