All tools run in your browser — your files never leave your device.
All tools154

Design & SEO

Flexbox or Grid, and why dark mode is not an inversion

Two front-end decisions with clear answers that get argued about anyway: which layout system, and how to build a dark theme.

The short answer. Use Flexbox for one-dimensional layout, where items flow along a single axis and their content determines the sizing. Use Grid for two-dimensional layout, where you define rows and columns in advance. For dark mode, do not invert: desaturate the colours, avoid pure black and pure white, and signal elevation with lighter surfaces rather than shadows.

One dimension or two

That is the whole distinction, and almost every other rule follows from it.

Flexbox lays out along a single axis — a row or a column — and lets content sizes drive the result. Grid defines rows and columns up front and places items into that structure, controlling both axes at once.

One dimension or two
Use caseUseWhy
Page layout with sidebarsGridRows and columns together
Navigation barFlexboxOne row, content-sized
Card of stacked contentFlexboxOne column
Image gallery in a gridGridBoth axes align
Toolbar with a spacerFlexboxmargin-left:auto pushes
Form with aligned labelsGridColumns line up across rows
Tags that wrapFlexboxContent-driven wrapping

A useful test: if you can describe the layout as a list, use Flexbox. If you have to describe it as a table, use Grid. They also nest happily — a Grid page layout containing Flexbox components is the standard arrangement, not a compromise.

Things worth knowing about both

  • gap works in Flexbox too. It was Grid-only originally, which is why so much code still uses margins on children. Browser support is universal now.
  • Grid can be one-dimensional and is often cleaner for a simple row when you want equal columns regardless of content.
  • Flexbox items shrink by default. flex-shrink: 0 is the fix for content squashing unexpectedly.
  • min-width: auto on flex items stops them shrinking below their content, which is the usual cause of overflow. Set min-width: 0 to allow it.
  • Fragmentation differs. Neither paginates reliably for print — see the note on print stylesheets.

The min-width one accounts for a large share of "why does this overflow" questions. A flex item containing a long unbroken string will refuse to shrink below that string's width, pushing the container wider, and nothing in the CSS you wrote says so.

Why inverting a light theme fails

Dark mode is not a light theme with the lightness values flipped, and doing exactly that produces the harsh, vibrating, hard-to-read result that gives dark modes a bad name.

Three things go wrong at once. Saturated colours that look fine on white appear to glow and vibrate on dark backgrounds. Pure white text on pure black is uncomfortably high contrast, causing halation where light letterforms bleed into the dark ground. And every shadow you used to signal depth becomes invisible.

The perceptual reason is that light-on-dark and dark-on-light are not symmetrical to the human eye. A light shape on a dark field appears to expand; the same shape reversed appears to contract. Type looks heavier in dark mode at identical weight, which is why some designs drop a weight for the dark theme.

Building one properly

Building one properly
ElementDo thisNot this
BackgroundA very dark grey, around #121212#000000
Body textOff-white, around #E0E0E0#FFFFFF
Accent coloursDesaturate and lightenThe same hex as light mode
ElevationLighter surface for higher layersBigger shadows
DividersLow-opacity whiteDarker lines
ImagesSlightly reduce brightnessLeave at full

Pure black deserves its own note. On OLED screens it saves power because the pixels switch off, and that is a real benefit — but the abrupt transition between an off pixel and a lit one produces visible smearing during scrolling, and the contrast against light text is fatiguing. A very dark grey keeps almost all of the aesthetic and none of the problems.

Contrast, in both directions

WCAG requires 4.5:1 for body text and 3:1 for large text and interface components, and it applies to the dark theme exactly as it does to the light one.

Dark themes fail this more often than light ones, usually on secondary text — a mid-grey that reads as pleasantly subdued against a dark background frequently measures below 4.5:1.

There is also an upper bound worth respecting, which no standard enforces. Maximum contrast is not maximum readability, and pure white on pure black at 21:1 is measurably tiring over a long read. Check every pair with Contrast Checker, and aim for comfortably above the threshold rather than as far above it as possible.

Taking colours from an image

Building a palette from a photograph or a logo is a common starting point, and the result usually needs work before it becomes a theme.

Picking a single colour is an eyedropper operation. Extracting a palette is different — algorithms group similar pixels and return the dominant clusters, which is why the colours you get are not necessarily the ones you noticed.

  • The dominant colour is often the background, not the subject. Sample deliberately rather than accepting the first result.
  • Extracted colours rarely pass contrast checks against each other. Expect to lighten or darken them.
  • Photographs give muted palettes; logos give saturated ones. They need different treatment.
  • Convert to HSL to adjust, since changing lightness while holding hue and saturation is what you almost always want.

That last point is the practical one. Colour Picker from Image pulls the values out, and Colour Converter moves them into HSL where a palette can be built by varying lightness across a single hue — which produces a coherent scheme far more reliably than picking several colours that happened to appear in one picture.

Frequently asked questions

When should I use Flexbox instead of Grid?

Flexbox for one-dimensional layout where content drives the sizing — navigation bars, toolbars, stacked cards, wrapping tags. Grid for two-dimensional layout where rows and columns must align. If you can describe it as a list, use Flexbox; if you have to describe it as a table, use Grid.

Can I use gap with Flexbox?

Yes. It was originally Grid-only, which is why older code uses margins on children instead, but browser support is now universal.

Why does my flex item overflow its container?

Flex items will not shrink below their content width by default, so a long unbroken string forces the container wider. Set min-width: 0 on the item to allow it to shrink.

Why can I not just invert my colours for dark mode?

Three things break at once: saturated colours appear to vibrate on dark backgrounds, white on black is uncomfortably high contrast and causes halation, and shadows used for depth become invisible. Light-on-dark and dark-on-light are not perceptually symmetrical.

Should dark mode use pure black?

Usually not. It saves power on OLED screens, but the transition between off and lit pixels causes visible smearing when scrolling, and the contrast against light text is fatiguing. A very dark grey around #121212 keeps the aesthetic without those problems.

How do I show elevation in dark mode?

With lighter surfaces rather than larger shadows. A shadow against a dark background is nearly invisible, so higher layers are signalled by being progressively lighter than the ones beneath them.

Why do colours extracted from an image look wrong together?

Extraction returns the dominant pixel clusters, which is often the background rather than the subject, and those colours rarely pass contrast checks against one another. Convert them to HSL and build a palette by varying lightness across a hue instead.

Stop reading, start doing

Every tool in this guide is free.

154 browser-based utilities. No account, no upload, and no file size limit — your files are processed on your own device and never sent anywhere.

Browse all 154 tools