用Bulma构建现代化响应式页面的实战技巧
先上代码,直接开干
我最近接手一个内部工具项目,UI要求简单清爽,但不想花太多时间在样式上。之前用 Bootstrap 总觉得太重,Tailwind 又得记一堆 class,最后选了 Bulma。说实话,刚开始只是试试看,结果一用就停不下来了。
先来个最简单的布局,三栏等分布局,中间自适应。这种需求太常见了,比如左侧导航、中间内容、右侧侧边栏:
<div class="container">
<div class="columns">
<div class="column is-3">
<div class="box">左侧菜单</div>
</div>
<div class="column">
<div class="box">主要内容区(自动撑满)</div>
</div>
<div class="column is-3">
<div class="box">右侧辅助信息</div>
</div>
</div>
</div>
就这么几行,搞定响应式三栏。注意那个没有加 is-* 的 column,它会自动填满剩余空间——这招我亲测有效,比 Flex 手动写 flex-grow 省事多了。
Bulma 其实是个“纯 CSS 框架”
这里得提一嘴,Bulma 不像 Bootstrap 那样依赖 JavaScript。它就是一堆 CSS class,你拿去用就行,不用引入 jQuery 或其他 JS 库。这也是我喜欢它的原因:轻,干净。
但这也意味着,像 modal、dropdown 这些交互组件,得自己写 JS 控制显示隐藏。别慌,其实很简单。比如 modal 弹窗:
<!-- Modal Overlay -->
<div id="my-modal" class="modal">
<div class="modal-background" onclick="closeModal()"></div>
<div class="modal-content">
<div class="box">
<p>这是弹窗内容</p>
</div>
</div>
<button class="modal-close is-large" aria-label="close" onclick="closeModal()"></button>
</div>
<button class="button is-primary" onclick="openModal()">打开弹窗</button>
function openModal() {
document.getElementById('my-modal').classList.add('is-active');
}
function closeModal() {
document.getElementById('my-modal').classList.remove('is-active');
}
核心是给 modal 加 is-active class 来控制显隐。这个 class 是 Bulma 定义的,你只需要用 JS 切换它就行。我之前折腾了半天想覆盖默认样式,后来发现根本不用,直接用官方推荐方式最稳。
这个场景最好用:表单 + 按钮组
做后台管理页面时,经常要搞搜索表单,带几个输入框和按钮。Bulma 的 field 和 control 配合起来特别顺手:
<div class="field is-horizontal">
<div class="field-body">
<div class="field">
<p class="control is-expanded">
<input class="input" type="text" placeholder="用户名">
</p>
</div>
<div class="field">
<p class="control is-expanded">
<input class="input" type="email" placeholder="邮箱">
</p>
</div>
<div class="field is-narrow">
<p class="control">
<button class="button is-info">搜索</button>
</p>
</div>
<div class="field is-narrow">
<p class="control">
<button class="button is-light">重置</button>
</p>
</div>
</div>
</div>
重点是 field-body 和 is-expanded 的组合。is-expanded 让 input 自动占满可用空间,多个 input 平均分配宽度,按钮固定大小。这里注意下,我踩过坑:一开始没加 field-body,结果 layout 错乱,调试半天才发现文档里写了必须嵌套。
踩坑提醒:这三点一定注意
- 不要滥用 container:container 默认有 max-width 和居中 margin。如果你在一个已居中的 div 里再套 container,可能会出现意外留白。建议只在最外层用一次。
- 响应式 class 的优先级问题:比如你写
is-6-mobile is-3-tablet,意思是移动端占一半,平板占1/4。但如果后面又加了个is-4-desktop,desktop 下就会变成1/3。测试时一定要在不同尺寸下检查,别只看 desktop。 - 自定义主题要用 Sass:Bulma 原生支持通过 Sass 变量覆盖主题色。如果你直接写 CSS 覆盖
.button.is-primary,后期维护会疯掉。正确做法是引入 Sass 版本,改 $primary 变量:
// 自定义变量
$primary: #48c774;
$danger: #ff3860;
// 引入 Bulma(必须放变量之后)
@import "~bulma/bulma";
我之前图省事直接 override CSS,结果后来换主题颜色改了七八个文件,后悔死了。现在一律走 Sass 变量,一改全改。
高级技巧:用 level 做页头布局
很多新手会用 columns 做页头,左边标题右边按钮。但更好的方式是用 level:
<nav class="level">
<div class="level-left">
<div class="level-item">
<h2 class="subtitle is-4">用户列表</h2>
</div>
</div>
<div class="level-right">
<div class="level-item">
<button class="button is-small is-info">导出 CSV</button>
</div>
<div class="level-item">
<button class="button is-small is-primary">新增用户</button>
</div>
</div>
</nav>
level 的好处是垂直居中对齐天然做好了,而且 responsive 下会自动堆叠。相比之下,columns 在小屏下需要额外处理对齐。
API 请求示例怎么写?顺手演示下
有时候你做完前端,还得联调 API。比如提交表单后发请求,可以这样写:
async function submitForm(userData) {
try {
const response = await fetch('https://jztheme.com/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
if (!response.ok) throw new Error('提交失败');
alert('保存成功!');
} catch (error) {
alert('网络错误,请重试');
}
}
这只是个 demo,实际项目中建议封装成 service 层。不过对于小工具来说,这么写也够用了。
为什么我不再用 Bootstrap?
不是说 Bootstrap 不好,而是它太“完整”了。每次新建项目都要删掉用不到的组件,JS 还绑一堆事件监听。Bulma 就很克制,只管样式,不管逻辑。这让我的 bundle size 小了不少,Lighthouse 分数也高了两分(笑)。
而且 Bulma 的 class 命名更语义化。is-flex, is-align-items-center, is-justify-content-center —— 看名字就知道干嘛,不像 Bootstrap 的 d-flex align-items-center justify-content-center 那么缩写成性。
最后说点实在的
Bulma 不适合做复杂动画或高度定制 UI。如果你要做设计感很强的官网,它可能不够用。但它非常适合后台系统、管理面板、工具类网页——这类项目讲究的是快速出活、稳定维护。
我现在新项目基本都默认上 Bulma,配合 Vue 或 React 都很舒服。Sass 定制 + 原子化 class 组合,改个主题色半小时搞定,产品经理再来改需求也不慌。
以上是我踩坑后的总结,希望对你有帮助。这个技术的拓展用法还有很多,比如结合 FontAwesome 做图标系统、用 tile 做卡片流布局,后续会继续分享这类博客。

暂无评论