DEV Community

Cover image for 180 Days of Frontend Development Challenge: Day 32 CSS Advanced Flexbox
CodeWithDhanian
CodeWithDhanian

Posted on

180 Days of Frontend Development Challenge: Day 32 CSS Advanced Flexbox

I am Codewithdhanian, front-end adventurers, settle in! We've made it to Day 32 of our epic 180-day journey. If you've been with me from the start, give yourself a mental high-five. You’re doing great!

Today, we're not just dipping our toes into Flexbox; we're diving headfirst into the deep end of Advanced CSS Flexbox. You've probably encountered Flexbox before—it's like that reliable friend who always helps you perfectly align things. But today, we're going to unlock its superpowers and see what it can really do.

Think of Flexbox as your personal layout assistant. You tell it what you want, and it arranges your items beautifully, no matter the screen size. It's incredibly powerful for creating responsive designs without tearing your hair out.

The "Aha!" Moment with Advanced Flexbox

You've likely used display: flex; on a container and then played with justify-content and align-items to spread things out or center them. That's fantastic groundwork! But what about when things get a little more complex? What if you want one item to take up all the available space, while others just take up what they need? Or perhaps you want to reorder items without touching your HTML? That's where the "advanced" part comes in.

Key Concepts We'll Unpack Today:

  1. flex-grow: Imagine you have a pie, and everyone wants a slice. flex-grow is like telling certain pieces of the pie to expand and take up more of the remaining space within the flex container. The "remaining space" is whatever is left after all flex items have taken up their initial flex-basis size.
  * A value of `1` means "take up an equal share of the leftover space."
  * A value of `2` means "take up *twice* as much as someone with a `flex-grow` of `1`."
  * A value of `0` means "do not grow at all, just stick to your `flex-basis` size."

`flex-grow` is incredibly useful for creating layouts where some elements should dynamically fill the available horizontal or vertical space (depending on `flex-direction`), while others maintain a fixed size or grow proportionally less.
Enter fullscreen mode Exit fullscreen mode
  1. flex-shrink: This is the opposite of flex-grow, and it comes into play when there isn't enough space for all your flex items to maintain their flex-basis size. flex-shrink dictates how much an item shrinks relative to its siblings. The default value for flex-shrink is 1.
  * A value of `1` means it will shrink proportionally to other items with a `flex-shrink` of `1`.
  * A value of `0` means "don't you dare shrink me\!" (useful for ensuring crucial elements, like buttons or icons, maintain their minimum required size).
  * Higher values mean the item will shrink more aggressively than others.

Understanding `flex-shrink` is crucial for creating robust, responsive designs that gracefully handle shrinking screen sizes or excessive content.
Enter fullscreen mode Exit fullscreen mode
  1. flex-basis: Before any growing or shrinking happens, flex-basis defines the initial main size of a flex item. Think of it as its default width (if flex-direction is row or row-reverse) or height (if flex-direction is column or column-reverse).
  * You can use values like `auto` (which uses the item's content size or any explicitly set width/height), or specific measurements like `200px`, `30%`, `5rem`, etc.
  * If `flex-basis` is set to `auto` and the item also has an explicit `width` (or `height` in a column flex container), the `width` will take precedence for the initial size.
  * If `flex-basis` is set to a specific value (e.g., `200px`), that value will override any `width` property on the item.

`flex-basis` gives you precise control over the starting size of your flex items before they are distributed along the main axis.
Enter fullscreen mode Exit fullscreen mode
  1. The flex Shorthand: Instead of writing flex-grow, flex-shrink, and flex-basis separately, you can use the flex shorthand property. It's an incredibly common and efficient way to define these three properties at once.
  * The order is: `flex-grow flex-shrink flex-basis`.
  * **Common Usage Examples:**
      * `flex: 1;` is a shorthand for `flex: 1 1 0%;`. This is a very common pattern meaning the item can grow and shrink, and its basis is 0. This effectively makes items "fill" the space equally.
      * `flex: auto;` is a shorthand for `flex: 1 1 auto;`. This means the item can grow and shrink, and its basis is determined by its content.
      * `flex: none;` is a shorthand for `flex: 0 0 auto;`. This means the item will not grow or shrink, and its basis is determined by its content (making it a fixed-size item).
      * `flex: 0 0 200px;` means no growing, no shrinking, and a fixed basis of 200px.

Mastering the `flex` shorthand will significantly streamline your CSS.
Enter fullscreen mode Exit fullscreen mode
  1. order: This is where Flexbox truly shines for reordering. If you want to change the visual order of your items without changing their source order in your HTML (which is excellent for accessibility and maintainability), order is your friend.
  * By default, all items have an `order` of `0`.
  * Items with lower `order` values appear first.
  * Items with higher `order` values appear later.
  * If items have the same `order` value, their order is determined by their source order in the HTML.
  * You can use positive or negative integers (e.g., `order: -1;` or `order: 5;`).

This property is powerful for creating responsive designs where the layout needs to change dramatically at different screen sizes without altering the semantic meaning of your HTML.
Enter fullscreen mode Exit fullscreen mode

Let's Get Our Hands Dirty (Code Examples):

Imagine a simple navigation bar.

HTML:

<nav class="navbar">
    <div class="nav-item">Home</div>
    <div class="nav-item">About</div>
    <div class="nav-item">Services</div>
    <div class="nav-item">Contact</div>
    <div class="nav-item">Blog</div>
</nav>
Enter fullscreen mode Exit fullscreen mode

Basic Flexbox (Review):

.navbar {
    display: flex;
    justify-content: space-around; /* Spreads items out evenly */
    align-items: center; /* Vertically centers items */
    border: 1px solid #ccc;
    padding: 10px;
    height: 60px; /* Added for better visualization of vertical alignment */
}

.nav-item {
    padding: 10px 15px;
    background-color: lightblue;
    margin: 5px;
    border-radius: 5px;
}
Enter fullscreen mode Exit fullscreen mode

Now, let's play with Advanced Flexbox:

Example 1: Making items grow disproportionately with flex-grow

Let's say we want the "Services" item to take up twice as much available space as "Home" and "About", and "Contact" and "Blog" should not grow at all, maintaining their minimum content size.

.navbar {
    display: flex;
    justify-content: space-around;
    align-items: center;
    border: 1px solid #ccc;
    padding: 10px;
    height: 60px;
    width: 100%; /* Ensure container has space to grow into */
    box-sizing: border-box; /* Include padding/border in total width */
}

.nav-item {
    padding: 10px 15px;
    background-color: lightblue;
    margin: 5px;
    border-radius: 5px;
    flex-grow: 1; /* By default, all items would grow equally */
    flex-basis: auto; /* Start with content-based width */
}

/* Specific flex-grow values */
.nav-item:nth-child(3) { /* Targeting "Services" */
    flex-grow: 2; /* Services will grow twice as much as items with flex-grow: 1 */
    background-color: lightcoral;
}

.nav-item:nth-child(4), /* Targeting "Contact" */
.nav-item:nth-child(5) { /* Targeting "Blog" */
    flex-grow: 0; /* These items will not grow, keeping their flex-basis (auto in this case) */
    background-color: lightgreen;
}
Enter fullscreen mode Exit fullscreen mode

Explanation: When the .navbar container has more space than its items initially occupy, flex-grow distributes that extra space. "Services" gets a larger share (2 units) compared to "Home" and "About" (1 unit each). "Contact" and "Blog" get 0 units, meaning they just keep their content size.

Example 2: Controlling initial size with flex-basis and the flex shorthand

Maybe "Home" always needs to be at least 100px wide, "About" at least 150px, and "Services" should fill the rest, while "Contact" and "Blog" have a fixed size.

.navbar {
    display: flex;
    justify-content: flex-start; /* Let items fill from the start */
    align-items: center;
    border: 1px solid #ccc;
    padding: 10px;
    height: 60px;
    width: 100%;
    box-sizing: border-box;
}

.nav-item {
    padding: 10px 15px;
    background-color: lightblue;
    margin: 5px;
    border-radius: 5px;
    /* Default for items not explicitly set */
    flex: 0 1 auto; /* Don't grow, can shrink, basis is auto */
}

.nav-item:first-child { /* Targeting "Home" */
    flex: 0 0 100px; /* Don't grow, don't shrink, initial basis 100px */
    background-color: orange;
}

.nav-item:nth-child(2) { /* Targeting "About" */
    flex: 0 0 150px; /* Don't grow, don't shrink, initial basis 150px */
    background-color: pink;
}

.nav-item:nth-child(3) { /* Targeting "Services" */
    flex: 1 1 auto; /* Grow to fill space, can shrink, basis is auto */
    background-color: lightcoral;
}

.nav-item:nth-child(4) { /* Targeting "Contact" */
    flex: 0 0 80px; /* Fixed width of 80px */
    background-color: lightgreen;
}

.nav-item:nth-child(5) { /* Targeting "Blog" */
    flex: 0 0 70px; /* Fixed width of 70px */
    background-color: lightseagreen;
}
Enter fullscreen mode Exit fullscreen mode

Explanation: Here, flex-basis dictates the starting size. "Home" and "About" get fixed starting widths. "Services" gets flex: 1 1 auto; which means it will take up all the remaining space after the fixed-size items are laid out. "Contact" and "Blog" also have fixed widths thanks to flex: 0 0 [value].

Example 3: Controlling shrinking with flex-shrink

Let's make sure "Home" never shrinks, even if the container gets too small, while "About" shrinks normally, and "Services" shrinks more aggressively.

.navbar {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    border: 1px solid #ccc;
    padding: 10px;
    height: 60px;
    width: 400px; /* Make the container narrow to force shrinking */
    overflow: auto; /* Add scroll if items overflow completely */
    box-sizing: border-box;
}

.nav-item {
    padding: 10px 15px;
    background-color: lightblue;
    margin: 5px;
    border-radius: 5px;
    flex-basis: 120px; /* Give all items an initial large basis */
    flex-grow: 0; /* Don't grow, we are testing shrinking */
    flex-shrink: 1; /* Default shrink behavior for most */
}

.nav-item:first-child { /* Targeting "Home" */
    flex-shrink: 0; /* This item will NOT shrink */
    background-color: orange;
}

.nav-item:nth-child(2) { /* Targeting "About" */
    flex-shrink: 1; /* Shrinks normally */
    background-color: pink;
}

.nav-item:nth-child(3) { /* Targeting "Services" */
    flex-shrink: 3; /* Shrinks three times as much as others */
    background-color: lightcoral;
}

/* Observe the behavior when you resize the browser window! */
Enter fullscreen mode Exit fullscreen mode

Explanation: When the navbar width is 400px, and each item has a flex-basis of 120px, the total initial width (5 * 120px = 600px) exceeds the container width. This triggers flex-shrink. "Home" (flex-shrink: 0) retains its 120px width. "About" (flex-shrink: 1) shrinks proportionally. "Services" (flex-shrink: 3) takes the brunt of the shrinking, becoming much smaller than "About".

Example 4: Reordering items with order

Let's move "Contact" to be the second item in the visual layout, "Blog" to be first, and "Home" to be last, even though their HTML order is different.

<nav class="navbar">
    <div class="nav-item">Home</div>
    <div class="nav-item">About</div>
    <div class="nav-item">Services</div>
    <div class="nav-item">Contact</div>
    <div class="nav-item">Blog</div>
</nav>
Enter fullscreen mode Exit fullscreen mode
.navbar {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    border: 1px solid #ccc;
    padding: 10px;
    height: 60px;
    width: 100%;
    box-sizing: border-box;
}

.nav-item {
    padding: 10px 15px;
    background-color: lightblue;
    margin: 5px;
    border-radius: 5px;
    order: 0; /* Default order for all items */
}

.nav-item:first-child { /* Targeting "Home" */
    order: 10; /* Assign a high order to make it appear last */
    background-color: orange;
}

.nav-item:nth-child(4) { /* Targeting "Contact" */
    order: -1; /* Assign a negative order to make it appear before default (0) items */
    background-color: lightgreen;
}

.nav-item:nth-child(5) { /* Targeting "Blog" */
    order: -2; /* Assign an even lower order to make it appear first */
    background-color: lightseagreen;
}

/* "About" and "Services" (nth-child 2 & 3) still have order: 0,
   so they will appear after "Blog" and "Contact" but before "Home".
   Their relative order will be determined by their HTML source order. */
Enter fullscreen mode Exit fullscreen mode

Explanation: Items with lower order values appear first. So, "Blog" (order: -2) comes before "Contact" (order: -1). Then come "About" and "Services" (both order: 0, so their original HTML order is preserved). Finally, "Home" (order: 10) appears at the very end.

Go Even Deeper!

Flexbox has many nuances, and while these advanced properties are crucial, there's always more to learn. For those who want to accelerate their understanding and have a handy reference guide, I highly recommend checking out "Flexbox CSS in 30 Minutes" by Dhanian.

You can get the ebook here: https://codewithdhanian.gumroad.com/l/ejmgi

It's a concise, practical resource that can solidify your Flexbox knowledge and provide quick solutions when you're stuck. Learning from well-structured guides like this can significantly boost your productivity and confidence in building complex layouts.

Your Challenge for Day 32:

  1. Create a complex layout with at least 6 flex items inside a flex container. Use a variety of content types (short text, long text, maybe an image).
  2. Experiment with flex-grow:
    • Make one item grow significantly more (e.g., flex-grow: 3;).
    • Make another item not grow at all (flex-grow: 0;).
    • Make the remaining items grow equally (flex-grow: 1;).
  3. Experiment with flex-shrink:
    • Set your flex container to a fixed width that is smaller than the sum of your items' flex-basis values (this will force shrinking).
    • Make one item refuse to shrink (flex-shrink: 0;).
    • Make another item shrink more aggressively than others (flex-shrink: 2;).
  4. Use flex-basis:
    • Give some items a fixed initial width (e.g., 100px, 15rem).
    • Give other items an auto basis.
    • Give one item a percentage basis (e.g., 30%).
  5. Implement the flex shorthand property for all your items, combining flex-grow, flex-shrink, and flex-basis where appropriate. This is a common practice.
  6. Reorder at least three items using the order property, ensuring their visual appearance differs significantly from their HTML source order. Try using both positive and negative order values.
  7. Bonus: Add some media queries to your CSS and change some flex properties (e.g., flex-direction, flex-grow, flex-basis, or order) at different screen sizes to see how responsive designs work with these advanced properties.

Don't just copy and paste! Play around with the values. Break it, fix it, learn from it. That's how you truly understand these concepts. Open your browser's developer tools and inspect the flex items to see how their computed sizes change as you manipulate the properties and resize the window.

This advanced dive into Flexbox might feel like a lot at first, but with practice, it becomes incredibly intuitive. It’s a game-changer for building robust and adaptable web layouts.

Keep up the fantastic work! Day 33 awaits, and we'll be building on these powerful layout techniques. What cool layouts are you excited to build with your new Flexbox superpowers?

Google AI Education track image

Build Apps with Google AI Studio 🧱

This track will guide you through Google AI Studio's new "Build apps with Gemini" feature, where you can turn a simple text prompt into a fully functional, deployed web application in minutes.

Read more →

Top comments (0)

MongoDB Atlas runs apps anywhere. Try it now.

MongoDB Atlas runs apps anywhere. Try it now.

MongoDB Atlas lets you build and run modern apps anywhere—across AWS, Azure, and Google Cloud. With availability in 115+ regions, deploy near users, meet compliance, and scale confidently worldwide.

Start Free

👋 Kindness is contagious

Dive into this thoughtful piece, beloved in the supportive DEV Community. Coders of every background are invited to share and elevate our collective know-how.

A sincere "thank you" can brighten someone's day—leave your appreciation below!

On DEV, sharing knowledge smooths our journey and tightens our community bonds. Enjoyed this? A quick thank you to the author is hugely appreciated.

Okay