Search by

bugo / flexgrid

Bugo

Fluent PHP builder for CSS Grid and Flexbox layouts

0.2 2026-09-24 00:45 UTC

This package is auto-updated.

Last update: 2026-09-24 00:55:54 UTC


README

PHP Coverage Status

English | Русский

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 {
  place-self: start end;
}

Each item is emitted as its own multi-line rule. Note that setting both alignSelf() and justifySelf() collapses into the place-self shorthand (align justify order).

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;
}

Line-based placement comes in two forms that must not be mixed on the same item:

  • Area placement via area(), place(), namedArea() or span() (emits the grid-row/grid-column/grid-area shorthands).
  • Individual line properties via rowStart(), rowEnd(), columnStart(), columnEnd() (emits the grid-*-start/grid-*-end longhands).

Combining the two on one GridItem throws an InvalidArgumentException at configuration time, so an ambiguous placement never reaches the generated CSS. Likewise, a named GridArea and line-based coordinates are mutually exclusive: calling rowStart(), columnEnd(), spanRows() and friends on GridArea::named(...) throws.

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;
  }
}

Each variant is configured from scratch, but only the properties that actually differ from the base container are emitted inside the @media block. Unchanged declarations (such as display) are dropped, and a variant that changes nothing produces no @media block at all.

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

Placement is chosen with one of the following (they are mutually exclusive — see Line-based placement):

// Named area
GridItem::select('.selector')->namedArea('main');       // grid-area: main

// Line placement by coordinates
GridItem::select('.selector')->place(2, 1);              // grid-row: 2 / auto; grid-column: 1 / auto

// Auto-placement by span only
GridItem::select('.selector')->span(rowSpan: 2, colSpan: 3);  // grid-row: span 2; grid-column: span 3

// Full GridArea object
GridItem::select('.selector')->area(GridArea::at(1, 2)->spanRows(2));

Self-alignment and order are independent of placement and can be added to any of the above:

GridItem::select('.selector')
    ->place(2, 1)
    ->alignSelf(ItemAlignment::Start)        // align-self: start
    ->justifySelf(ItemAlignment::End)        // justify-self: end
    ->order(2)                               // order: 2
    ->toCss();                               // returns the CSS string

Setting both alignSelf() and justifySelf() collapses into the place-self shorthand. placeSelf(ItemAlignment $align, ?ItemAlignment $justify = null) sets both axes at once.

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.

Validation and errors

Configuration is validated eagerly: invalid input throws an InvalidArgumentException when you call the method, not later during CSS generation.

Numeric constraints

Method Rule
GridValue::fr($n) $n must not be negative (0fr is allowed).
GridValue::repeat($count, ...) an integer $count must be >= 1; keyword counts like auto-fill/auto-fit are passed through.
GridBuilder::repeatColumns() / repeatRows(), Grid::columns() column/row count must be >= 1.
GridArea::spanRows() / spanColumns(), GridItem::span() span must be >= 1.
FlexItem::grow() / shrink() / flex() grow and shrink must not be negative (0 is allowed).

order() accepts any integer, including negatives, because negative order is valid CSS.

Track and placement calls

  • columns(...) / rows(...) accumulate their tracks across calls; a call without arguments adds nothing.
  • Area placement and individual line properties are mutually exclusive on a GridItem (see Line-based placement).
  • A named GridArea cannot also carry line-based coordinates.

GridTemplate constraints

grid-template-areas must be rectangular, so GridTemplate::row() (and the areaRows() shortcut) enforce:

  • rows must not be empty;
  • every cell must be a non-empty token without whitespace or quotes (use . for an empty cell);
  • every row must have the same number of columns as the first row.

CSS string safety

User-supplied strings (selectors, track sizes, gaps, media queries, item values) are not validated as CSS — passing otherwise valid CSS is the caller's responsibility. The library does apply a minimal deny-list that rejects, at configuration time, only the characters that could break out of the surrounding CSS/HTML context:

Position Rejected characters
Selectors, media queries { } < ; and control characters (tab, newline, \0, …)
Property values (tracks, gaps, sizes, flex-basis, named lines, …) { } < > ; " ' and control characters

This is a breakout guard, not a CSS validator: legitimate CSS such as minmax(0, 1fr), calc(100% - 20px), var(--x), the child combinator .a > .b, and quoted attribute selectors [type="text"] all pass. Two consequences worth noting:

  • Values are also meant to be safe inside an HTML style="…" attribute, so " and ' are rejected in values.
  • Media Queries Level 4 range syntax that relies on < (e.g. (width < 640px)) is rejected; use (min-width: …) / (max-width: …) instead.

Limitations

  • FlexItem has no justifySelf(): justify-self has no effect in Flexbox. Use margin: auto on the item or justifyContent() on the container instead.
  • Only the delta relative to the base container is emitted inside a @media block; a responsive variant that changes nothing produces no block (see Responsive breakpoints).
  • The library generates CSS text only. Beyond the breakout deny-list above, it does not parse or validate arbitrary CSS values.

API reference

Compact signatures for every public builder and facade method, with the CSS each one produces. GridValue, GridArea, GridItem, FlexItem and GridTemplate also have dedicated example sections above.

Container methods (shared by GridBuilder and FlexBuilder)

Method Returns CSS / effect
make(string $selector = '') static Factory; the argument becomes the rule selector (empty = no selector).
gap(string $rowGap, ?string $columnGap = null) $this gap: <row>, or gap: <row> <column> when they differ.
rowGap(string $gap) self row-gap: <gap>
columnGap(string $gap) self column-gap: <gap>
alignContent(ContentAlignment $a) self align-content: <a>
justifyContent(ContentAlignment $a) self justify-content: <a>
placeContent(ContentAlignment $align, ?ContentAlignment $justify = null) self place-content: <align> [<justify>]; collapses to one value when equal.
responsive(int $minWidth, callable $configure) self Wraps the variant delta in @media (min-width: <minWidth>px).
media(string $query, callable $configure) self Wraps the variant delta in @media <query>.
build(string $indent = '') string Full CSS: container rule, child rules and @media blocks.
toInlineStyle() string prop: val; … for the container only — no selector, no braces.

GridBuilder

Adds grid-specific methods on top of the shared container methods.

Method Returns CSS / effect
inline() self display: inline-grid
columns(string ...$tracks) self Appends tracks to grid-template-columns (accumulates across calls).
rows(string ...$tracks) self Appends tracks to grid-template-rows (accumulates across calls).
repeatColumns(int $count, string $track = '1fr') self Appends repeat(<count>, <track>) to the columns.
repeatRows(int $count, string $track = '1fr') self Appends repeat(<count>, <track>) to the rows.
autoFillColumns(string $min, string $max = '1fr') self Appends repeat(auto-fill, minmax(<min>, <max>)).
autoFitColumns(string $min, string $max = '1fr') self Appends repeat(auto-fit, minmax(<min>, <max>)).
areas(GridTemplate $template) self grid-template-areas: <template>
areaRows(mixed ...$rows) self Builds grid-template-areas from strings or arrays of names.
autoRows(string $size) self grid-auto-rows: <size>
autoColumns(string $size) self grid-auto-columns: <size>
autoFlow(GridValue|string $flow) self grid-auto-flow: <flow>. Accepts a GridValue case (Row, Column, RowDense, ColumnDense) or a raw string.
alignItems(ItemAlignment $a) self align-items: <a>
justifyItems(ItemAlignment $a) self justify-items: <a>
placeItems(ItemAlignment $align, ?ItemAlignment $justify = null) self place-items: <align> [<justify>]; collapses to one value when equal.
item(GridItem $item) self Appends one child rule.
items(list<GridItem> $items) self Appends several child rules.

FlexBuilder

Adds flex-specific methods on top of the shared container methods.

Method Returns CSS / effect
inline() self display: inline-flex
direction(FlexDirection $value) self flex-direction: <value> (merges into flex-flow when wrap is also set).
wrap(FlexWrap $value) self flex-wrap: <value> (merges into flex-flow when direction is also set).
noWrap() self flex-wrap: nowrap
wrapReverse() self flex-wrap: wrap-reverse
flow(FlexDirection $direction, FlexWrap $wrap) self flex-flow: <direction> <wrap>
alignItems(ItemAlignment $a) self align-items: <a>
item(FlexItem $item) self Appends one child rule.
items(list<FlexItem> $items) self Appends several child rules.

When both direction() and wrap() are set (directly or via flow()), the two collapse into a single flex-flow declaration.

Grid facade

Every preset returns a ready-to-chain GridBuilder.

Method Returns CSS / effect
Grid::container(string $selector = '') GridBuilder Empty grid container.
Grid::item(string $selector = '') GridItem New grid item.
Grid::template() GridTemplate New area template.
Grid::area() GridArea New placement area.
Grid::columns(int $n, string $selector = '', string $gap = '1rem') GridBuilder grid-template-columns: repeat(<n>, 1fr) + gap.
Grid::fluid(string $selector = '', string $minWidth = '250px', string $gap = '1rem') GridBuilder repeat(auto-fill, minmax(<minWidth>, 1fr)) + gap.
Grid::sidebar(string $selector = '', string $sideWidth = '260px', string $gap = '1.5rem') GridBuilder grid-template-columns: <sideWidth> 1fr + gap.
Grid::centered(string $selector = '', string $maxWidth = '720px', string $gap = '1rem') GridBuilder grid-template-columns: 1fr minmax(0, <maxWidth>) 1fr + gap.
Grid::holyGrail(string $selector = '', string $sideWidth = '200px', string $asideWidth = '160px', string $gap = '0') GridBuilder header / (sidebar + main + aside) / footer areas + gap.
Grid::dashboard(string $selector = '', string $sidebarWidth = '240px', string $headerHeight = '60px') GridBuilder header / (nav + main) / (nav + footer) areas.
Grid::masonry(string $selector = '', string $minWidth = '220px', string $gap = '1rem') GridBuilder auto-fill columns + grid-auto-rows: 10px + grid-auto-flow: row dense.

Every preset returns a ready-to-chain FlexBuilder.

Method Returns CSS / effect
Flex::container(string $selector = '') FlexBuilder Empty flex container.
Flex::item(string $selector = '') FlexItem New flex item.
Flex::row(string $selector = '', string $gap = '1rem') FlexBuilder flex-direction: row + gap.
Flex::column(string $selector = '', string $gap = '1rem') FlexBuilder flex-direction: column + gap.
Flex::cards(string $selector = '', string $minWidth = '250px', string $gap = '1rem') FlexBuilder row + wrap + gap; child <selector> > *: flex: 1 1 <minWidth>.
Flex::sidebar(string $selector = '', string $sideWidth = '260px', string $gap = '1.5rem') FlexBuilder row + gap; first child flex: 0 0 <sideWidth>, last child flex: 1 1 0.

Flex::cards() and Flex::sidebar() only emit child rules when $selector is non-empty.

GridItem

Method Returns CSS / effect
GridItem::select(string $selector) static Factory.
area(GridArea $area) self The area's grid-* properties.
place(int $row, int $col) self grid-row: <row> / auto; grid-column: <col> / auto
span(int $rowSpan, int $colSpan) self grid-row: span <rowSpan>; grid-column: span <colSpan>
namedArea(string $name) self grid-area: <name>
rowStart / rowEnd / columnStart / columnEnd (int|string $line) self grid-<axis>-start / grid-<axis>-end longhands.
alignSelf(ItemAlignment $a) self align-self: <a>
justifySelf(ItemAlignment $a) self justify-self: <a>
placeSelf(ItemAlignment $align, ?ItemAlignment $justify = null) self place-self: <align> [<justify>]; collapses to one value when equal.
order(int $order) self order: <order>
toCss(string $indent = '') string The item's CSS rule.

Area placement (area()/place()/span()/namedArea()) and the individual line longhands are mutually exclusive; alignSelf() + justifySelf() collapse into place-self.

FlexItem

Method Returns CSS / effect
FlexItem::select(string $selector) static Factory.
grow(int|float $value) self flex-grow: <value>
shrink(int|float $value) self flex-shrink: <value>
basis(string $value) self flex-basis: <value>
flex(int|float $grow, int|float $shrink, string $basis) self flex: <grow> <shrink> <basis>
alignSelf(ItemAlignment $a) self align-self: <a>
order(int $value) self order: <value>
toCss(string $indent = '') string The item's CSS rule.

flex() and the grow()/shrink()/basis() longhands are mutually exclusive — setting either side clears the other. FlexItem has no justifySelf() (see Limitations).

References