Tag: Flexbox

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

, , ,

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]

The Thought Process Behind a Flexbox Layout

I just need to put two boxes side-by-side and I hear flexbox is good at stuff like that.

Just adding display: flex; to the parent element lays out the children in a row.

Well, that’s cool. I guess I could have floated them, but this is easier.

They should probably take up the full space they have though. Can I just stretch the parent to 100% wide? Well, I can, but that’s apparently not going to affect the child elements.

If the parent element has more space than the children need, it doesn’t do anything to help the children fill the space alone.

Maybe I can use width: 50%; on the children? That works, but I thought the point of flexbox is that you don’t have to be all specific about width. Ah yes, flexbox has all of these ways of expressing the growy-shrinky-initial behavior of children. Looks like flex: 1; is about as easy as it gets here.

Applying flex: 1; to the children allow them to grow and fill the space.

I like how I haven’t had to do any math or hard code values so far. Can I make it a three-up pattern without touching CSS?

Nice.

Hmmm, wait. The sizing is a bit, uhhhh, flexy? Nothing is forcing these boxes to be one-third of the container all the time.

Looks like flex-basis: 33% doesn’t fix this. flex: 0 0 33%; also doesn’t do the trick. Looks like width: 33%; flex-shrink: 0; does though, if we’re really wanting to strongarm it.

Sometimes a design calls for exactly equal size boxes. This is maybe CSS Grid territory, but whatever.

The long word forcing that sizing behavior at narrow widths is perhaps an uncommon scenario. We could have also solved it with word-break: break-word; hyphens: auto; on the child.

Another thing we could do it just let the dang items wrap instead of being so strict about it. Flexbox can do that, right?

Oh hey, that reminds me how cool it is that those first two items are the same height. That’s the default stretch behavior, but it can be controlled as well. And it’s by row, which is why the second row has its own different height.

What if I want that first “Love” block to be on top instead? Looks like I can re-order it, eh? Let’s see, the default order is 0, so to be first, I do order: -1;.

Ha! That kinda worked. But I meant that I want it to take up the full width on the top row. I guess I can just kick it up to flex-basis: 100%; and the others will wrap accordingly.

It’s pretty weird to have the source order and visual order different like this. Maybe that should go in the “don’t ever do this” category.

What if I wanna bail on the whole flexbox thing at a certain point? Part of me wants to change the direction to go vertical with flex-direction: column; and force the children to be full-width. Ah, a simple display: block; on the parent does that in one swoop.

Rather than changing all the flexbox stuff to handle a column layout, we just turn flexbox off.

Flexbox can do way more stuff! One of my favorites is how auto margins work to “push” other elements away when there is space. This is just one little journey playing with some UI and seeing the useful things flexible does along with things that can make it confusing.

The post The Thought Process Behind a Flexbox Layout appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Adaptive Photo Layout with Flexbox

Let’s take a look at a super lightweight way to create a horizontal masonry effect for a set of arbitrarily-sized photos. Throw any set of photos at it, and they will line up edge-to-edge with no gaps anywhere.

The solution is not only lightweight but also quite simple. We’ll be using an unordered list of images and just 17 lines of CSS, with the heavy lifters being flexbox and object-fit.

Why?

I have two hobbies: documenting my life with photos, and figuring out interesting ways to combine CSS properties, both old and new.

A couple of weeks ago, I attended XOXO and shot a ton of photos which I narrowed down to a nice little set of 39. Wanting to own my content, I’ve spent the past couple of years thinking about putting together a simple photo blog, but was never able to nail the layout I had in mind: a simple masonry layout where photos fill out rows while respecting their aspect ratio (think Photos.app on iOS, Google Photos, Flickr…).

I did some research to see if there were any lightweight, non-JavaScript options, but couldn’t find anything suiting my needs. Facing some delayed flights, I started playing around with some code, limiting myself to keep things as simple as possible (because that’s my definition of fun).

Basic Markup

Since I’m basically creating a list of images, I opted for an unordered list:

<ul>   <li>     <img>   </li>   <!-- ... -->   <li>     <img>   </li> </ul>

All hail flexbox

Then came a string of lightbulb moments:

  • Flexbox is great for filling up rows by determining cell width based on cell content.
  • This meant the images (landscape or portrait) all needed to have the same height.
  • I could use object-fit: cover; to make sure the images filled the cells.

In theory, this sounded like a solid plan, and it got me a result I was about 90% happy with.

ul {   display: flex;   flex-wrap: wrap; }  li {   height: 40vh;   flex-grow: 1; }  img {   max-height: 100%;   min-width: 100%;   object-fit: cover;   vertical-align: bottom; }

Note: 40vh seemed like the best initial approach for desktop browsers, showing two full rows of photos at a reasonable size, and hinting at more below. This also allowed more photos per line, which dramatically improves the aspect ratios.

Last row stretchiness

The only issue I ran into is that flexbox really wants to fill all the lines, and it did some silly things to the aspect ratios of the photos on the last row. This is probably my least favorite bit of this layout, but I had to add an empty <li> element at the end of the list.

<ul>   <li>     <img>   </li>   <!-- ... -->   <li>     <img>   </li>   <li></li> </ul>

Combined with this bit of CSS:

li:last-child {   flex-grow: 10; }

Note: There’s no science in using “10” here. In all my testing, this delivered the best results.

Demo

See the Pen
Adaptive Photo Layout
by Tim Van Damme (@maxvoltar)
on CodePen.

Viewport optimization

There are some considerations to keep in mind when working in different viewport orientations.

Portrait

If your viewport is taller than it is wide, this approach limits the amount of photos per line thus messing up their aspect ratios. To solve this, you can make the photo rows less tall with this simple media query:

@media (max-aspect-ratio: 1/1) {   li {     height: 30vh;   } }

Short Screens

To help with small devices in landscape, increasing the height of photos helps to see them as large as possible:

@media (max-height: 480px) {   li {     height: 80vh;   } }

Smaller Screens + Portrait

Most phones aren’t wide enough to allow flexbox to properly do its job without miniaturizing the photos, so here I opted to not try to fit multiple photos per line. Still, it’s worth setting a maximum height here so you’ll at least have a hint at the next photo in the list.

@media (max-aspect-ratio: 1/1) and (max-width: 480px) {   ul {     flex-direction: row;   }    li {     height: auto;     width: 100%;   }    img {     width: 100%;     max-height: 75vh;     min-width: 0;   } }

There we have it!

This approach doesn’t fully respect the aspect ratios of photos (but it’s close) and occasionally leads to some weird results, but I absolutely love the simplicity and flexibility of it all. Want to have your gallery scroll horizontally instead of vertically? A couple of tweaks will allow you to do this. Are there 1,000 photos in the gallery or just one? It’ll all look good. Unclear about aspect ratios? Flexbox is your best friend. Take another look at the demo if you haven’t yet, and let me know what you think!

Bonus

Depending on the size of these photos, a page like this can grow to multiple megabytes real quick. On the blog I’m working on, I’ve added loading="lazy" to help with this. With that attribute in place on the images, it only loads photos once you approach them while scrolling. It’s supported just in Chrome for now, but you could roll your own more supported technique.

The post Adaptive Photo Layout with Flexbox appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]