Tag: Flexbox

Equal Columns With Flexbox: It’s More Complicated Than You Might Think

You get a nice-looking design handed to you and it has this nice big hero section, followed by one of those three-up columns right beneath it. You know, like almost every other website you’ve ever worked on.

You bang through the hero section and get to work on the three-column section. It’s time to pull out our trusty friend flexbox! Except, you write display: flex and you get this mess instead of getting the three equal columns you’d expect.

This happens because of how flexbox calculates the base size of an element. You’ve probably read lots of flexbox tutorials, and many of them (including my own) are an overly simplistic example of what flexbox does without really digging into the complex things that flexbox does for us that we take for granted.

I’m positive you’ve seen examples and tutorials that look at something like this, where three divs shrink down around the content that’s inside them:

In other words, we get some block-level elements shrinking down and slotting next to one another. It feels like flex wants things to be as small as possible. But in reality, flexbox actually wants things to be as big as possible.

Wait, what? Flex shrinks things by default — that can’t be right! Right?

As awesome as flexbox is, what it’s doing under the hood is actually a little strange because, by default, it is doing two things at once. It first looks at the content size which is what we would get if by declaring width: max-content on an element. But on top of that, flex-shrink is also doing some work allowing the items to be smaller, but only if needed.

To really understand what’s going on, let’s break those two down and see how they work together.

Diving into max-content

max-content is a pretty handy property value in certain situations, but we want to understand how it works in this particular situation where we are trying to get three seemingly simple equal columns. So let’s strip away flexbox for a moment and look at what max-content does on its own.

MDN does a good job of explaining it:

The max-content sizing keyword represents the intrinsic maximum width of the content. For text content this means that the content will not wrap at all even if it causes overflows.

Intrinsic might throw you off here, but it basically means we’re letting the content decide on the width, rather than us explicitly setting a set width. Uri Shaked aptly describes the behavior by saying “the browser pretends it has infinite space, and lays all the text in a single line while measuring its width.”

So, bottom line, max-content allows the content itself to define the width of the element. If you have a paragraph, the width of that paragraph will be the text inside it without any line breaks. If it’s a long enough paragraph, then you end up with some horizontal scrolling.

Let’s revisit that overly-simplistic example of three block-level elements that shrink down and slot next to one another. That isn’t happening because of flex-shrink; it’s happening because that’s the size of those elements when their declared width is max-content. That’s literally as wide as they go because that’s as wide as the combined content inside each element.

Here, take a look at those elements without flexbox doing it’s flexbox stuff, but with a width: max-content on there instead:

So, when there’s just a small amount of text, the intrinsic max-content shrinks things down instead of flex-shrink. Of course, flexbox also comes in with it’s default flex-direction: row behavior which turns the flex items into columns, putting them right next to one another. Here’s another look but with the free space highlighted.

Adding flex-shrink to the equation

So we see that declaring display: flex pushes that max-content intrinsic size on flex items. Those items want to be as big as their content. But there is another default that comes in here as well, which is flex-shrink.

flex-shrink is basically looking at all the flex items in a flexible container to make sure they don’t overflow the parent. If the flex items can all fit next to each other without overflowing the flexible container, then flex-shrink won’t do anything at all… it’s job is already done.

But if the flex items do overflow the container (thanks to that max-content intrinsic width thing), the flex items are allowed to shrink to prevent that overflow because flex-shrink is looking out for that.

This is why flex-shrink has a default value of 1. Without it, things would get messy pretty quickly.

Here’s why the columns aren’t equal

Going back to our design scenario where we need three equal columns beneath a hero, we saw that the columns aren’t equal widths. That’s because flexbox starts by looking at the content size of each flex item before even thinking about shrinking them.

Using Firefox’s DevTools (because it’s got some unique flexbox visualizations that others don’t), we can actually see how flexbox is calculating everything.

For simplicity’s sake, as we dive deeper into this, let’s work with some nice round numbers. We can do this by declaring widths on our flex items. When we declare a width on a flex item, we throw that intrinsic size out the window, as we’ve now declared an explicit value instead. This makes figuring out what’s really going on a lot easier.

In the Pen below, we have a parent that’s a 600px wide flexible container (display: flex). I’ve removed anything that might influence the numbers, so no gap or padding. I’ve also switched out the border for an outline so we can still visualize everything easily.

The first and third flex items have a width: 300px and the middle one a width: 600px. If we add that all up, it’s a total of 1200px. That’s bigger than the the 600px available within the parent, so flex-shrink kicks in.

flex-shrink is a ratio. If everything has the same flex-shrink (which is 1 by default), they all shrink at the same rate. That doesn’t mean they all shrink to the same size or by the same amount, but they all shrink at the same rate.

If we jump back into Firefox DevTools, we can see the base size, the flex-shrink and the final size. In this case, the two 300px elements are now 150px, and the 600px one is now 300px.

The two elements that have a base width of 300px become 150px.

The larger element with a base width of 600px becomes 300px.

If we add up all the base sizes of all three flex items (the actual widths we declared on them), the total comes out to 1200px. Our flex container is 600px wide. If we divide everything by 2, it fits! They are all shrinking by the same rate, dividing their own widths by 2.

It’s not often that we have nice round numbers like that in the real world, but I think this does a nice job illustrating how flexbox does what it does when figuring out how big to make things.

Getting the columns to be equal

There are a few different ways to get the three columns we want to be equal in width, but some are better than others. For all the approaches, the basic idea is that we want to get all the columns base size to be the same. If they have an equal base size, then they will shrink (or grow, if we use flex-grow) at an equal rate when flexbox does it’s flex things, and in theory, that should make them the same size.

There are a few common ways to do this, but as I discovered while diving into all of this, I have come to believe those approaches are flawed. Let’s look at two of the most common solutions that I see used in the wild, and I’ll explain why they don’t work.

Method 1: Using flex: 1

One way we can try to get all the flex items to have the same base size is by declaring flex: 1 on all of them:

.flex-parent { display: flex; } .flex-parent > * { flex: 1; }

In a tutorial I made once, I used a different approach, and I must have had 100 people asking why I wasn’t using flex: 1 instead. I replied by saying I didn’t want to dive into the flex shorthand property. But then I used flex: 1 in a new demo, and to my surprise, it didn’t work.

The columns weren’t equal.

The middle column here is larger than the other two. It’s not by a ton, but the whole design pattern I’m creating is just so you have perfectly equal columns every single time, regardless of the content.

So why didn’t it work in this situation? The culprit here is the padding on the component in the middle column.

And maybe you’ll say it’s silly to add padding to one of the items and not the others, or that we can nest things (we’ll get to that). In my opinion, though, I should be able to have a layout that works regardless of the content that we’re putting in it. The web is all about components that we can plug and play these days, after all.

When I first set this up, I was sure it would work, and seeing this issue pop up made me want to learn what was really going on here.

The flex shorthand does more than just set the flex-grow: 1. If you don’t already know, flex is shorthand for flex-grow, flex-shrink, and flex-basis.

The default values for those constituent properties are:

.selector {   flex-grow: 0;   flex-shrink: 1;   flex-basis: auto; }

I’m not going to deep dive flex-basis in this article, as that’s something Robin has already done well. For now, we can think of it like width to keep things simple since we aren’t playing with flex-direction.

We’ve already seen how flex-shrink works. flex-grow is the opposite. If the size of all the flex items along the main axis is smaller than the parent, they can grow to fill that space.

So by default, flex items:

  • don’t grow;
  • if they would otherwise overflow the parent, they are allowed to shrink;
  • their width acts like max-content.

Putting that all together, the flex shorthand defaults to:

.selector {   flex: 0 1 auto; }

The fun thing with the flex shorthand is you can omit values. So, when we declare flex: 1, it’s setting the first value, flex-grow, to 1, which basically turns on flex-grow.

The strange thing here is what happens to the values that you omit. You’d expect them to stay at their defaults, but they don’t. Before we get to what happens, though, let’s first dive into what flex-grow even does.

As we’ve seen, flex-shrink allows elements to shrink if their base sizes add up to a computed value that’s bigger than the available width of the parent container. flex-grow is the opposite. If the grand total of the element base sizes is smaller than the value of the parent container’s width, then they will grow to fill the available space.

If we take that super basic example where we have three small divs next to one another and add flex-grow: 1, they grow to fill that leftover space.

But if we have three divs with unequal widths — like those ones we started with — adding flex-grow to them won’t do anything at all. They won’t grow because they’re already taking up all the available space —so much space, in fact, that flex-shrink needs to kick in and shrink them down to fit!

But, as folks have pointed out to me, setting flex: 1 can work to create equal columns. Well, sort of, as we saw above! In simple situations it does work though, as you can see below.

When we declare flex: 1 it works because, not only does this set the flex-grow to 1, but it also changes the flex-basis!

.selector {   flex: 1;   /* flex-grow: 1; */   /* flex-shrink: 1; */   /* flex-basis: 0%; Wait what? */ }

Yup, setting flex: 1 sets the flex-basis to 0%. This overwrites that intrinsic sizing we had before that behaved like max-content. All of our flex-items now want to have a base size of 0!

Looking at the expanded view of the flex: 1 shorthand in DevTools shows us that the flex-basis has changed to 0

So their base sizes are 0 now, but because of the flex-grow, they can all grow to fill up the empty space. And really, in this case, flex-shrink is no longer doing anything, as all the flex items now have a width of 0, and are growing to fill the available space.

FireFox’s DevTools showing an element with flex: 1 has a content size of 0 and is growing to fill the available space.

Just like the shrink example before, we’re taking the space that’s available, and letting all the flex items grow at an equal rate. Since they are all a base width of 0, growing at an equal rate means the available space is equally divided between them and they all have the same final size!

Except, as we saw, that’s not always the case…

The reason for this is because, when flexbox does all this stuff and distributes the space, whether it’s shrinking or growing a flex item, it’s looking at the content size of the element. If you remember back to the box model, we have the content size itself, then the padding, border, and margin outside of that.

And no, I didn’t forget * { box-sizing: border-box; }.

This is one of those strange quirks of CSS but it does make sense. If the browser looked at the width of those elements and included their padding and borders in the calculations, how could it shrink things down? Either the padding would also have to shrink or things are going to overflow the space. Both of those situations are terrible, so instead of looking at the box-size of elements when calculating the base size of them, it only looks at the content-box!

So, setting flex: 1 causes a problem in cases where you have borders or padding on some of your elements. I now have three elements that have a content-size of 0, but my middle one has padding on it. If we didn’t have that padding, we’d have the same math we did when we looked at how flex-shrink works.

A parent that is 600px and three flex items with a width of 0px. They all have a flex-grow: 1 so they grow at an equal rate, and they each end up 200px wide. But the padding mucks it all up. Instead, I end up with three divs with a content size of 0, but the middle one has padding: 1rem. That means it has a content size of 0, plus 32px padding as well.

We have 600 - 32 = 568px to divide equally, instead of 600px. All the divs want to grow at an equal rate, so 568 / 3 = 189.3333px.

And that’s what happens!

But… remember, that’s their content size, not the total width! That leaves us with two divs with a width of 189.333px, and another with a which of 189.333px + 32 = 221.333px. That’s a pretty substantial difference!

Method 2: flex-basis: 100%

I have always handled this like this:

.flex-parent {   display: flex; }  .flex-parent > * {   flex-basis: 100%; }

I thought this worked for the longest time. Actually, this was supposed to be my final solution after showing that flex: 1 doesn’t work. But while I was writing this article, I realized it also falls into the same problem, but it’s a lot less obvious. Enough so that I didn’t notice it with my eyes.

The elements are all trying to be 100% width, meaning they all want to match the width of the parent, which, again, is 600px (and in normal circumstances, is often much bigger, which further reduces the perceivable difference).

The thing is that 100% includes the padding in the computed values (because of * { box-size: border-box; }, which for the sake of this article, I’m assuming everyone is using). So, the outer divs end up with a content size of 600px, whereas the middle div ends up with a content size of 600 - 32 = 568px.

When the browser is working out how to evenly divide the space, it isn’t looking at how to evenly squish 1800px into a 600px space, but rather it’s looking at how to squish 1768px. Plus, as we saw earlier, flex items don’t shrink by the same amount, but at an equal pace! So, the element with padding shrinks slightly less in total than the others do.

This results in the .card having a final width of 214.483px while the others clock in at 192.75px. Again, this leads to unequal width values, though the difference is smaller than we saw with the flex: 1 solution.

Why CSS Grid is the better choice here

While all this is a little frustrating (and even a little confusing), it all happens for a good reason. If margins, padding, or borders changed sizes when flex gets involved, it would be a nightmare.

And maybe this means that CSS Grid might be a better solution to this really common design pattern.

I’ve long thought that flexbox was easier to pick up and start using than grid, but grid gives you more ultimate control in the long run, but that it’s a lot harder to figure out. I’ve changed my mind on that recently though, and I think not only does grid give us better control in this type of situation, but it’s actually more intuitive as well.

Normally, when we use grid, we explicitly declare our columns using grid-template-columns. We don’t have to do that though. We can make it behave a lot like flexbox does by using grid-auto-flow: column.

.grid-container {   display: grid;   grid-auto-flow: column; }

Just like that, we end up with the same type of behavior as throwing display: flex on there. Like flex, the columns can potentially be unbalanced, but the advantage with grid is that the parent has total control over everything. So, rather than the content of the items having an impact like they would in flexbox, we only need one more line of code and we can solve the problem:

.grid-container {   display: grid;   grid-auto-flow: column;   grid-auto-columns: 1fr; }

I love that this is all on the parent selector, and that we don’t have to select the children to help get the layout that we are after!

The interesting thing here is how fr units work. They are literally called flex units in the spec, and they work just like flexbox does in dividing up space;. The big difference: they’re looking at the other tracks to determine how much space they have, paying no attention to the content inside those tracks.

That’s the real magic here. By declaring grid-auto-columns: 1fr, we are in essence saying, “by default, all my columns should have an equal width,” which is what we’ve been after from the start!

But what about at small screens?

What I love with this approach is we can keep it super simple:

.grid-container {   display: grid;   gap: 1em; }  @media (min-width: 35em) {   grid-auto-flow: column;   grid-auto-columns: 1fr; }

And just like that, it works perfectly. And by declaring display: grid from the start, we can include the gap to maintain equal spacing, whether the children are rows or columns.

I also find this to be a lot more intuitive than changing the flex-direction within a media query to get a similar result. As much as I love flexbox (and I really do still think it has great use cases), the fact that declaring flex-direction: column creates rows, and vice versa, is a little counter-intuitive at first glance.

And of course, if you prefer rolling without media queries, there is nothing stopping you from taking this to the next level with the help of auto-fit, which would be similar to setting something up with flex-wrap (though not exactly the same):

.grid-container {   display: grid;   gap: 1em;   grid-template-columns: repeat(auto-fit, minmax(10em, 25em)); }

Making it work with flexbox

I realize that we can get around this with flexbox by nesting the element with the padding on it. We’ve done this since we started making layouts using floats, and Bootstrap really hammered home this type of design pattern.

<div class="container">   <div class="row">     <div class="col"> <div class="">... </div>     <div class="col"> <div class="element-with-padding">...</div> </div>     <div class="col"> ... </div>   </div> </div>

And there is nothing wrong with that. It works! But floats work too, and we’ve stopped using them for layouts as better solutions have been released in recent years.

One of the reasons that I love grid is because we can simplify our markup quite a bit. Just like we ditched floats for a better solution, I’d at least like to people to keep an open mind that maybe, just maybe, grid could be a better, and more intuitive solution for this type of design pattern.

Flexbox still has it’s place, of course

I still love flexbox, but I think its real power comes from times that we want to rely on the intrinsic width of the flex items, such as with navigations, or groups of elements, such as buttons or other items of varying width that you want to go next to one another.

In those situations, that behavior is an asset that makes things like even spacing between unequal items such a breeze! Flexbox is wonderful, and I have no plans to stop using.

In other situations though, when you find yourself fighting with how flexbox is trying to work, maybe you could turn to grid instead, even if it’s not a typical “2d” grid where you’re told you should be using it for.

People often tell me that they struggle to figure out grid because it’s too complicated, and while it can be, as we saw here, it doesn’t have to be.


The post Equal Columns With Flexbox: It’s More Complicated Than You Might Think appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , , , ,

Safari 14.1 Adds Support for Flexbox Gaps

Yay, it’s here! Safari 14.1 reportedly adds support for the gap property in flexbox layouts. We’ve had grid-gap support for some time, but true to its name, it’s limited to grid layouts. Now we can use gap in either type of layout:

.container {   display: flex;   flex-flow: row wrap;   gap: 1.5rem; }

Apple’s been rather quiet about the update. I didn’t even hear about it until Eric Meyer brought it up in an email, and he only heard about it when Jen Simmons tweeted it out.

I checked the WebKit CSS Feature Status and, sure enough, it’s supported. It just wasn’t called out in the release notes. Nothing is posted to Safari’s release notes archive just yet, so maybe we’ll hear about it officially there at some point. For now, it seems that Maximiliano Firtman‘s overview of iOS 14.5 is the deepest look at what’s new.

And how timely is it that Eric recently covered how to use the gap property, not only in grid and flexbox layouts, but multi-column as well.


The post Safari 14.1 Adds Support for Flexbox Gaps appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , ,
[Top]

grid-auto-flow : CSS Grid :: flex-direction : Flexbox

When setting a parent element to display: flex, its child elements align left-to-right like this:

Now, one of the neat things we can do with flexbox is change the direction so that child elements are stacked vertically on top of each other in a column. We can do that with the flex-direction property (or with the flex-flow shorthand):

Okay, cool. But how would I do something like this with CSS Grid? As in, let’s say I want all those child elements to be aligned like this:

1 3 5 7 -------- 2 4 6 8

…instead of this:

1 2 3 4 -------- 5 6 7 8

By default, when I set a parent element to use CSS Grid, the elements will be positioned left-to-right just like flexbox. In the example below I’m telling the grid to have 6 columns and 2 rows, then let the child elements fill up each column of the first row before they fill up the columns of the second. You know, standard line wrapping behavior.

.parent {   display: grid;   grid-template-columns: repeat(6, 1fr);   grid-template-rows: repeat(2, 150px);   gap: 20px; }

Basically what I want here is the opposite: I want our child elements to fill up column 1, row 1 and row 2, then move on to the next column. In other words, column wrapping! I know that if I create a grid with rows and columns I could individually place those elements into those positions. Like so:

.parent {   display: grid;   grid-template-columns: repeat(6, 1fr);   grid-template-rows: repeat(6, 150px); }  .child-1 {   grid-column: 1;   grid-row: 1; }  .child-2 {   grid-column: 1;   grid-row: 2; }  .child-3 {   grid-column: 2;   grid-row: 1; }  /* etc, etc. */

Okay, neat! This gets me what I want but it’s a giant pain having to individually set the position of each item. It feels like I’m using position: absolute and it doesn’t feel particularly smart. So what if I just wanted this layout to be done for me, so that each new child element would align into the correct spot…correctly?

What I’m asking for (I think) is this: is there a CSS Grid version of flex-direction: column?

Well, after searching around a bit, Rachel Andrew pointed me to the correct answer in her rather excellent playground, Grid by Example. And as you can see in this demo, Rachel shows us how to do just that:

Neato! Rachel does this with the grid-auto-flow property: it tells a grid container how to fill the unoccupied space with child elements. So I can do that just by writing this:

.parent {   display: grid;   grid-auto-flow: column;   /* set up columns and rows here */ }

By default, child elements of a grid will fill up each column until a row is filled, then it’ll flow into the next beneath it. This is why the default for grid-auto-flow is set to row because we’re filling up rows of the grid first. But if we set it to column, then each new element will fill up all the space of column 1 before moving on to column 2, etc.

.parent {   display: grid;   grid-auto-flow: column;   grid-template-columns: repeat(6, 1fr);   grid-template-rows: repeat(2, 150px); }

This is what the flow part of grid-auto-flow means and for the longest time I ignored the property because it seemed (don’t laugh) scary. Just reading the word grid-auto-flow is enough to make me want to shut off my laptop and walk into the ocean.

But! It’s a pretty useful property and makes a ton of sense, especially if you think of it as the CSS Grid version of flex-direction.


The post grid-auto-flow : CSS Grid :: flex-direction : Flexbox appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , ,
[Top]

Balancing on a pivot with Flexbox

Let me show you a way I recently discovered to center a bunch of elements around what I call the pivot. I promise you that funky HTML is out of the question and you won’t need to know any bleeding-edge CSS to get the job done.

I’m big on word games, so I recently re-imagined the main menu of my website as a nod to crossword puzzles, with my name as the vertical word, and the main sections of my website across the horizontals.

Here’s how the design looks with the names of some colors instead:

And here’s a sample of the HTML that drives this puzzle:

<div class="puzzle">   <div class="word">     <span class="letter">i</span>     <span class="letter">n</span>     <span class="letter">d</span>     <span class="letter">i</span>     <span class="letter pivot">g</span>     <span class="letter">o</span>   </div>   <!-- MORE WORDS --> </div>

In this example, the letter g is the pivot. See how it’s not at the halfway mark? That’s the beauty of this challenge.

We could apply an offset to each word using hard-coded CSS or inline custom properties and walk away. It certainly gets an award for being the most obvious way to solve the problem, but there’s a downside — in addition to the .pivot class, we’d have to specify an offset for every word. The voice in my head tells me that’s adding unnecessary redundancy, is less flexible, and requires extra baggage we don’t need every time we add or change a word.

Let’s take a step back instead and see how the puzzle looks without any balancing:

Imagine for a moment that we use display: none to hide all of the letters before the pivot; now all we can see are the pivots and everything after them:

With no further changes, our pivots would already be aligned. But we’ve lost the start of our words, and when we reintroduce the hidden parts, each word gets pushed out to the right and everything is out of whack again.

If we were to hide the trailing letters instead, we’d still be left with misaligned pivots:

All of this back-and-forth seems a bit pointless, but it reveals a symmetry to my problem. If we were to use a right-to-left (RTL) reading scheme, we’d have the opposite problem — we’d be able to solve the right side but the left would be all wrong.

Wouldn’t it be great if there was a way to have both sides line up at the same time?

As a matter of fact, there is.

Given we already have half a solution, let’s borrow a concept from algorithmics called divide and conquer. The general idea is that we can break a problem down into parts, and that by finding a solution for the parts, we’ll find a solution for the whole.

In that case, let’s break our problem down into the positioning of two parts. First is the “head” or everything before the pivot.

Next is the “tail” which is the pivot plus everything after it.

The flex display type will help us here; if you’re not familiar with it, flex is a framework for positioning elements in one-dimension. The trick here is to take advantage of the left and right ends of our container to enforce alignment. To make it work, we’ll swap the head and tail parts by using a smaller order  property value on the tail than the head. The order property is used by flex to determine the sequence of elements in a flexible layout. Smaller numbers are placed earlier in the flow.

To distinguish the head and tail elements without any extra HTML, we can apply styles to the head part to all of the letters, after which we’ll make use of the cascading nature of CSS to override the pivot and everything after it using the subsequent-sibling selector .pivot ~ .letter.

Here’s how things look now:

Okay, so now the head is sitting flush up against the end of the tail. Hang on, don’t go kicking up a stink about it! We can fix this by applying margin: auto to the right of the last element in the tail. That just so happens to also be the last letter in the word which is not sitting somewhere in the middle. The addition of an auto margin serves to push the head away from the tail and all the way over to the right-hand side of our container.

Now we have something that looks like this:

The only thing left is stitch our pieces back together in the right order. This is easy enough to do if we apply position: relative to all of our letters and then chuck a left: 50% on the tail and a right: 50% on our head items.

Here’s a generalized version of the code we just used. As you can see, it’s just 15 lines of simple CSS:

.container {   display: flex; } .item:last-child {   margin-right: auto; } .item {   order: 2;   position: relative;   right: 50%; } .pivot, .pivot ~ .item {   order: 1;   left: 50%; }

It’s also feasible to use this approach for vertical layouts by setting the flex-direction to a column value. It should also be said that the same can be achieved by sticking the head and tail elements in their own wrappers — but that would require more markup and verbose CSS while being a lot less flexible. What if, for example, our back-end is already generating an unwrapped list of elements with dynamically generated classes?

Quite serendipitously, this solution also plays well with screen readers. Although we’re ordering the two sections backwards, we’re then shifting them back into place via relative positioning, so the final ordering of elements matches our markup, albeit nicely centered.

Screen readers preserve the element ordering as per the original markup.

Here’s the final example on CodePen:

Conclusion

Developers are better at balancing than acrobats. Don’t believe me? Think about it: many of the common challenges we face require finding a sweet spot between competing requirements ranging from performance and readability, to style and function, and even scalability and simplicity. A balancing act, no doubt.

But the point at which we find balance isn’t always midway between one thing and another. Balance is often found at some inexplicable point in between; or, as we’ve just seen, around an arbitrary HTML element.

So there you have it! Go and tell your friends that you’re the greatest acrobat around.


The post Balancing on a pivot with Flexbox appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,
[Top]

Using Flexbox and text ellipsis together

You can truncate a single line of text with an ellipsis (…) fairly easily with text-overflow and a few friends. But, as you might expect, that truncation happens at the end of the line of text. What if you want to truncate content in the middle?

Leonardo Faria details good use cases for this, like in an operating system window listing files. The line of text is a file name and a file extension. When that line truncates, it truncates just the name, always leaving the extension at the end. The trick is a flexbox parent so you can use overflow on just the file name part, but have to make sure to reset the min-width, as the natural value there is min-content, which prevents the truncation which is confusing.

Direct Link to ArticlePermalink


The post Using Flexbox and text ellipsis together appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , ,
[Top]

Posters! (for CSS Flexbox and CSS Grid)

Any time I chat with a fellow web person and CSS-Tricks comes up in conversation, there is a good chance they’ll say: oh yeah, that guide on CSS flexbox, I use that all the time!

Indeed that page, and it’s cousin the CSS grid guide, are among our top trafficked pages. I try to take extra care with them making sure the information on them is current, useful, and the page loads speedily and properly. A while back, in a round of updates I was doing on the guides, I reached out to Lynn Fisher, who always does incredible work on everything, to see if she’d be up for re-doing the illustrations on the guides. Miraculously, she agreed, and we have the much more charismatic illustrations that live on the guides today.

In a second miracle, I asked Lynn again if she’d be up for making physical paper poster designs of the guides, and see agreed again! And so they live!

Here they are:

You better believe I have it right next to me in my office:

They are $ 25 each which includes shipping anywhere in the world.

The post Posters! (for CSS Flexbox and CSS Grid) appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Grid for layout, flexbox for components

When should we reach for CSS grid and when should we use flexbox? Rachel Andrew wrote about this very conundrum way back in 2016:

Flexbox is essentially for laying out items in a single dimension – in a row OR a column. Grid is for layout of items in two dimensions – rows AND columns.

Ahmad Shadeed wrote a post where he gives the same advice, but from a different angle. He argues we should use grid for layout and flexbox for components:

Remember that old layout method might be perfect for the job. Overusing flexbox or grid can increase the complexity of your CSS by time. I don’t mean they are complex, but using them correctly and in the right context as explained from the examples in this article is much better.

Speaking of which, there’s so many great layout examples in this post, too.

Direct Link to ArticlePermalink

The post Grid for layout, flexbox for components appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Chromium lands Flexbox gap

I mentioned this the other day via Michelle Barker’s coverage, but here I’ll link to the official announcement. The main thing is that we’ll be getting gap with flexbox, which means:

.flex-parent {   display: flex;   gap: 1rem; } .flex-child {   flex: 1; }

That’s excellent, as putting space in between flex items has been tough in the past. We have justify-content: space-between, which is nice sometimes, but that doesn’t allow you to explicitly tell the flex container how much space you want. For that, we’d typically use margin, but that means avoiding setting the margin on the first or last element depending on the direction of the margin — which is annoying gets complicated.

We have gap in CSS Grid and it’s way better. It’s great to have it in flexbox.

But it’s going to get weird for a minute. Safari doesn’t support it yet (nor stable Chrome) so we can’t just plop it out there and expect it to work with flexbox. But shouldn’t we be able to do an @supports query these days?

/* Nope, sorry. This "works" but it doesn't     actually tell you if it works in *flexbox* or not.    This works in grid in most browsers now, so it will pass. */ @supports (gap: 1rem) {   .flex-parent {      gap: 1rem;   } }

That got weird because grid-gap was dropped in favor of just gap. I’m sure grid-gap will be supported forever because that’s generally how these things go, but we’re encouraged to use gap instead. So, you might say gap is a little overloaded, but that should shake out over time (a year?). It’s complicated a smidge more by the fact that column-gap is now going to gap as well. gap has a whole bunch of jobs.

I’d say I’m still in favor of the change, despite the overloading. Simpler mental modals are important for the long-term, and there isn’t exactly anything coming up to challenge CSS for styling in the browser. I’d bet my 2-year old daughter writes some CSS in her lifetime.

Direct Link to ArticlePermalink

The post Chromium lands Flexbox gap appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Flexbox and absolute positioning

Chen Hui Jing notes that when you absolutely position a flex item, it’s no longer part of the flex layout. Except… it kinda is a little bit. If you make the child position: absolute; but don’t apply any top/right/bottom/left properties, then flexbox alignment will still apply to it.

It’s odd to see, but it makes a certain sort of sense as well. When you apply position: absolute; to things (and nothing else), they kinda just stay where they are until you apply other positioning. Check out how this SVG icon just sits in the middle of this paragraph, and even flows with it on resize, because it doesn’t have any specific positioning instructions other than to not affect anything else.

Direct Link to ArticlePermalink

The post Flexbox and absolute positioning appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

How Auto Margins Work in Flexbox

Robin has covered this before, but I’ve heard some confusion about it in the past few weeks and saw another person take a stab at explaining it, and I wanted to join the party.

Say you have a flex container with some flex items inside that don’t fill the whole area.

See the Pen
ZEYLVEX
by Chris Coyier (@chriscoyier)
on CodePen.

Now I want to push that “Menu” item to the far right. That’s where auto margins come in. If I put a margin-left: auto; on it, it’ll push as far away as it possibly can on that row.

See the Pen
WNbRLbG
by Chris Coyier (@chriscoyier)
on CodePen.

Actually, you might consider margin-inline-start: auto; instead and start using logical properties everywhere so that you’re all set should you need to change direction.

See the Pen
gObgZpb
by Chris Coyier (@chriscoyier)
on CodePen.

Also, note that auto margins work in both directions as long as there is room to push. In this example, it’s not alignment that is moving the menu down, it’s an auto margin.

See the Pen
XWJpobE
by Chris Coyier (@chriscoyier)
on CodePen.

The post How Auto Margins Work in Flexbox appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]