How to add Flexbox fallback to CSS Grid
I shared how to build a calendar with CSS Grid in the previous article. Today, I want to share how to build a Flexbox fallback for the same calendar.
How to provide support
Generally, there are three ways to provide support when it comes to CSS.
First method: Write fallback code. Overwrite fallback code.
.selector {
property: fallback-value;
property: actual-value;
}
Second method: Write fallback code. Overwrite fallback code in CSS Feature Queries (@supports
). Reset properties inside @supports
if you need.
.selector {
property: fallback-value;
}
@supports (display: grid) {
.selector {
property: actual-value;
}
}
Third method: Write everything in @supports
.
@supports not (display: grid) {
.selector {
property: fallback-value;
}
}
@supports (display: grid) {
.selector {
property: actual-value;
}
}
These three methods are listed in order of decreasing-complexity. (If you need to overwrite code, it’s more complicated). This means writing everything in @supports
is the simplest of the three.
How you choose to support your project depends on browser support for:
- The feature
- The fallback feature
- Support for Feature Queries
Checking for support
The best place to check for support is caniuse. Here, I see that support for CSS Grid is decent. Browsers I have to worry about are:
- Opera Mini: 1.42% global usage
- Android Browsers 2.1 to 4.4.4: 0.67% global usage
- Blackberry browser: 0.02% global usage (Not gonna worry about this one).
![](/_astro/css-grid-support.1a940196_Z2aMxJn.png)
Support for the fallback (Flexbox) is also good.
But we have a problem: Flexbox fallback wouldn’t work for Android 2.1 to 4.3 (it doesn’t support wrapping). Global usage for Android 2.1 to 4.3 is 0.37%.
Here, I have to decide:
- Is providing Flexbox fallback for Opera Mini (1.42%), Android 4.4.4 (0.3%), and Blackberry (0.02%) worth the effort?
- Should I change fallback from Flexbox to an older feature to support Android 2.1 to 4.3 (another 0.37%)?
![](/_astro/flexbox-support.306c764b_dVaJ.png)
Let’s assume, for this project, I decide that Flexbox fallback is sufficient. I’m not going to worry about Android 2.1 to 4.3.
Next, I want to check whether browsers support CSS Feature Queries.
Here, I see:
- Opera Mini supports Feature Queries
- Android 4.4.4 supports Feature Queries
- Blackberry browser doesn’t support Feature Queries
- IE 11 does’t support Feature Queries
![](/_astro/feature-queries-support.c439028b_9kbAa.png)
Deciding how to write fallback code
Earlier, I mentioned there are three ways to write fallback code for CSS:
- Write fallback code. Overwrite fallback code.
- Write fallback code. Overwrite fallback code in
@supports
. - Write everything in
@supports
.
If I write everything inside @supports
, I can provide support for:
- Opera Mini (1.43%)
- Android 4.4.4 (0.3%)
But I lose support for:
- IE 11 (2.3%)
- Blackberry (0.02%)
I do not want to forsake the 2.3% of IE users, which means Method 3 (write everything in @supports
) is out.
If I use Method 2 (Write fallback code. Overwrite fallback code in @supports
), I can provide support for:
- IE 11 (2.3%)
- Opera Mini (1.43%)
- Android 4.4.4 (0.3%)
- Blackberry browser (0.02%)
That’s everything I need. That’s why I’m gonna go with Method 2.
Note: If you want to code along, you can use demo from my previous article as the starting point.
Disabling Grid code
First, we park the CSS Grid code under @supports
(like we discussed above).
@supports (display: grid) {
.day-of-week,
.date-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
.date-grid button:first-child {
grid-column: 6;
}
}
We can disable the CSS Grid code by setting display
to an invalid value (not grid
). This disables the entire block of code.
(Thank Rachel Andrew for this neat trick. I believe I learned it from her 😄).
@supports (display: gridx) {
/*...*/
}
![Initial layout.](/_astro/inital-layout.ff4eb027_Z1EiLVr.png)
Writing Flexbox code
We need to build the same seven-column grid with Flexbox. The first thing we need to do is acknowledge that Flexbox and Grid work differently. We won’t be able to get a perfect replica, but we can get close.
The first thing is set display
to flex
.
.day-of-week,
.date-grid {
display: flex;
}
![Results after setting display to flex.](/_astro/flexbox-1.8095d2d5_icXky.png)
We need the buttons in .date-grid
to wrap, so we set flex-wrap
to wrap
.
.date-grid {
flex-wrap: wrap;
}
![Buttons in date grid wrapped at the edges.](/_astro/flexbox-2.bb23e336_Z2hexvL.png)
We need to replicate the seven-column grid. An easy way to do this is calculate the width of the grid according to the width of each button. Here, I have already set each button to 4.5ch. This means the width of the grid should be 7 x 4.5ch
.
(We can use CSS Calc to do the math for us).
.day-of-week,
.date-grid {
max-width: calc(4.5ch * 7);
}
![Wrapping at 7 columns](/_astro/flexbox-3.75e30244_NrXYj.png)
We need the elements in .day-of-week
to spread out across the available width. One simple way is to set justify-content
to space-between
.
.day-of-week {
justify-content: space-between;
}
![After setting space-between.](/_astro/flexbox-4.521c631e_1Ofah7.png)
Here, we can see that elements in .day-of-week
extend past the grid. This extension happens because we let Flexbox calculate flex-basis
for us. If we want every element in .day-of-week
to be have the same width, we need to set flex-basis
ourselves.
In this case, the easiest way is to set flex-basis
to the width of one grid item (or 4.5ch
). Note: I adjusted font-size
of each item in .day-of-week
to 0.7em
(for visual aesthetics). We have to account for this change.
.day-of-week > * {
flex-basis: calc(4.5ch / 0.7);
}
![Adjusted .day-of-week for size.](/_astro/flexbox-5.134eb5bc_Z1Ectva.png)
Finally, we need to push the 1 February to Friday. (Five columns). Since column is 4.5ch
, we simply push it by 4.5ch x 5
.
(Again, we can use CSS Calc to help us with this).
.date-grid button:first-child {
margin-left: calc(4.5ch * 5);
}
![Pushed 1 Febuary to Friday](/_astro/flexbox-6.89345a3f_ZTGdr0.png)
Fixing the CSS Grid version
We can reactivate the CSS Grid code and make any necessary changes now.
@supports (display: grid) {
/* ... */
}
![Activating CSS Grid code](/_astro/grid-fix-1.49ae3cc3_1xtB7y.png)
Here, we see some values fly far out to the right. This happens because we added margin-left
to the first grid item. We need to reset the added margin.
@supports (display: grid) {
/* ... */
.date-grid button:first-child {
grid-column: 6;
margin-left: 0;
}
}
![Removed margin-left.](/_astro/grid-fix-2.19a9c9a8_ZpIUog.png)
Another thing: We can remove max-width
because we don’t need it in the CSS Code. (Even though this doesn’t affect the CSS Code, we still want to remove it. Always better to have less properties).
@supports (display: grid) {
.day-of-week,
.date-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
max-width: initial;
}
/* ... */
}
Here’s the visual difference between the Flexbox and CSS Grid versions. Not too bad!
![Visual difference between the Flexbox and CSS Grid code](/_astro/difference.b483fa91.gif)
One fun thing
CSS Grid is cool because it follows writing direction. We can easily change the flow from left-to-right to right-to-left.
Note: I don’t know if calendars are read from right to left in rtl languages. I just thought it’ll fun to mention this 😜).
![Switching between ltr and rtl.](/_astro/rtl.7cebd08a.gif)
Our code for CSS Grid supports this behaviour naturally. If you want to support the same behaviour with Flexbox, you need to use CSS Logical Properties.
![Support for CSS Logical Properties.](/_astro/css-logical-properties-support.137fac04_Z8Az3v.png)
Since support for CSS Logical Properties is not-so-great, we need to provide fallback for it. (Best way is to through Method 1: Write fallback; overwrite fallback).
.date-grid button:first-child {
margin-left: calc(4.5ch * 5);
margin-inline-start: calc(4.5ch * 5);
}
@supports (display: grid) {
/* ... */
.date-grid button:first-child {
grid-column: 6;
margin-left: 0;
margin-inline-start: 0;
}
}
That’s it! Here’s a Codepen for the final code:
See the Pen Building a Calendar with CSS Grid (and fallback with Flexbox)by Zell Liew (@zellwk) onCodePen.