Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexbox + calc() - possible bug in flexbox?

Tags:

css

flexbox

The Goal

I'm working on a flexbox + calc() based grid system with gutters in SASS.

You define your grid via mixins like so:

.box {    
    @include column('1/3', $gutter: 20px);
}

Compiled this will be:

.box {
    width: calc(99.999999% * 1/3 - 13.33333px);
}

The Problem (please read the updates further down)

I'm trying to find a way get rid of the classic .row containers.

In my mind this should be super simple with flexbox + calc() but I have this strange bug (or an error in my caculations?) which sometimes break the layout when multiple rows should be created.

As an example:
I want a grid with a 20px gutter between the columns.

The rest is best explained in code, so here's a pen:

http://codepen.io/NilsDannemann/pen/OMBVry?editors=1100

Why is the last example (1/8 - multi row) breaking?

enter image description here


Update #1

Okay, heres whats happening: the Problem is not rooted in the flexbox space-between property, but comes from flexbox' behavior in general.

Flexbox always sees the gutters as available space. So in the last example it combines them (7 * 20px = 140px) and concludes that there is enough space to fit another item (width after calc() = 107.5px) on the first row.

This is were the whole thing falls.
space-betweenthen does it's job as intended.


Update #2

I think the only way around that is (as @Siguza pointed out) to add margins to fill the gutters. Then use an :nth-child selector to set the last margin of a row to 0.

In SASS this would look something like this:

.box {
    @include column('1/8', $gutter: 20px);
    margin-right: 20px;

    &:nth-child(8n) {
        margin-right: 0;
    }
}

Now it becomes a SASS challenge:
How do I get the :nth-child (whole number) from the passed fraction?

With some effort I have solved this. :-)
Heres the pen with the current SASS version of the grid: http://codepen.io/NilsDannemann/pen/OMaOvX?editors=1100

Wow! This works great! A multi-column grid with a completely clean DOM!
No .row classes or .eigth classes. Feel free to play around with the mixin (change the fraction or the gutter).

Heres the sad part though:
Try uneven grids like this:

.box1 {
    @include column('2/8', $gutter: 20px);;
}
.box2 {
    @include column('4/8', $gutter: 20px);;
}
.box3 {
    @include column('2/8', $gutter: 20px);;
}

Now the :nth-child is wrong and the whole thing breaks. :-(

If we can solve this (without introducing another variable to the mixin) we would have one of the cleanest any intuitive grids I have seen to date. But this last problem is a tough one.

I'm not sure if it can be done at all.
Any SASS-Genius out there to help?

like image 953
Arrowcatch Avatar asked Feb 05 '16 11:02

Arrowcatch


People also ask

Can I use flexbox inside flexbox?

Flexbox is inherently a one dimensional layout model. Flex items within a flex container can be laid out either horizontally or vertically, but not both. If you want to lay out items in both dimensions, you'll need to nest a flex container inside another one.

What are the disadvantages of using flexbox?

One of the major drawbacks of using flexbox is performance issues. The use of flexbox can increase the page loading time if you have a larger project. You can compare the page loading time through Chrome development tools using the flexbox and the same pages constructed without using flexbox.

How do I put 3 items in flexbox?

For 3 items per row, add on the flex items: flex-basis: 33.333333% You can also use the flex 's shorthand like the following: flex: 0 0 33.333333% => which also means flex-basis: 33.333333% .


1 Answers

The problem boils down to the definition of justify-content: space-between.

8.2. Axis Alignment: the justify-content property

The justify-content property aligns flex items along the main axis of the current line of the flex container.

space-between

Flex items are evenly distributed in the line.

source: https://www.w3.org/TR/css-flexbox-1/#justify-content-property

So, in your code, flex items will align per the rules of space-between, even when they wrap.

Extra space will be distributed differently depending on how many flex items exist on the line.

In your example illustrating the problem, you have nine flex items on the first row, and seven flex items on the second row. The second row has more extra space to distribute. Hence, the gutters are wider.

There are a total of 16 flex items in that container. Add two more, and everything aligns perfectly.

Revised Codepen

A few more considerations:

  • Flexbox is not built to serve as a grid system. The W3C is developing the CSS Grid Layout Module for this purpose.

  • Instead of width for defining the size of your flex items, consider using the flex property, which will enable you to control the width, as well as the flex-grow and flex-shrink factors.

  • Although it doesn't seem to be causing a problem in the codepen, using line comment syntax (\\ comments) is invalid in CSS and has the potential to break your code. It's safer to use the standard CSS commenting method (/* comments */). More details here: https://stackoverflow.com/a/34799134/3597276

like image 178
Michael Benjamin Avatar answered Oct 14 '22 02:10

Michael Benjamin