bugo / flexgrid
Fluent PHP builder for CSS Grid and Flexbox layouts
Requires
- php: ^8.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- pestphp/pest: ^3.8|^4.4
- phpstan/phpstan: ^2.1
- rector/rector: ^2.3
- roave/backward-compatibility-check: ^8.20
- vimeo/psalm: ^6.15
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
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()orspan()(emits thegrid-row/grid-column/grid-areashorthands). - Individual line properties via
rowStart(),rowEnd(),columnStart(),columnEnd()(emits thegrid-*-start/grid-*-endlonghands).
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-selfContentAlignment: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
GridAreacannot 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
FlexItemhas nojustifySelf():justify-selfhas no effect in Flexbox. Usemargin: autoon the item orjustifyContent()on the container instead.- Only the delta relative to the base container is emitted inside a
@mediablock; 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).