Bulma columns: responsive grid sizing, gap control, and a card layout example
How to build a responsive card grid with Bulma's Flexbox columns system, handle version-sensitive gap controls, and avoid common markup pitfalls.
21 Jan 2026, 12:30 UTC

The problem with responsive grids
Building a responsive grid often means reaching for float hacks or custom media queries. When a recent project needed a card component that adapts from three columns on desktop to a single stack on mobile, Bulma's columns system offered a surprising way forward—but the gap behavior caught me off guard. The useful takeaway: Bulma's Flexbox-powered columns with responsive size modifiers can layout that grid without a single media query, but version-sensitive gap controls mean you'll want to verify your build before shipping.
How bulma's columns system works
Bulma's layout core is the .columns container with .column children, built on Flexbox. Columns share space equally by default and require no float or clearfix hacks. Because Bulma is mobile-first, unprefixed column classes apply at all sizes, and breakpoint-suffixed classes (e.g., -desktop) override behavior only from that breakpoint upward. This means a simple .column will always have width set, and adding .is-one-third reduces that width to roughly 33.3% across every device, while .is-one-third-desktop keeps the full width below the desktop breakpoint and switches to one-third above it.
Mobile-first foundation
Unprefixed classes such as .is-one-third apply at all screen sizes, serving as the baseline layout. Breakpoint-suffixed variants like .is-one-third-desktop then override that baseline only from the specified breakpoint upward, letting one markup structure adapt across mobile, tablet, and desktop without duplicate media queries.
Gap control across Bulma versions
Gap behavior changed across versions. Older Bulma relied on column padding (with .is-gapless to remove it), while newer releases introduced variable-gap controls via CSS custom properties, so gap handling is version-sensitive. In practice, this means if you inspect a .column in devtools and see generous padding on left and right, you're likely on a build that still uses the padding approach. Newer builds may expose a --bulma-gap CSS variable that you can adjust—or opt out of with .is-gapless.
Padding-based gap (older Bulma)
Versions prior to the 1.x rework typically space columns through inner padding on the column element itself. The .is-gapless class strips this padding, collapsing the gap to zero. If you're customizing spacing tokens, check whether your build expects padding-based or variable-gap CSS.
CSS-custom-property gap (newer Bulma)
Bulma 1.x reworked internals around CSS variables and added dark mode; class names stayed largely stable, but Sass-based customization from 0.9.x may need migration. Newer releases expose a --bulma-gap custom property on the .columns container, allowing you to set a global gap value that propagates to all children without per-column padding.
Nesting and complex grids
Columns can be nested by placing a new .columns element inside a .column, which is the idiomatic way to build complex grids without custom CSS. However, the columns system is less expressive than CSS Grid for two-dimensional layouts; forcing complex grids into nested columns can produce bloated markup. If your design requires both row and column control across axes, evaluate whether a hybrid approach—or pure Grid—makes more sense.
Worked example – a responsive card row
<div class='columns is-multiline'>
<div class='column is-one-third-desktop is-half-tablet'>Card A</div>
<div class='column is-one-third-desktop is-half-tablet'>Card B</div>
<div class='column is-one-third-desktop is-half-tablet'>Card C</div>
</div>On desktop the three .is-one-third-desktop columns sit side-by-side. Below the desktop breakpoint each column stacks, but the .is-half-tablet modifier then kicks in, pairing them into two-up rows on tablet-sized viewports. Below the tablet breakpoint all three collapse to full-width, mobile-stacked cards. Because Bulma ships no JavaScript, the columns system pairs cleanly with any frontend stack; interactivity (modals, dropdowns) must be wired up separately.
Verification in practice
To check your Bulma version, run cat package.json | grep bulma (or inspect the CSS header comment) in your project directory. Required permissions: read access to package.json. Meaningful placeholder: the bulma string in your dependencies. Expected check: a version number such as 1.2.3; if you see 0.9.x, note that Sass-based customization from that era may need migration for gap controls. Relevant risk: misidentifying the version leads to incorrect gap expectations—older builds will apply padding-based spacing that .is-gapless can suppress, while newer builds expect CSS variable adjustments.
Trade-offs and limitations
Importing the full bulma.css adds unused weight; importing only needed Sass modules reduces bundle size but requires a build step. The columns system is less expressive than CSS Grid for two-dimensional layouts, and nesting columns for intricate grids can result in markup that's harder to maintain than a single Grid container. Dark mode was reworked in Bulma 1.x; class names stayed largely stable, but Sass customization from 0.9.x may need review if you're tuning gap colors or spacing tokens.
Closing
If you're building a component grid that needs to adapt across devices, start with Bulma's .columns and responsive size modifiers. Verify your Bulma version, test the card-row example in a resizing browser, and decide on your gap strategy based on the build you're running. From there, you can nest columns for complexity or reach for CSS Grid when two-dimensional control outweighs the Flexbox convenience.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.