承接 bugo/flexgrid 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

bugo/flexgrid

Composer 安装命令:

composer require bugo/flexgrid

包简介

Fluent PHP builder for CSS Grid and Flexbox layouts

README 文档

README

PHP Coverage Status

Fluent PHP library for generating CSS Grid and Flexbox layouts. Supports named areas, line-based placement, responsive breakpoints, and ready-made presets for common patterns.

Installation

composer require bugo/flexgrid

Quick start

use FlexGrid\Grid;

echo Grid::columns(3, '.grid', '1.5rem')->build();
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

GridBuilder

GridBuilder is the main class. All methods return static, so they chain freely.

Columns and rows

use FlexGrid\GridBuilder;
use FlexGrid\Enums\GridValue;

GridBuilder::make('.layout')
    ->columns('200px', '1fr', '200px')   // fixed values
    ->rows('64px', '1fr', '48px')        // row tracks
    ->gap('1rem')
    ->build();

Use GridValue helpers to avoid writing CSS strings by hand:

GridBuilder::make('.layout')
    ->columns(
        GridValue::fr(1),                          // "1fr"
        GridValue::minmax('200px', '1fr'),         // "minmax(200px, 1fr)"
        GridValue::repeat(3, GridValue::fr(1)),    // "repeat(3, 1fr)"
    )
    ->autoRows(GridValue::minmax('100px', 'auto')) // grid-auto-rows
    ->build();

Shorthand methods for repeated tracks:

GridBuilder::make('.grid')
    ->repeatColumns(4, '1fr')         // repeat(4, 1fr)
    ->repeatRows(3, '200px')          // repeat(3, 200px)
    ->autoFillColumns('250px')        // repeat(auto-fill, minmax(250px, 1fr))
    ->autoFitColumns('250px', '1fr')  // repeat(auto-fit,  minmax(250px, 1fr))
    ->build();

Gap

->gap('1rem')           // gap: 1rem  (both axes)
->gap('1rem', '2rem')   // gap: 1rem 2rem  (row, column)
->rowGap('1rem')        // row-gap only
->columnGap('2rem')     // column-gap only

Named template areas

Use GridTemplate to define the visual layout as an ASCII-art grid:

use FlexGrid\GridTemplate;

GridBuilder::make('.page')
    ->columns('220px', '1fr')
    ->rows('60px', '1fr', '40px')
    ->areas(GridTemplate::create()
        ->row(['header', 'header'])
        ->row(['nav',    'main'])
        ->row(['nav',    'footer']))
    ->build();
.page {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas:
    "header header"
    "nav main"
    "nav footer";
}

For a more compact syntax, pass the area names as strings directly:

GridBuilder::make('.page')
    ->areaRows(
        'header header',
        'nav    main',
        'nav    footer',
    )
    ->build();

Grid items (child elements)

Attach GridItem objects to the builder to generate child selectors alongside the container:

use FlexGrid\GridItem;
use FlexGrid\Enums\ItemAlignment;

GridBuilder::make('.page')
    ->columns('220px', '1fr')
    ->rows('60px', '1fr', '40px')
    ->areaRows('header header', 'nav main', 'nav footer')
    ->item(GridItem::select('.page__header')->namedArea('header'))
    ->item(GridItem::select('.page__nav')->namedArea('nav'))
    ->item(GridItem::select('.page__main')->namedArea('main'))
    ->item(
        GridItem::select('.page__aside')
            ->justifySelf(ItemAlignment::End)
            ->alignSelf(ItemAlignment::Start)
    )
    ->build();
.page {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas:
    "header header"
    "nav main"
    "nav footer";
}

.page__header { grid-area: header; }
.page__nav    { grid-area: nav; }
.page__main   { grid-area: main; }
.page__aside  { justify-self: end; align-self: start; }

Line-based placement

When named areas are not used, place items by grid line numbers:

use FlexGrid\GridArea;

GridBuilder::make('.gallery')
    ->repeatColumns(4, '1fr')
    ->gap('1rem')
    ->item(
        GridItem::select('.gallery__hero')
            ->area(GridArea::at(1, 1)->spanRows(2)->spanColumns(2))
    )
    ->item(
        GridItem::select('.gallery__wide')
            ->area(GridArea::at(3, 1)->spanColumns(3))
    )
    ->item(
        GridItem::select('.gallery__tall')
            ->area(GridArea::at(1, 4)->rowEnd(4))
    )
    ->build();
.gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.gallery__hero  { grid-row: 1 / span 2; grid-column: 1 / span 2; }
.gallery__wide  { grid-row: 3 / auto;   grid-column: 1 / span 3; }
.gallery__tall  { grid-row: 1 / 4;      grid-column: 4 / auto;   }

Alignment

Grid alignment is split into two enums:

  • ItemAlignment: align-items, justify-items, align-self, justify-self
  • ContentAlignment: align-content, justify-content
use FlexGrid\Enums\ContentAlignment;
use FlexGrid\Enums\ItemAlignment;

GridBuilder::make('.grid')
    ->columns(GridValue::repeat(3, '200px'))
    ->placeItems(ItemAlignment::Center)                  // align-items + justify-items
    ->placeContent(ContentAlignment::Center)             // align-content + justify-content
    ->build();

// Or set each axis individually:
GridBuilder::make('.grid')
    ->alignItems(ItemAlignment::Start)
    ->justifyItems(ItemAlignment::End)
    ->alignContent(ContentAlignment::SpaceBetween)
    ->justifyContent(ContentAlignment::SpaceAround)
    ->build();

ItemAlignment cases: Start, End, Center, Stretch, Baseline.

ContentAlignment cases: Start, End, Center, Stretch, SpaceBetween, SpaceAround, SpaceEvenly.

Self-alignment on items:

GridItem::select('.box')
    ->placeSelf(ItemAlignment::Center)       // align-self + justify-self
    ->build();

GridItem::select('.box')
    ->alignSelf(ItemAlignment::Start)
    ->justifySelf(ItemAlignment::End)
    ->build();

Auto flow and implicit tracks

GridBuilder::make('.masonry')
    ->autoFillColumns('220px')
    ->autoRows('10px')           // fine-grained implicit rows for JS masonry
    ->autoFlow('row dense')      // fill gaps greedily
    ->build();

Responsive breakpoints

responsive(int $minWidth, callable) wraps a variant in @media (min-width: …). media(string $query, callable) accepts any media query string.

GridBuilder::make('.layout')
    ->columns('1fr')
    ->gap('1rem')
    ->responsive(640, fn(GridBuilder $g) =>
        $g->columns('1fr', '1fr')
    )
    ->responsive(1024, fn(GridBuilder $g) =>
        $g->columns('1fr', '1fr', '1fr')
          ->gap('2rem')
    )
    ->media('(prefers-reduced-motion: reduce)', fn(GridBuilder $g) =>
        $g->autoFlow('row')
    )
    ->build();
.layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

@media (min-width: 640px) {
  .layout { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 1024px) {
  .layout { grid-template-columns: 1fr 1fr 1fr; gap: 2rem; }
}

@media (prefers-reduced-motion: reduce) {
  .layout { grid-auto-flow: row; }
}

Inline styles

toInlineStyle() returns a string suitable for the HTML style attribute — no selector, no braces:

$style = GridBuilder::make()
    ->columns('1fr', '2fr')
    ->gap('1rem')
    ->toInlineStyle();

// "display: grid; grid-template-columns: 1fr 2fr; gap: 1rem"
<div style="<?= $style ?>">…</div>

Inline grid

GridBuilder::make('.widget')
    ->inline()          // display: inline-grid
    ->columns('auto', '1fr')
    ->build();

Presets

The Grid facade provides one-liner factory methods for the most common layouts. Every preset returns a GridBuilder you can keep chaining.

Grid::columns()

Equal N-column layout.

Grid::columns(3, '.grid', '1.5rem')->build();
// grid-template-columns: repeat(3, 1fr); gap: 1.5rem

Grid::fluid()

Responsive fluid columns using auto-fill. Columns collapse automatically when the container is too narrow.

Grid::fluid('.cards', '280px', '1.25rem')->build();
// grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))

Grid::sidebar()

Fixed-width sidebar on the left, fluid content on the right.

Grid::sidebar('.layout', '260px', '2rem')->build();
// grid-template-columns: 260px 1fr

Grid::centered()

Centers content at a max-width by placing fluid gutters on either side.

Grid::centered('.page', '860px')->build();
// grid-template-columns: 1fr minmax(0, 860px) 1fr

Place your content in the middle column:

GridItem::select('.page__content')->place(1, 2)->build();
// grid-row: 1 / auto; grid-column: 2 / auto

Grid::holyGrail()

Classic five-area layout: header across the top, sidebar + main content + aside in the middle, footer across the bottom.

Grid::holyGrail('.page', sideWidth: '220px', asideWidth: '160px')->build();
.page {
  display: grid;
  grid-template-columns: 220px 1fr 160px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header  header"
    "sidebar main    aside"
    "footer  footer  footer";
}

Grid::dashboard()

Two-column dashboard with a persistent sidebar and a three-row main area.

Grid::dashboard('.app', sidebarWidth: '240px', headerHeight: '64px')->build();
.app {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr auto;
  grid-template-areas:
    "header header"
    "nav    main"
    "nav    footer";
}

Grid::masonry()

Dense auto-flow grid for JavaScript masonry: items are placed greedily to fill gaps. Pair with JS to calculate grid-row-end per item.

Grid::masonry('.wall', '240px', '1rem')->build();
// grid-template-columns: repeat(auto-fill, minmax(240px, 1fr))
// grid-auto-rows: 10px
// grid-auto-flow: row dense

GridValue reference

Static helpers for CSS Grid value functions. All return plain strings.

Call Output
GridValue::fr(1) "1fr"
GridValue::fr(2.5) "2.5fr"
GridValue::minmax('200px', '1fr') "minmax(200px, 1fr)"
GridValue::repeat(3, '1fr') "repeat(3, 1fr)"
GridValue::repeat('auto-fill', '1fr') "repeat(auto-fill, 1fr)"
GridValue::fitContent('300px') "fit-content(300px)"
GridValue::Auto->value "auto"
GridValue::MaxContent->value "max-content"
GridValue::MinContent->value "min-content"

GridArea reference

// Named area (outputs grid-area)
GridArea::named('header');

// Line-based (outputs grid-row + grid-column)
GridArea::at(rowStart: 1, columnStart: 1)
    ->spanRows(2)
    ->spanColumns(3);

// Explicit end lines
GridArea::at(2, 1)
    ->rowEnd(5)
    ->columnEnd(4);

// Set lines individually
(new GridArea())
    ->rowStart(1)
    ->columnStart(3)
    ->spanRows(2);

GridItem reference

GridItem::select('.selector')
    ->namedArea('main')                      // grid-area: main
    ->place(2, 1)                            // grid-row: 2; grid-column: 1
    ->span(rowSpan: 2, colSpan: 3)           // span 2 rows, 3 columns
    ->area(GridArea::at(1, 2)->spanRows(2))  // full GridArea object
    ->alignSelf(ItemAlignment::Start)
    ->justifySelf(ItemAlignment::End)
    ->placeSelf(ItemAlignment::Center)       // both axes
    ->order(2)
    ->toCss();                               // returns CSS string

GridTemplate reference

$template = GridTemplate::create()
    ->row(['header', 'header', 'header'])
    ->row(['nav',    'main',   'aside'])
    ->row(['footer', 'footer', 'footer']);

$template->build();          // CSS value string for grid-template-areas
$template->getAreaNames();   // ['header', 'nav', 'main', 'aside', 'footer']
$template->columnCount();    // 3
$template->rowCount();       // 3

Flex Examples

Basic row with gap

use FlexGrid\Flex;

Flex::row('.menu', '1rem')->build();
.menu {
  display: flex;
  flex-direction: row;
  gap: 1rem;
}

Flexible cards with wrapping

use FlexGrid\Enums\FlexDirection;
use FlexGrid\Enums\FlexWrap;
use FlexGrid\FlexBuilder;

FlexBuilder::make('.cards')
    ->direction(FlexDirection::Row)
    ->wrap(FlexWrap::Wrap)
    ->gap('1rem')
    ->item(FlexItem::select('.cards > .card')->flex(1, 1, '240px'))
    ->build();
.cards {
  display: flex;
  flex-flow: row wrap;
  gap: 1rem;
}

.cards > .card { flex: 1 1 240px; }

Toolbar alignment

use FlexGrid\Enums\ContentAlignment;
use FlexGrid\Enums\FlexDirection;
use FlexGrid\Enums\ItemAlignment;
use FlexGrid\FlexBuilder;

FlexBuilder::make('.toolbar')
    ->direction(FlexDirection::Row)
    ->justifyContent(ContentAlignment::SpaceBetween)
    ->alignItems(ItemAlignment::Center)
    ->build();
.toolbar {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

Responsive direction switch

use FlexGrid\Enums\FlexDirection;
use FlexGrid\FlexBuilder;

FlexBuilder::make('.layout')
    ->direction(FlexDirection::Column)
    ->gap('1rem')
    ->responsive(768, fn(FlexBuilder $f) => $f->direction(FlexDirection::Row))
    ->build();
.layout {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

@media (min-width: 768px) {
  .layout { flex-direction: row; }
}

Direction/wrap helpers and repeated gap calls

use FlexGrid\Enums\FlexDirection;
use FlexGrid\FlexBuilder;

FlexBuilder::make('.rail')
    ->direction(FlexDirection::ColumnReverse)
    ->noWrap()         // flex-wrap: nowrap
    ->gap('0.5rem')
    ->gap('1rem')      // last call wins
    ->build();
.rail {
  display: flex;
  flex-flow: column-reverse nowrap;
  gap: 1rem;
}

Flex Presets

The Flex facade provides one-liner factory methods for common Flexbox layouts.

Flex::row()

Flex::row('.menu', '0.75rem')->build();
// display: flex; flex-direction: row; gap: 0.75rem

Flex::column()

Flex::column('.stack', '0.5rem')->build();
// display: flex; flex-direction: column; gap: 0.5rem

Flex::cards()

Flex::cards('.cards', '240px', '1rem')->build();
// container: row + wrap + gap
// children (.cards > *): flex: 1 1 240px

Flex::sidebar()

Flex::sidebar('.layout', '260px', '1.5rem')->build();
// first child: flex: 0 0 260px
// last child:  flex: 1 1 0

FlexBuilder wrapping helpers

use FlexGrid\Enums\FlexDirection;
use FlexGrid\Enums\FlexWrap;
use FlexGrid\FlexBuilder;

FlexBuilder::make('.list')
    ->direction(FlexDirection::RowReverse)
    ->wrapReverse();   // flex-wrap: wrap-reverse

noWrap() is shorthand for wrap(FlexWrap::NoWrap). Repeated gap(...) calls do not accumulate: the last call replaces the previous value.

References

bugo/flexgrid 适用场景与选型建议

bugo/flexgrid 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 03 月 12 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「css grid」 「css grid php」 「css grid builder」 「css grid flex」 「css flexbox」 「css flexbox php」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 bugo/flexgrid 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 bugo/flexgrid 我们能提供哪些服务?
定制开发 / 二次开发

基于 bugo/flexgrid 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 30
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-12