bem-flex-grid v3.0.0
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.
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:
- any BEM Block or Element is directly used as an HTML tag attribute.
- any BEM Modifier is used to construct the attribute's value.
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-gridUsage 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.scssThe
distfolder 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-cardblock can also be used as a standalone component, outside of the.bfgblock.
.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--rowmodifier, the grid needs the.bfgblock width (or its parent width) to be defined (and that's usually the case).
<div class="bfg bfg--col">...</div>When using
.bfg--colmodifier, the grid needs the.bfgblock 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:
- Fit to the parent height on all screen sizes (even greater than 1200px).
- Use auto-height on large screen (until 992px).
<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:
- Wrap onto multiple lines on all screen sizes (even greater than 1200px).
- Do not wrap on large screen (until 992px).
- Wrap again on small screen (until 768px).
<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:
- Fit boxes on 2 lines on all screen sizes (even greater than 1200px).
- Fit boxes on 3 lines on large screen (until 992px).
- Fit boxes on 4 lines on small screen (until 768px).
<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:
- Add the gap on all screen sizes (even greater than 1200px).
- Remove the gap on small screen (until 768px).
<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__boxelement). 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:
- Use
.bfg__box--5to set the box size to be 5/12 of the available size for all screen size (even greater than 1200px). - Add
.bfg__box--xl-6to increase the size on extra large screen (until 1200px). - Add
.bfg__box--lg-4to reduce the size on large screen (until 992px). - Add
.bfg__box--sm-8to increase the size on small screen (until 768px). - Add
.bfg__box--xs-12to increase the size on extra small screen (until 576px).
...
<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
widthis 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
heightis 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:
- Use
.bfg__box--firstto place the box in first position on all screen sizes (even greater than 1200px). - Add
.bfg__box--lg-lastto place the box in last position on large screen (until 992px). - Add
.bfg__box--sm-in-placeto restore the original box position on small screen (until 768px).
...
<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-cardto 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:
.bfg__box.bfg__box--6as it is an element of its parent.bfg.bfg--colblock..bfg.bfg--rowas it is a block of its children.bfg__boxelements.
<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--gapmodifier, you'll need to add.bfg__box--nopadmodifier 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-shadowbut only--bfg-card-box-shadow. On the other hand, the CSS variables for the "secondary" card do contain the wordsecondary.
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
$sizevalue 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:
.bfg--row.bfg--col
Auto height:
.bfg--auto-height,.bfg--xl-auto-height,.bfg--lg-auto-height,.bfg--sm-auto-height,.bfg--xs-auto-height
Wrap onto multiple lines:
.bfg--wrap,.bfg--xl-wrap,.bfg--lg-wrap,.bfg--sm-wrap,.bfg--xs-wrap.bfg--nowrap,.bfg--xl-nowrap,.bfg--lg-nowrap,.bfg--sm-nowrap,.bfg--xs-nowrap
Number of lines:
.bfg--2-lines,.bfg--xl-2-lines,.bfg--lg-2-lines,.bfg--sm-2-lines,.bfg--xs-2-lines.bfg--3-lines,.bfg--xl-3-lines,.bfg--lg-3-lines,.bfg--sm-3-lines,.bfg--xs-3-lines.bfg--4-lines,.bfg--xl-4-lines,.bfg--lg-4-lines,.bfg--sm-4-lines,.bfg--xs-4-lines.bfg--5-lines,.bfg--xl-5-lines,.bfg--lg-5-lines,.bfg--sm-5-lines,.bfg--xs-5-lines
Gap:
.bfg--gap.bfg--gap-in.bfg--nogap,.bfg--xl-nogap,.bfg--lg-nogap,.bfg--sm-nogap,.bfg--xs-nogap
Main axis alignment:
.bfg--main-center.bfg--main-end.bfg--main-between.bfg--main-around
Cross axis alignment:
.bfg--cross-start.bfg--cross-center.bfg--cross-end
Order:
.bfg--reverse,.bfg--xl-reverse,.bfg--lg-reverse,.bfg--sm-reverse,.bfg--xs-reverse
Box overflow:
.bfg--box-overflow-visible.bfg--box-overflow-hidden
Card overflow:
.bfg--card-content-overflow-visible.bfg--card-content-overflow-hidden
Disabled:
.bfg--disabled,.bfg--xl-disabled,.bfg--lg-disabled,.bfg--sm-disabled,.bfg--xs-disabled.bfg--disabled-all,.bfg--xl-disabled-all,.bfg--lg-disabled-all,.bfg--sm-disabled-all,.bfg--xs-disabled-all
.bfg__box element
Size:
.bfg__box--1,.bfg__box--xl-1,.bfg__box--lg-1,.bfg__box--sm-1,.bfg__box--xs-1.bfg__box--2,.bfg__box--xl-2,.bfg__box--lg-2,.bfg__box--sm-2,.bfg__box--xs-2.bfg__box--3,.bfg__box--xl-3,.bfg__box--lg-3,.bfg__box--sm-3,.bfg__box--xs-3- ...
.bfg__box--11,.bfg__box--xl-11,.bfg__box--lg-11,.bfg__box--sm-11,.bfg__box--xs-11.bfg__box--12,.bfg__box--xl-12,.bfg__box--lg-12,.bfg__box--sm-12,.bfg__box--xs-12
Fit:
.bfg__box--fit
Order:
.bfg__box--first,.bfg__box--xl-first,.bfg__box--lg-first,.bfg__box--sm-first,.bfg__box--xs-first.bfg__box--last,.bfg__box--xl-last,.bfg__box--lg-last,.bfg__box--sm-last,.bfg__box--xs-last.bfg__box--in-place,.bfg__box--xl-in-place,.bfg__box--lg-in-place,.bfg__box--sm-in-place,.bfg__box--xs-in-place
Overflow:
.bfg__box--overflow-visible.bfg__box--overflow-hidden
Padding:
.bfg__box--nopad
.bfg-card block
Type:
.bfg-card--primary,.bfg-card--secondary,.bfg-card--success,.bfg-card--danger,.bfg-card--info,.bfg-card--warning- ...
.bfg-card__content element
Overflow:
.bfg-card__content--overflow-visible.bfg-card__content--overflow-hidden
Padding:
.bfg-card__content--nopad
For attr syntax
.bfg block attribute
Direction:
bfg="row | col"
Auto height:
bfg="auto-height | xl-auto-height | lg-auto-height | sm-auto-height | xs-auto-height"
Wrap onto multiple lines:
bfg="wrap | xl-wrap | lg-wrap | sm-wrap | xs-wrap"bfg="nowrap | xl-nowrap | lg-nowrap | sm-nowrap | xs-nowrap"
Number of lines:
bfg="2-lines | xl-2-lines | lg-2-lines | sm-2-lines | xs-2-lines"bfg="3-lines | xl-3-lines | lg-3-lines | sm-3-lines | xs-3-lines"bfg="4-lines | xl-4-lines | lg-4-lines | sm-4-lines | xs-4-lines"bfg="5-lines | xl-5-lines | lg-5-lines | sm-5-lines | xs-5-lines"
Gap:
bfg="gap | gap-in | nogap | xl-nogap | lg-nogap | sm-nogap | xs-nogap"
Main axis alignment:
bfg="main-center | main-between | main-around"
Cross axis alignment:
bfg="cross-start | cross-center | cross-end"
Order:
bfg="reverse | xl-reverse | lg-reverse | sm-reverse | xs-reverse"
Box overflow:
bfg="box-overflow-visible | box-overflow-hidden"
Card overflow:
bfg="card-content-overflow-visible | card-content-overflow-hidden"
Disabled:
bfg="disabled | xl-disabled | lg-disabled | sm-disabled | xs-disabled"bfg="disabled-all | xl-disabled-all | lg-disabled-all | sm-disabled-all | xs-disabled-all"
.bfg__box element attribute
Size:
bfg__box="1 | xl-1 | lg-1 | sm-1 | xs-1"bfg__box="2 | xl-2 | lg-2 | sm-2 | xs-2"bfg__box="3 | xl-3 | lg-3 | sm-3 | xs-3"- ...
bfg__box="11 | xl-11 | lg-11 | sm-11 | xs-11"bfg__box="12 | xl-12 | lg-12 | sm-12 | xs-12"
Fit:
bfg__box="fit"
Order:
bfg__box="first | xl-first | lg-first | sm-first | xs-first"bfg__box="last | xl-last | lg-last | sm-last | xs-last"bfg__box="in-place | xl-in-place | lg-in-place | sm-in-place | xs-in-place"
Overflow:
bfg__box="overflow-visible | overflow-hidden"
Padding:
bfg__box="nopad"
.bfg-card block attribute
Type:
bfg-card="primary | secondary | success | danger | info | warning"- ...
.bfg-card__content element attribute
Overflow:
bfg-card__content="overflow-visible | overflow-hidden"
Padding:
bfg-card__content="nopad"
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