Bem Flex Grid
doc demo github

CSS flex grid, BEM compliant.

bem-flex-grid

CSS flex grid, BEM compliant.

A responsive grid system based on the flex display property that perfectly fits to the viewport in both width and height when needed and lets you design native app layout as well as scrollable web page.

Build Status

Getting started

The library comes with 2 syntaxes: class and attribute (or attr for short). Let's take a look at each of them.

Class syntax

The first implementation sticks to the BEM convention (Block, Element and Modifier) using only CSS class, but has a more verbose syntax.

Here's an example of a simple grid in the vertical direction (column) that uses the class syntax:

<div class="bfg bfg--col bfg--gap">
  <div class="bfg__box bfg__box--4">bem</div>
  <div class="bfg__box bfg__box--4">flex</div>
  <div class="bfg__box bfg__box--4">grid</div>
</div>

No worries, we'll explain all this in detail below. For now, let's see how this get converted to the attr syntax.

Attr syntax

The second implementation derives from the BEM convention, but has a more concise syntax.

Here are the conversion rules:

The example above get converted to the attr syntax as follows:

<div bfg="col gap">
  <div bfg__box="4">bem</div>
  <div bfg__box="4">flex</div>
  <div bfg__box="4">grid</div>
</div>

Try it

To get instant access to the library, insert the link tag of the implementation of your choice into your web pages from unpkg CDN.

Class syntax:

<link rel="stylesheet" href="https://unpkg.com/bem-flex-grid/dist/bem-flex-grid-class.min.css">

Attr syntax:

<link rel="stylesheet" href="https://unpkg.com/bem-flex-grid/dist/bem-flex-grid-attr.min.css">

Here's the full markup of the example above using the class syntax:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bem Flex Grid - Class</title>
  <link rel="stylesheet" href="https://unpkg.com/bem-flex-grid/dist/bem-flex-grid-class.min.css">
  <style>html, body { height:100%; margin:0; }</style>
</head>
<body>
  <div class="bfg bfg--col bfg--gap">
    <div class="bfg__box bfg__box--4">bem</div>
    <div class="bfg__box bfg__box--4">flex</div>
    <div class="bfg__box bfg__box--4">grid</div>
  </div>
</body>
</html>

To learn more about the features, check out the demos available for both syntaxes.

Installation and usage

Install the package from NPM (or Yarn) and insert the link tag into your web pages or use Sass import for advanced customization.

NPM

npm i bem-flex-grid

Usage with class syntax

Link tag:

<link rel="stylesheet" href="[PATH_TO_NODE_MODULES]/bem-flex-grid/dist/bem-flex-grid-class.css">

Sass import:

@use "~/bem-flex-grid/src/lib/bem-flex-grid-class.scss";

Usage with attr syntax

Link tag:

<link rel="stylesheet" href="[PATH_TO_NODE_MODULES]/bem-flex-grid/dist/bem-flex-grid-attr.css">

Sass import:

@use "~/bem-flex-grid/src/lib/bem-flex-grid-attr.scss";

Package content

bem-flex-grid/
├─ dist
│  ├─ bem-flex-grid-attr.css
│  ├─ bem-flex-grid-attr.min.css
│  │
│  ├─ bem-flex-grid-class.css
│  ├─ bem-flex-grid-class.min.css
│  │
│  ├─ bem-flex-grid-core-attr.css
│  ├─ bem-flex-grid-core-attr.min.css
│  │
│  ├─ bem-flex-grid-core-class.css
│  └─ bem-flex-grid-core-class.min.css
└─ src
   └─ lib
      ├─ attr
      │  ├─ _card.scss
      │  ├─ _core.scss
      │  └─ mixins
      │     ├─ _card.scss
      │     └─ _core.scss
      │
      ├─ class
      │  ├─ _card.scss
      │  ├─ _core.scss
      │  └─ mixins
      │     ├─ _card.scss
      │     └─ _core.scss
      │
      ├─ variables
      │  ├─ _card.scss
      │  └─ _core.scss
      │
      ├─ bem-flex-grid-attr.scss
      ├─ bem-flex-grid-class.scss
      │
      ├─ bem-flex-grid-core-attr.scss
      └─ bem-flex-grid-core-class.scss

The dist folder also contains the sourcemap for each CSS file.

Browser support

Bem-flex-grid supports the latest, stable releases of all major browsers.

API

This documentation is based on the class syntax. But as we said above, it's really easy to switch from one syntax to another.

Grid blocks and elements

At core the grid system consists of one .bfg block and one or more .bfg__box elements.

<div class="bfg">
  <div class="bfg__box">...</div>
  <div class="bfg__box">...</div>
  ...
</div>

The box's content can be anything, but the .bfg-card block can be used to fill the box with a card.

Only one card is allowed per box.

The card's content must be placed inside a .bfg-card__content element.

<div class="bfg-card">
  <div class="bfg-card__content">...</div>
</div>

Then you can add an header to the card using the optional .bfg-card__header element and one or more actions to the header using the optional .bfg-card__action element.

<div class="bfg-card">
  <div class="bfg-card__action">...</div>
  <div class="bfg-card__action">...</div>
  ...
  <div class="bfg-card__header">...</div>
  <div class="bfg-card__content">...</div>
</div>

Next, insert the .bfg-card block as a child of the .bfg__box element (nesting technique)...

<div class="bfg">
  <div class="bfg__box">
    <div class="bfg-card">
      <div class="bfg-card__content">...</div>
    </div>
  </div>
</div>

...or use the markup .bfg__box.bfg-card to treat a .bfg__box element as a .bfg-card block too (chaining technique).

<div class="bfg">
  <div class="bfg__box bfg-card">
    <div class="bfg-card__content">...</div>
  </div>
</div>

Finally, using the markup .bfg.bfg-card simply tells that the .bfg block contains cards elements (content, header and actions) that are not direct children of the .bfg-card block.

This allows you to define the default look and feel for all cards and lets you customize some of them, using the different .bfg-card--* modifiers (you'll see below how to define the card's look and feel).

But order matters! This technique works only when using the .bfg-card--primary modifier as the global look and feel.

<!-- global card definition -->
<div class="bfg bfg-card bfg-card--primary">
  <div class="bfg__box">
    <div class="bfg-card__content"><!-- use global "primary" card type --></div>
  </div>

  <div class="bfg__box">
    <div class="bfg-card__content"><!-- use global "primary" card type --></div>
  </div>

  <!-- chained card definition (at box level) -->
  <div class="bfg__box bfg-card bfg-card--secondary">
    <div class="bfg-card__content"><!-- use local "secondary" card type --></div>
  </div>

  <div class="bfg__box">
    <!-- nested card definition (as box child) -->
    <div class="bfg-card bfg-card--secondary">
      <div class="bfg-card__content"><!-- use local "secondary" card type --></div>
    </div>
  </div>
</div>

The .bfg-card block can also be used as a standalone component, outside of the .bfg block.

.bfg modifiers

Direction: .bfg--row, .bfg--col

It is required to define the direction the .bfg__box elements are placed in the .bfg block, using .bfg--row or .bfg--col modifiers.

<div class="bfg bfg--row">...</div>

When using .bfg--row modifier, the grid needs the .bfg block width (or its parent width) to be defined (and that's usually the case).

<div class="bfg bfg--col">...</div>

When using .bfg--col modifier, the grid needs the .bfg block height (or its parent height) to be defined (and that's not always the case!).

Auto height: .bfg--[B]auto-height

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

By default, the main .bfg block will try to fit to the height of its parent node, by using the height: 100% rule.

Use .bfg--auto-height modifier to apply height: auto rule instead.

<div class="bfg bfg--auto-height">...</div>

As the grid is responsive, you can change this behavior at each breakpoint.

Example:

<div class="bfg bfg--lg-auto-height">...</div>

Wrap onto multiple lines: .bfg--[B]wrap, .bfg--[B]nowrap

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

By default, .bfg__box elements are displayed onto one line and can not leave outside the .bfg block.

To allow .bfg__box elements to wrap as needed onto multiple lines, use the .bfg--wrap modifier.

<div class="bfg bfg--wrap">...</div>

As the grid is responsive, you can change this behavior at each breakpoint.

Example:

<div class="bfg
  bfg--wrap
  bfg--lg-nowrap
  bfg--sm-wrap">
  ...
</div>

Number of lines: .bfg--[B][N]-lines

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

[N] Number: 2, 3, 4 or 5.

As said above, if you use the markup .bfg.bfg--row.bfg--wrap then .bfg__box elements are placed in the row direction and wrapped onto multiple lines when needed.

But in this case the total height of all .bfg__box elements might be bigger than the .bfg block height itself!

If you know that there's exactly 2 lines of .bfg__box elements, you can constrain them to fit into the .bfg block, by using .bfg--2-lines modifier.

In the same way, use .bfg--3-lines, .bfg--4-lines or .bfg--5-lines modifiers to fit into exactly 3, 4 or 5 lines respectively.

<div class="bfg bfg--row bfg--wrap bfg--2-lines">...</div>
<div class="bfg bfg--row bfg--wrap bfg--3-lines">...</div>
<div class="bfg bfg--row bfg--wrap bfg--4-lines">...</div>
<div class="bfg bfg--row bfg--wrap bfg--5-lines">...</div>

Notice that all the rows will have the same height.

The same pattern applies to the markup .bfg.bfg--col.bfg--wrap.

<div class="bfg bfg--col bfg--wrap bfg--2-lines">...</div>
<div class="bfg bfg--col bfg--wrap bfg--3-lines">...</div>
<div class="bfg bfg--col bfg--wrap bfg--4-lines">...</div>
<div class="bfg bfg--col bfg--wrap bfg--5-lines">...</div>

Notice that all the columns will have the same width.

As the grid is responsive, you can change the number of lines at each breakpoint.

Example:

<div class="bfg bfg--wrap
  bfg--2-lines
  bfg--lg-3-lines
  bfg--sm-4-lines">
  ...
</div>

Gap: .bfg--gap, .bfg--gap-in, .bfg--[B]nogap

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

Add a gap between .bfg__box elements, using .bfg--gap modifier.

<div class="bfg bfg--gap">...</div>

In this case, the grid is self contained and you don't need to add margin (or padding) to the parent node of the .bfg block.

But if you prefer to define a main margin (or padding) at the parent node of the .bfg block then use .bfg--gap-in modifier.

<div style="margin: 1.5rem">
  <div class="bfg bfg--gap-in">...</div>
</div>
<div style="padding: 1.5rem">
  <div class="bfg bfg--gap-in">...</div>
</div>

The default value of the gap is 1.5rem (see below the Sass variable $bfg-half-gap).

The advantage of using .bfg--gap-in modifier is that you can reduce the main margin (or padding) up to $bfg-half-gap when needed.

Here's an example using the minimal main margin:

<div style="margin: 0.75rem">
  <div class="bfg bfg--gap-in">...</div>
</div>

The .bfg--gap modifier targets all .bfg__box elements, even those in the inner grids, if any. To remove the gap between .bfg__box elements of an inner grid, use the .bfg--nogap modifier at the inner grid level.

Here's an example with chained grid.

<!-- main grid -->
<div class="bfg bfg--gap">
  <div class="bfg__box"><!-- box with gap --></div>
  <div class="bfg__box"><!-- box with gap --></div>

  <!-- chained inner grid -->
  <div class="bfg__box bfg bfg--nogap">

    <div class="bfg__box"><!-- box without gap --></div>
    <div class="bfg__box"><!-- box without gap --></div>

  </div>
</div>

See below chained and nested grids to learn how inner grids works.

But the .bfg--nogap modifier can also be useful at the main grid level. Let's say your grid contains some .bfg-card blocks that have a nice border-radius. In this case, putting the cards next to each other without gap will look weird.

To reset the border-radius of the card's elements, add .bfg--nogap modifier at the main grid.

<div class="bfg bfg--nogap bfg-card bfg-card--primary">
  <div class="bfg__box">
    <div class="bfg-card__content"><!-- card without border-radius --></div>
  </div>
  <div class="bfg__box">
    <div class="bfg-card__content"><!-- card without border-radius --></div>
  </div>
</div>

As the grid is responsive, you can remove the gap at each breakpoint.

Example:

<div class="bfg bfg--gap bfg--sm-nogap">...</div>

Main axis alignment: .bfg--main-[P]

[P] Position: center, end, between, around.

Justify content along the "main" axis using .bfg--main-* modifiers.

By default, .bfg__box elements are packed toward the start line.

<div class="bfg bfg--main-center">...</div>

<div class="bfg bfg--main-end">...</div>

<div class="bfg bfg--main-between">...</div>

<div class="bfg bfg--main-around">...</div>

This is relevant only when the total size of the boxes along the line is less than 12 (see below the size modifiers for .bfg__box element). Then you can choose the distribution mode of the remaining space.

Cross axis alignment: .bfg--cross-[P]

[P] Position: start, center, end.

Align items along the "cross" axis using .bfg--cross-* modifiers.

By default, .bfg__box elements stretch to fill the .bfg block.

<div class="bfg bfg--cross-start">...</div>

<div class="bfg bfg--cross-center">...</div>

<div class="bfg bfg--cross-end">...</div>

Order: .bfg--[B]reverse

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

Reverse the boxes order using .bfg--reverse modifier.

<div class="bfg bfg--reverse">...</div>

As the grid is responsive, you can reverse the .bfg__box elements order at each breakpoint.

<div class="bfg bfg--reverse">...</div>

<div class="bfg bfg--xl-reverse">...</div>

<div class="bfg bfg--lg-reverse">...</div>

<div class="bfg bfg--sm-reverse">...</div>

<div class="bfg bfg--xs-reverse">...</div>

Overflow: .bfg--box-overflow-[T], .bfg--card-content-overflow-[T]

[T] Type: visible, hidden.

By default, .bfg__box and .bfg-card__content elements use the overflow: auto; rule.

Use .bfg--box-overflow-visible modifier on .bfg block to apply the overflow: visible; rule instead on all .bfg__box elements.

In the same way, use .bfg--box-overflow-hidden modifier to apply the overflow: hidden; rule instead.

<div class="bfg bfg--box-overflow-visible">...</div>
<div class="bfg bfg--box-overflow-hidden">...</div>

Use .bfg--card-content-overflow-visible modifier on .bfg block to apply the overflow: visible; rule instead on all .bfg-card__content elements.

In the same way, use .bfg--card-content-overflow-hidden modifier to apply the overflow: hidden; rule instead.

<div class="bfg bfg--card-content-overflow-visible">...</div>
<div class="bfg bfg--card-content-overflow-hidden">...</div>

See below .bfg__box--overflow-[T] and .bfg-card__content--overflow-[T] modifiers to apply this behavior to a specific element.

Disabled: .bfg--[B]disabled, .bfg--[B]disabled-all

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

To disable the grid system for the current .bfg block only, use .bfg--disabled modifier.

To disable the grid system for the current .bfg block and its chained or nested .bfg blocks, use .bfg--disabled-all modifier.

<div class="bfg bfg--disabled">...</div>

<div class="bfg bfg--disabled-all">...</div>

As the grid is responsive, you can disable the grid system at each breakpoint.

Here's an example of disabling the grid system for the current .bfg block only.

<div class="bfg bfg--disabled">...</div>

<div class="bfg bfg--xl-disabled">...</div>

<div class="bfg bfg--lg-disabled">...</div>

<div class="bfg bfg--sm-disabled">...</div>

<div class="bfg bfg--xs-disabled">...</div>

.bfg__box modifiers

Size: .bfg__box--[B][S]

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

[S] Size: 1, 2, ..., 11, 12.

Define the .bfg__box element size using .bfg__box--1, .bfg__box--2, ..., .bfg__box--11, .bfg__box--12 modifiers.

The total size available for each line is 12.

...
  <div class="bfg__box bfg__box--1">...</div>
  <div class="bfg__box bfg__box--2">...</div>
  ...
  <div class="bfg__box bfg__box--11">...</div>
  <div class="bfg__box bfg__box--12">...</div>
...

If the total size of the boxes along the line is less than 12, the remaining space is distributed based on the .bfg--main-[P] modifiers.

As the grid is responsive, you can change the .bfg__box element size at each breakpoint.

Example:

...
  <div class="bfg__box
    bfg__box--5
    bfg__box--xl-6
    bfg__box--lg-4
    bfg__box--sm-8
    bfg__box--xs-12">
    ...
  </div>
...

Fit: .bfg__box--fit

Use .bfg__box--fit modifier to indicate that a .bfg__box element should not grow or shrink.

Here's an example when using .bfg--row modifier:

<div class="bfg bfg--row">
  <div class="bfg__box bfg__box--fit" style="width:150px">
    <!-- width is fixed at 150px -->
  </div>
  <div class="bfg__box bfg__box--4">
    <!-- width is 4/12 of the remaining space (`.bfg` width, minus 150px) -->
  </div>
  <div class="bfg__box bfg__box--8">
    <!-- width is 8/12 of the remaining space (`.bfg` width, minus 150px) -->
  </div>
</div>

Defining the box width is optional. If not defined the box width will simply fit to its content.

Here's an example when using .bfg--col modifier:

<div class="bfg bfg--col">
  <div class="bfg__box bfg__box--fit" style="height:150px">...</div>
  <div class="bfg__box bfg__box--4">...</div>
  <div class="bfg__box bfg__box--8">...</div>
</div>

Defining the box height is optional. If not defined the box height will simply fit to its content.

Order: .bfg__box--[B]first, .bfg__box--[B]last, .bfg__box--[B]in-place

[B] Breakpoint: xl-, lg-, sm-, xs- or none.

Change the box order using .bfg__box--first or .bfg__box--last modifiers.

Restore the box order using .bfg__box--in-place modifier.

...
  <div class="bfg__box bfg__box--last"><!-- will move to last position --></div>
  <div class="bfg__box bfg__box--in-place"><!-- will stay in place --></div>
  <div class="bfg__box bfg__box--first"><!-- will move to first position --></div>
...

As the grid is responsive, you can change the .bfg__box element order at each breakpoint.

Example:

...
  <div class="bfg__box
    bfg__box--first
    bfg__box--lg-last
    bfg__box--sm-in-place">
    ...
  </div>
...

Overflow: .bfg__box--overflow-[T]

[T] Type: visible, hidden.

By default, .bfg__box element use the overflow: auto; rule.

Use .bfg__box--overflow-visible modifier to apply the overflow: visible; rule instead.

Or use .bfg__box--overflow-hidden modifier to apply the overflow: hidden; rule instead.

...
  <div class="bfg__box bfg__box--overflow-visible">...</div>
  <div class="bfg__box bfg__box--overflow-hidden">...</div>
...

Padding: .bfg__box--nopad

When using .bfg--gap modifier, add .bfg__box--nopad modifier to remove the padding of a specific box.

<div class="bfg bfg--row bfg--gap">
  <div class="bfg__box bfg__box--4">...</div>
  <div class="bfg__box bfg__box--4 bfg__box--nopad">
    <!-- no padding -->
  </div>
  <div class="bfg__box bfg__box--4">...</div>
</div>

.bfg-card modifier

Type: .bfg-card--[T]

[T] Type: primary, secondary, success, danger, info, warning or any string.

For example, add "primary" look and feel to the card's content, header and actions using .bfg-card--primary modifier.

...
  <div class="bfg-card bfg-card--primary">
    <div class="bfg-card__action">...</div>
    <div class="bfg-card__header">...</div>
    <div class="bfg-card__content">...</div>
  </div>
...

See below the Sass mixin bfg-card to create your own card types.

.bfg-card__content modifiers

Overflow: .bfg-card__content--overflow-[T]

[T] Type: visible, hidden.

By default, .bfg-card__content element use the overflow: auto; rule.

Use .bfg-card__content--overflow-visible modifier to apply the overflow: visible; rule instead.

Or use .bfg-card__content--overflow-hidden modifier to apply the overflow: hidden; rule instead.

...
  <div class="bfg-card__content bfg-card__content--overflow-visible">...</div>
  <div class="bfg-card__content bfg-card__content--overflow-hidden">...</div>
...

Padding: .bfg-card__content--nopad

Remove the card content padding using .bfg-card__content--nopad modifier.

...
  <div class="bfg-card__content bfg-card__content--nopad">...</div>
...

Chained and nested grids

Chained grid

To chain grids, use markup .bfg__box.bfg to treat a .bfg__box element as a .bfg block too.

Example:

See below the <div> that has both roles:

<div class="bfg bfg--col bfg--gap">
  <div class="bfg__box bfg__box--3">...</div>

  <!-- chained grid starts here, on the `.bfg__box` element -->
  <div class="bfg__box bfg__box--6 bfg bfg--row">

    <div class="bfg__box bfg__box--3">...</div>
    <div class="bfg__box bfg__box--6">...</div>
    <div class="bfg__box bfg__box--3">...</div>

  </div>

  <div class="bfg__box bfg__box--3">...</div>
</div>

Nested grid

An alternative to chained grids consists to simply nest a new .bfg block inside a .bfg__box element.

With this markup, if you use .bfg--gap modifier, you'll need to add .bfg__box--nopad modifier on the parent node of the nested grid.

<div class="bfg bfg--col bfg--gap">
  <div class="bfg__box bfg__box--3">...</div>

  <!-- `.bfg__box--nopad` modifier added to the parent node of
    the nested grid, because of the `.bfg--gap` modifier above -->
  <div class="bfg__box bfg__box--6 bfg__box--nopad">

    <!-- nested grid starts here, inside the `.bfg__box` element -->
    <div class="bfg bfg--row">
      <div class="bfg__box bfg__box--3">...</div>
      <div class="bfg__box bfg__box--6">...</div>
      <div class="bfg__box bfg__box--3">...</div>
    </div>

  </div>

  <div class="bfg__box bfg__box--3">...</div>
</div>

Sass customization

Variables

You can change the grid and cards look and feel using Sass, by overriding the default variables value.

// ------ src/lib/variables/_core.scss ------

$bfg-breakpoints: (
  xs: 576px,
  sm: 768px,
  lg: 992px,
  xl: 1200px
) !default;

$bfg-half-gap: 0.75rem !default;

// ------ src/lib/variables/_card.scss ------

$bfg-card-margin: 1.5rem !default;

$bfg-card-padding: 1rem !default;

$bfg-card-header-height: 2.5rem !default;

$bfg-card-default: (
  box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05),
  border-radius: 3px,
  border-width: 1px,

  header-border-bottom-width: 1px,
  header-border-color: #d5d5d5,
  header-background-color: #f6f6f6,
  header-color: inherit,

  content-border-color: #ddd,
  content-background-color: #fff,
  content-color: inherit
) !default;

$bfg-card-secondary: (
  header-border-color: darken(#6c757d, 5),
  header-background-color: #6c757d,
  header-color: #fff,
) !default;

$bfg-card-success: (
  header-border-color: darken(#28a745, 5),
  header-background-color: #28a745,
  header-color: #fff,
) !default;

$bfg-card-danger: (
  header-border-color: darken(#dc3545, 5),
  header-background-color: #dc3545,
  header-color: #fff,
) !default;

$bfg-card-info: (
  header-border-color: darken(#17a2b8, 5),
  header-background-color: #17a2b8,
  header-color: #fff,
) !default;

$bfg-card-warning: (
  header-border-color: darken(#ffc107, 5),
  header-background-color: #ffc107,
) !default;

$bfg-card-theme-included: true !default;

It's important to note that Bem-flex-grid generates CSS variables based on the Sass variables.

For example, the Sass variable $bfg-half-gap becomes the CSS variable --bfg-half-gap. Thus, the compiled version (dist/bem-flex-grid-class.css for example) contains the following rule:

:root {
  --bfg-half-gap: 0.75rem;
}

The same idea applies to the Sass variables of the card.

For example, $bfg-card-default contains a box-shadow property. Thus, the compiled version contains the following rule:

:root {
  --bfg-card-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05);
}

For cards other than the default card, only the overwritten properties produce CSS variables.

For example, $bfg-card-secondary overwrites the header-background-color property. Thus, the compiled version contains the following rule:

:root {
  --bfg-card-secondary-header-background-color: #6c757d;
}

Note that the CSS variables for the "primary" card (which are based on the default card) do NOT contain the word primary! Thus, there's no CSS variable --bfg-card-primary-box-shadow but only --bfg-card-box-shadow. On the other hand, the CSS variables for the "secondary" card do contain the word secondary.

Example:

Let's customize the boxes gap to be bigger than the default.

@use "~/bem-flex-grid/src/lib/bem-flex-grid-class.scss" with ($bfg-alf-gap: 1.25rem);

Mixins

Cards

The bfg-card mixin allows you to customize the look and feel of the card's content, header and actions.

@include bfg-card($type, $settings: ());

By default, Bem-flex-grid generates cards with the following values for the $type parameter: primary, secondary, success, danger, info and warning. But you are free to completely change this naming.

Example:

Let's remove the default list of types and define a single type named "fancy".

@use "~/bem-flex-grid/src/lib/bem-flex-grid-class.scss" as * with ($bfg-card-theme-included: false);

@include bfg-card(fancy, (
  box-shadow: none,
  border-radius: 0px
));

The $settings parameter is optional. In this example, the "fancy" card looks like the default card (picked from the $bfg-card-default), but with a different box-shadow and border-radius.

Now, let's use the "fancy" card using the .bfg-card--fancy modifier (instead of .bfg-card--primary which is no longer available).

...
  <div class="bfg-card bfg-card--fancy">
    <div class="bfg-card__action">...</div>
    <div class="bfg-card__header">...</div>
    <div class="bfg-card__content">...</div>
  </div>
...

An advanced use case of the card mixin is to create 2 different sets of cards for "light" and "dark" themes.

Example:

@use "../lib/bem-flex-grid-class" as * with (
  $bfg-card-theme-included: false,

  // Let's define the default card using flat design (no box-shadow nor border-radius)
  $bfg-card-default: (
    box-shadow: none,
    border-radius: 0px,
    border-width: 1px,

    header-border-bottom-width: 1px,
    header-border-color: #d5d5d5,
    header-background-color: #f6f6f6,
    header-color: inherit,

    content-border-color: #ddd,
    content-background-color: #fff,
    content-color: inherit
  )
);

// Let's define the "primary" card based on the `$bfg-card-default`
@include bfg-card(primary);

// Let's define the "warning" card by overwriting some properties 
@include bfg-card(warning, (
  header-border-color: darken(#ffc107, 5),
  header-background-color: #ffc107,
  header-color: #fff,
));

body.theme--dark {
  // Let's redefine the CSS variables of the "primary" card for the "dark" theme
  --bfg-card-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2);
  --bfg-card-header-border-color: #4a4a4a;
  --bfg-card-header-background-color: #3a3a3a;
  --bfg-card-header-color: #fff;
  --bfg-card-content-border-color: #4a4a4a;
  --bfg-card-content-background-color: #2a2a2a;

  // Because the "warning" card have a "header-color" property in its definition,
  // we have access to the associated CSS variable
  --bfg-card-warning-header-color: #000;
}

// Let's imagine this is the global look and feel of our "light" and "dark" themes
body {
  background: #fff;
  color: #424242;

  &.theme--dark {
    background: #252525;
    color: #dedede;
  }
}

Media breakpoints

The bfg-media-breakpoint-* mixins lets you add CSS rules that target specific screen sizes.

@include bfg-media-breakpoint-up($size) { ... }

@include bfg-media-breakpoint-down($size) { ... }

Pick the $size value in the following list: xl, lg, sm, xs.

Example:

Let's add CSS rules that target only the screen whose size is greater than 992 pixels:

@include bfg-media-breakpoint-up(lg) {
  body { margin: 3rem; }
}

This is equivalent to:

@media (min-width: 992px) {
  body { margin: 3rem; }
}

Selectors summary

Let's recap the available selectors for both class and attr syntaxes.

For Class syntax

.bfg block

Direction:

Auto height:

Wrap onto multiple lines:

Number of lines:

Gap:

Main axis alignment:

Cross axis alignment:

Order:

Box overflow:

Card overflow:

Disabled:

.bfg__box element

Size:

Fit:

Order:

Overflow:

Padding:

.bfg-card block

Type:

.bfg-card__content element

Overflow:

Padding:

For attr syntax

.bfg block attribute

Direction:

Auto height:

Wrap onto multiple lines:

Number of lines:

Gap:

Main axis alignment:

Cross axis alignment:

Order:

Box overflow:

Card overflow:

Disabled:

.bfg__box element attribute

Size:

Fit:

Order:

Overflow:

Padding:

.bfg-card block attribute

Type:

.bfg-card__content element attribute

Overflow:

Padding:

Contribute

git clone https://github.com/avine/bem-flex-grid.git

cd bem-flex-grid

npm i

# Open showcase in your favorite browser
npm start

# Compile SASS (`src/lib/`) to CSS (`dist/`)
npm run build

# Build HTML documentation (`src/index.html`) from `README.md`
npm run readme

License

MIT