Flexbox + calc () - possible error in flexbox?

goal

I am working on a mesh- based flexbox + calc () system with gutters in SASS.

You define your grid through mixins as follows:

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

This will be compiled:

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

Problem (please read the updates below)

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

In my opinion, this should be super simple with flexbox + calc (), but I have this strange error (or an error in my caculation?) That sometimes breaks the layout when multiple lines 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 the handle:

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

Why does the last example (1/8 - a few lines) break?

enter image description here


Update # 1

Well, here's what happens: the problem is not related to the flexbox space-between property, but comes from flexbox "behavior in general.

flexbox always sees gutters as available space. Thus, in the last example, he combines them (7 * 20px = 140px) and concludes that there is enough space to place another element (width after calc () = 107.5px) in the first line.

That’s the whole thing falls.
space-between then does the job as intended.


Update # 2

I think the only way around this (as Siguza noted) is to add fields to fill the gutters. Then use the nth-child selector to set the last field of the string to 0.

In SASS, it looks something like this:

 .box { @include column('1/8', $gutter: 20px); margin-right: 20px; &:nth-child(8n) { margin-right: 0; } } 

Now this becomes a SASS problem:
How to get :nth-child (integer) from the passed fraction?

With some effort, I solved it. :-)
Here is a pen with the current version of SASS: http://codepen.io/NilsDannemann/pen/OMaOvX?editors=1100

Wow! It works great! Multicolumn mesh with a completely clean DOM!
No .row or .eigth . Feel free to play with the mixture (change the fraction or gutter).

Here is the sad part:
Try uneven grids:

 .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 mistaken, and all this breaks down .: - (

If we can solve this (without introducing another variable in mixin), we will have one of the cleanest of any intuitive grids I've seen to date. But this last problem is complex.

I am not sure that this can be done at all.
Any SASS-Genius help out there?

+6
source share
3 answers

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

8.2. Axis Alignment: justify-content property

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

space between

Flex items are evenly distributed in a row.

<sub> Source: https://www.w3.org/TR/css-flexbox-1/#justify-content-property

So, in your code, flex elements will be aligned according to the space-between rules, even when they are complete.

The extra space will be distributed differently depending on how many flex elements exist on the line.

In your example illustrating the problem, you have nine flex items in the first row and seven flex items in the second row. The second line has more space for distribution. Consequently, the gutters are wider.

This container contains a total of 16 elements of flexibility. Add two more and everything fits perfectly.

Revised Codepen

A few considerations:

  • Flexbox is not designed to serve as a grid. The W3C is developing a CSS grid layout module for this purpose.

  • Instead of defining a width to determine the size of your flex elements, consider using the flex property, which allows you to control the width, as well as the flex-grow and flex-shrink factors.

  • Although this does not cause a problem in the codec, using syntax syntax ( \\ comments ) is invalid in CSS and may violate your code. It’s safer to use the standard CSS comment method ( /* comments */ ). Read more here: fooobar.com/questions/1001242 / ...

+1
source

The main problem is that space-between doesn't like multi-line:

 #a { display: flex; width: 190px; border: solid 1px #999; flex-wrap: wrap; justify-content: space-between; } #a > div { height: 30px; width: 50px; background: #EFE; border: solid 1px #EEE; } 
 <div id="a"> <div></div> <div></div> <div></div> <div></div> </div> 

This will also happen with your 1/4 boxes, if the fifth box can fit on the first line, and it really will happen if you make the browser window extremely narrow.

But believe that this is seen as a function, not an error:
Flexbox is trying to place as many items as possible in a row.
(But I have no source to confirm this.)

What I have is a workaround.
This is a little ugly, but you can give .box a margin-right of 20px and then take it off every 4th .fourth , every eighth .eight , etc. Using :nth-child() :

 .box { background: #eee; text-align: center; padding: 20px; margin-right: 20px; } // Widths: 1/4 .box.fourth { width: calc(100% * 1/4 - (20px - 20px * 1/4)); } .box.fourth:nth-child(4n) { margin-right: 0; } // Widths: 1/8 .box.eigth { width: calc(100% * 1/8 - (20px - 20px * 1/8)); } .box.eigth:nth-child(8n) { margin-right: 0; } 

[ Updated pen ]

0
source

TL DR flexbox is super-high junk, and here is a grid that solves this insoluble problem.

Any SASS-Genius to help?

Hey. I would not consider myself a "genius of Sass" or anything else. I know this pretty well, but Hugo and several others have this title.

I have been called the "grid master" several times. This is pretty much the only thing I have in my life.

I did Jeet and Lost and literally spent hundreds of hours fighting what you are fighting right now. It haunts me. I wake up in the morning thinking about this problem and go to bed at night thinking about this problem. I have been doing this for many years.

Flexbox will not save you from this. In fact, the entire "flexbox will preserve mesh systems." Meme is really sad because it simply could not be more useful than not flexbox CSS.

Your original problem, as Michael_B pointed out , is that you are trying to use space-between. This will never work unless you have a certain number of elements on each line. You should not expect that someone will always have x number of elements in each row.

Then you switched to whole grids of “tons of markup” (a la Bootstrap) and margin-right , and it seems that you have selected margin-right grids. I tend to these because I care about what my markup looks like. Bootstrap grids get confused quickly, and I worked on countless teams in which some developer added something and screwed up the grid, forgetting the row or trying to insert something other than a column in a row. At first, no one notices this, but then you will see that the entire fragment of the site is offset by 15 pixels or so. Rewriting can be a pain. I even saw this several times by the self-proclaimed Bootstrap experts at ThemeForest.

 <!-- Bootstrap markup --> <div class="container"> <div class="row"> <div class="col-md-6">1</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1a</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1b</div> <div class="col-md-6">2b</div> </div> </div> </div> </div> </div> </div> <!-- Margin-right grid markup --> <div class="row"> <div class="col-6">1</div> <div class="col-6"> <div class="col-6">1a</div> <div class="col-6"> <div class="col-6">1b</div> <div class="col-6">2b</div> </div> </div> </div> 

https://youtu.be/ueZ6tvqhk8U?t=18

The disadvantage of margin-right grids is the need to get rid of the last element in the margin-right , which can be difficult, especially for preprocessors. This can be done by forcing the user to specify which element they want as their last, but this creates a number of problems when dealing with uneven meshes.

For example, if I create a mixin that removes margin-right from every third element, but I want to have size and shape for my elements inside my grid, then I'm completely screwed. The only way I found to mitigate this rather rare problem is to use disgusting Bootstrap markup.

This is the moment when you return to flexbox, wanting well and come empty-handed.

A week ago, I decided to see if Bootstrap / Foundation users are interested in a grid that was not built on a map markup map. They refused, but I put a decent job in what, in my opinion, is the best solution to this problem.

Here elements of any size without additional markup grid Bootstrap and Foundation shot down : http://codepen.io/corysimmons/pen/MKzPWW?editors=1100

In any case, if you like grids, stay tuned for my next big grid installed at the beginning of next month (I will spam it on reddit and Hacker News). He does not solve this particular problem, but it will be quite revolutionary.

If someone is as obsessed with solving this problem as I am, I would like to chat with you about it. I am sure that I did not think about everything, and there some smart bastard just sat on the answer.

0
source

All Articles