Skillversitas

Flexbox - Flexible Layout in CSS

Flexbox (Flexible Box Layout) is a CSS layout model designed to arrange elements in one dimension — either horizontally or vertically. With Flexbox, you can easily control the distribution, alignment, and order of elements without resorting to floats or fiddly positioning.

Flexbox works with the concept of a container and items. You apply display: flex to a parent element (the container), and all of its direct children instantly become flex items that you can control flexibly.

Advantages of Flexbox:
- Solves the centering problem that was difficult with older methods
- Controls the distribution of space between elements
- Changes the visual order of elements without changing the HTML
- Makes responsive layouts easier to build
- Controls the height of elements within a single row


Key Flexbox Properties

Flex Container

Property Purpose
display: flex Enables Flexbox on the container
flex-direction Sets the direction of the main axis (horizontal/vertical)
flex-wrap Controls whether items wrap to a new row
justify-content Alignment along the main axis (horizontal)
align-items Alignment along the cross axis (vertical)
align-content Alignment between rows when there are multiple rows
gap Spacing between items

Flex Item

Property Purpose
flex-grow How much the item grows to fill the remaining space
flex-shrink How much the item shrinks when space is limited
flex-basis The item's starting size before growing/shrinking
flex Shorthand for grow, shrink, and basis
order Changes the visual order of the item
align-self Overrides align-items for a single item

Code Example

Basic Flexbox

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Flexbox Dasar</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Segoe UI', Tahoma, sans-serif;
      padding: 20px;
      background: #f0f2f5;
    }

    h2 {
      margin-bottom: 15px;
      color: #1a1a2e;
    }

    /* ===== FLEX DIRECTION ===== */
    .direction-section {
      margin-bottom: 30px;
    }

    .flex-container {
      display: flex;
      gap: 10px;
      padding: 20px;
      background: #ffffff;
      border-radius: 12px;
      border: 2px dashed #cbd5e1;
      min-height: 100px;
    }

    .flex-row {
      flex-direction: row;
    }

    .flex-column {
      flex-direction: column;
    }

    .flex-row-reverse {
      flex-direction: row-reverse;
    }

    .flex-column-reverse {
      flex-direction: column-reverse;
    }

    .flex-item {
      padding: 15px 25px;
      background: linear-gradient(135deg, #667eea, #764ba2);
      color: white;
      border-radius: 8px;
      font-weight: 600;
      text-align: center;
      min-width: 80px;
    }

    .flex-item:nth-child(2) {
      background: linear-gradient(135deg, #f093fb, #f5576c);
    }

    .flex-item:nth-child(3) {
      background: linear-gradient(135deg, #4facfe, #00f2fe);
    }

    /* ===== JUSTIFY CONTENT ===== */
    .justify-section {
      margin-bottom: 30px;
    }

    .justify-start { justify-content: flex-start; }
    .justify-center { justify-content: center; }
    .justify-end { justify-content: flex-end; }
    .justify-between { justify-content: space-between; }
    .justify-around { justify-content: space-around; }
    .justify-evenly { justify-content: space-evenly; }

    /* ===== ALIGN ITEMS ===== */
    .align-section {
      margin-bottom: 30px;
    }

    .align-stretch {
      align-items: stretch;
    }

    .align-center {
      align-items: center;
    }

    .align-start {
      align-items: flex-start;
    }

    .align-end {
      align-items: flex-end;
    }

    .align-baseline {
      align-items: baseline;
    }

    .align-container .flex-item:nth-child(1) {
      font-size: 12px;
    }

    .align-container .flex-item:nth-child(2) {
      font-size: 20px;
    }

    .align-container .flex-item:nth-child(3) {
      font-size: 16px;
    }

    /* ===== FLEX WRAP ===== */
    .wrap-section {
      margin-bottom: 30px;
    }

    .no-wrap {
      flex-wrap: nowrap;
    }

    .do-wrap {
      flex-wrap: wrap;
    }

    .wrap-container .flex-item {
      min-width: 150px;
    }

    /* ===== FLEX ITEM PROPERTIES ===== */
    .item-section {
      margin-bottom: 30px;
    }

    .grow-container .flex-item:nth-child(1) {
      flex-grow: 1;
    }

    .grow-container .flex-item:nth-child(2) {
      flex-grow: 2;
    }

    .grow-container .flex-item:nth-child(3) {
      flex-grow: 1;
    }

    .basis-container .flex-item:nth-child(1) {
      flex-basis: 100px;
    }

    .basis-container .flex-item:nth-child(2) {
      flex-basis: 200px;
    }

    .basis-container .flex-item:nth-child(3) {
      flex-basis: 150px;
    }

    .shrink-container {
      width: 400px;
    }

    .shrink-container .flex-item:nth-child(1) {
      flex-shrink: 0;
      width: 200px;
    }

    .shrink-container .flex-item:nth-child(2) {
      flex-shrink: 1;
    }

    .shrink-container .flex-item:nth-child(3) {
      flex-shrink: 2;
    }

    /* ===== ORDER ===== */
    .order-container .flex-item:nth-child(1) {
      order: 3;
    }

    .order-container .flex-item:nth-child(2) {
      order: 1;
    }

    .order-container .flex-item:nth-child(3) {
      order: 2;
    }

    /* ===== ALIGN SELF ===== */
    .self-container {
      height: 200px;
    }

    .self-container .flex-item:nth-child(1) {
      align-self: flex-start;
    }

    .self-container .flex-item:nth-child(2) {
      align-self: center;
    }

    .self-container .flex-item:nth-child(3) {
      align-self: flex-end;
    }

    .label {
      font-size: 12px;
      color: #64748b;
      margin-bottom: 8px;
      font-family: monospace;
      background: #e2e8f0;
      display: inline-block;
      padding: 3px 8px;
      border-radius: 4px;
    }
  </style>
</head>
<body>
  <!-- Flex Direction -->
  <div class="direction-section">
    <h2>Flex Direction</h2>

    <span class="label">flex-direction: row</span>
    <div class="flex-container flex-row">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">flex-direction: column</span>
    <div class="flex-container flex-column">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">flex-direction: row-reverse</span>
    <div class="flex-container flex-row-reverse">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">flex-direction: column-reverse</span>
    <div class="flex-container flex-column-reverse">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </div>

  <!-- Justify Content -->
  <div class="justify-section">
    <h2>Justify Content</h2>

    <span class="label">justify-content: flex-start</span>
    <div class="flex-container justify-start">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">justify-content: center</span>
    <div class="flex-container justify-center">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">justify-content: space-between</span>
    <div class="flex-container justify-between">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">justify-content: space-around</span>
    <div class="flex-container justify-around">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">justify-content: space-evenly</span>
    <div class="flex-container justify-evenly">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </div>

  <!-- Align Items -->
  <div class="align-section">
    <h2>Align Items</h2>

    <span class="label">align-items: stretch</span>
    <div class="flex-container align-stretch align-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">align-items: center</span>
    <div class="flex-container align-center align-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>

    <br>

    <span class="label">align-items: baseline</span>
    <div class="flex-container align-baseline align-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </div>

  <!-- Flex Wrap -->
  <div class="wrap-section">
    <h2>Flex Wrap</h2>

    <span class="label">flex-wrap: nowrap (default)</span>
    <div class="flex-container no-wrap wrap-container">
      <div class="flex-item">Item 1</div>
      <div class="flex-item">Item 2</div>
      <div class="flex-item">Item 3</div>
      <div class="flex-item">Item 4</div>
      <div class="flex-item">Item 5</div>
    </div>

    <br>

    <span class="label">flex-wrap: wrap</span>
    <div class="flex-container do-wrap wrap-container">
      <div class="flex-item">Item 1</div>
      <div class="flex-item">Item 2</div>
      <div class="flex-item">Item 3</div>
      <div class="flex-item">Item 4</div>
      <div class="flex-item">Item 5</div>
    </div>
  </div>

  <!-- Flex Grow -->
  <div class="item-section">
    <h2>Flex Grow</h2>

    <span class="label">flex-grow: 1 | 2 | 1</span>
    <div class="flex-container grow-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </div>

  <!-- Flex Basis -->
  <div class="item-section">
    <h2>Flex Basis</h2>

    <span class="label">flex-basis: 100px | 200px | 150px</span>
    <div class="flex-container basis-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </div>

  <!-- Order -->
  <div class="item-section">
    <h2>Order</h2>

    <span class="label">order: 3 | 1 | 2</span>
    <div class="flex-container order-container">
      <div class="flex-item">1 (order:3)</div>
      <div class="flex-item">2 (order:1)</div>
      <div class="flex-item">3 (order:2)</div>
    </div>
  </div>

  <!-- Align Self -->
  <div class="item-section">
    <h2>Align Self</h2>

    <span class="label">align-self: flex-start | center | flex-end</span>
    <div class="flex-container self-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </div>
</body>
</html>

Code Explanation

Flex Direction

flex-direction determines the direction of the main axis of the flex container:

  • row — Items are laid out from left to right (default)
  • column — Items are laid out from top to bottom
  • row-reverse — Items are laid out from right to left
  • column-reverse — Items are laid out from bottom to top
.flex-row { flex-direction: row; }
.flex-column { flex-direction: column; }
.flex-row-reverse { flex-direction: row-reverse; }
.flex-column-reverse { flex-direction: column-reverse; }

Justify Content

justify-content controls how items are distributed along the main axis (horizontal for row):

  • flex-start — Items stick to the start (left)
  • center — Items are centered
  • flex-end — Items stick to the end (right)
  • space-between — Free space is distributed between items (no spacing at the edges)
  • space-around — Free space around each item (half at the edges)
  • space-evenly — Free space is evenly distributed on all sides, including the edges

Align Items

align-items controls the alignment of items along the cross axis (vertical for row):

  • stretch — Items stretch to fill the container's height (default)
  • center — Items are vertically centered
  • flex-start — Items stick to the top
  • flex-end — Items stick to the bottom
  • baseline — Items are aligned based on the text baseline

Flex Wrap

flex-wrap controls whether items move to a new row:

  • nowrap — All items stay on a single row (default), which may overflow
  • wrap — Items automatically move to a new row when there is not enough space
.flex-container {
  flex-wrap: wrap;
  gap: 10px;
}

Flex Grow, Shrink, Basis

Properties on a flex item that control sizing:

  • flex-grow — How much the item grows to fill the remaining space. A value of 2 grows twice as much as a value of 1
  • flex-shrink — How much the item shrinks when space is limited
  • flex-basis — The item's starting size before grow/shrink is applied
.item-1 { flex-grow: 1; }
.item-2 { flex-grow: 2; } /* Twice as large as item-1 */
.item-3 { flex-basis: 200px; flex-shrink: 0; }

Shorthand flex:

.item {
  flex: 1;           /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
  flex: 0 0 200px;   /* flex-grow: 0, flex-shrink: 0, flex-basis: 200px */
}

Order

order changes the visual order of items without changing the HTML. By default, all items have a value of 0. The smaller the number, the earlier the item appears:

.item-1 { order: 3; } /* Appears last */
.item-2 { order: 1; } /* Appears first */
.item-3 { order: 2; } /* Appears in the middle */

Align Self

align-self lets a single flex item override the container's align-items:

.flex-item-important {
  align-self: center; /* Centered on its own, the others stretch */
}

Everyday Use Cases

1. Simple Navbar

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    .navbar {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 15px 30px;
      background: #1a1a2e;
      color: white;
    }

    .navbar-brand {
      font-size: 24px;
      font-weight: bold;
    }

    .navbar-links {
      display: flex;
      gap: 25px;
      list-style: none;
    }

    .navbar-links a {
      color: #e2e8f0;
      text-decoration: none;
      transition: color 0.3s;
    }

    .navbar-links a:hover {
      color: #818cf8;
    }

    .navbar-actions {
      display: flex;
      gap: 10px;
    }

    .btn {
      padding: 8px 20px;
      border-radius: 6px;
      border: none;
      cursor: pointer;
      font-weight: 600;
    }

    .btn-outline {
      background: transparent;
      border: 2px solid #818cf8;
      color: #818cf8;
    }

    .btn-primary {
      background: #818cf8;
      color: white;
    }
  </style>
</head>
<body>
  <nav class="navbar">
    <div class="navbar-brand">MyBrand</div>
    <ul class="navbar-links">
      <li><a href="#">Home</a></li>
      <li><a href="#">Products</a></li>
      <li><a href="#">Tentang</a></li>
      <li><a href="#">Kontak</a></li>
    </ul>
    <div class="navbar-actions">
      <button class="btn btn-outline">Log In</button>
      <button class="btn btn-primary">Sign Up</button>
    </div>
  </nav>
</body>
</html>

Explanation: The navbar uses display: flex on the container. justify-content: space-between separates the brand, links, and actions into three sections. align-items: center aligns all elements to the vertical center.

2. Card Layout

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    .card-grid {
      display: flex;
      flex-wrap: wrap;
      gap: 20px;
      padding: 20px;
    }

    .card {
      flex: 1 1 280px;
      background: white;
      border-radius: 12px;
      overflow: hidden;
      box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    }

    .card-image {
      width: 100%;
      height: 180px;
      background: linear-gradient(135deg, #667eea, #764ba2);
    }

    .card-body {
      padding: 20px;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .card-body h3 {
      font-size: 18px;
    }

    .card-body p {
      color: #64748b;
      line-height: 1.5;
    }

    .card-footer {
      padding: 0 20px 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .card-price {
      font-size: 20px;
      font-weight: bold;
      color: #667eea;
    }

    .btn-buy {
      padding: 8px 16px;
      background: #667eea;
      color: white;
      border: none;
      border-radius: 6px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <div class="card-grid">
    <div class="card">
      <div class="card-image"></div>
      <div class="card-body">
        <h3>Product A</h3>
        <p>This product's short description is great.</p>
      </div>
      <div class="card-footer">
        <span class="card-price">$25.00</span>
        <button class="btn-buy">Beli</button>
      </div>
    </div>
    <div class="card">
      <div class="card-image"></div>
      <div class="card-body">
        <h3>Product B</h3>
        <p>This product's short description is really great.</p>
      </div>
      <div class="card-footer">
        <span class="card-price">$15.00</span>
        <button class="btn-buy">Beli</button>
      </div>
    </div>
    <div class="card">
      <div class="card-image"></div>
      <div class="card-body">
        <h3>Product C</h3>
        <p>This product's short description is amazing.</p>
      </div>
      <div class="card-footer">
        <span class="card-price">$35.00</span>
        <button class="btn-buy">Beli</button>
      </div>
    </div>
  </div>
</body>
</html>

Explanation: The card grid uses flex-wrap: wrap so cards move to a new row. flex: 1 1 280px means the card has a minimum of 280px, can grow to fill the available space, and can shrink. The card body uses flex-direction: column to stack the elements vertically.

3. Holy Grail Layout

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    .holy-grail {
      display: flex;
      flex-direction: column;
      min-height: 100vh;
    }

    .hg-header {
      padding: 20px;
      background: #1a1a2e;
      color: white;
      text-align: center;
    }

    .hg-body {
      display: flex;
      flex: 1;
    }

    .hg-sidebar-left {
      width: 200px;
      padding: 20px;
      background: #e2e8f0;
    }

    .hg-main {
      flex: 1;
      padding: 20px;
    }

    .hg-sidebar-right {
      width: 200px;
      padding: 20px;
      background: #e2e8f0;
    }

    .hg-footer {
      padding: 20px;
      background: #1a1a2e;
      color: white;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="holy-grail">
    <header class="hg-header">
      <h1>Header</h1>
    </header>
    <div class="hg-body">
      <aside class="hg-sidebar-left">Left Sidebar</aside>
      <main class="hg-main">Main Content</main>
      <aside class="hg-sidebar-right">Right Sidebar</aside>
    </div>
    <footer class="hg-footer">
      <p>Footer</p>
    </footer>
  </div>
</body>
</html>

Explanation: The main container uses flex-direction: column to stack the header, body, and footer. The body uses flex-direction: row (the default), with the left sidebar at a fixed width of 200px, main with flex: 1 filling the remaining space, and the right sidebar fixed at 200px.

4. Perfect Centering

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    .center-box {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background: linear-gradient(135deg, #667eea, #764ba2);
    }

    .center-content {
      background: white;
      padding: 40px;
      border-radius: 16px;
      text-align: center;
      box-shadow: 0 10px 40px rgba(0,0,0,0.2);
    }
  </style>
</head>
<body>
  <div class="center-box">
    <div class="center-content">
      <h2>Perfectly Centered!</h2>
      <p>Horizontal & Vertical Center</p>
    </div>
  </div>
</body>
</html>

Explanation: Just 3 lines of CSS for perfect centering: display: flex, justify-content: center (horizontal), and align-items: center (vertical). This is one of the biggest advantages of Flexbox.

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    .login-page {
      display: flex;
      flex-direction: column;
      min-height: 100vh;
    }

    .login-form {
      flex: 1;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .form-card {
      width: 400px;
      padding: 30px;
      background: white;
      border-radius: 12px;
      box-shadow: 0 4px 20px rgba(0,0,0,0.1);
    }

    .form-card h2 {
      margin-bottom: 20px;
      text-align: center;
    }

    .form-group {
      margin-bottom: 15px;
    }

    .form-group label {
      display: block;
      margin-bottom: 5px;
      font-weight: 600;
    }

    .form-group input {
      width: 100%;
      padding: 10px;
      border: 2px solid #e2e8f0;
      border-radius: 8px;
      font-size: 16px;
    }

    .form-submit {
      width: 100%;
      padding: 12px;
      background: #667eea;
      color: white;
      border: none;
      border-radius: 8px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      margin-top: 10px;
    }

    .login-footer {
      padding: 20px;
      text-align: center;
      color: #94a3b8;
    }
  </style>
</head>
<body>
  <div class="login-page">
    <form class="login-form">
      <div class="form-card">
        <h2>Log In</h2>
        <div class="form-group">
          <label>Email</label>
          <input type="email" placeholder="[email protected]">
        </div>
        <div class="form-group">
          <label>Password</label>
          <input type="password" placeholder="Enter password">
        </div>
        <button type="submit" class="form-submit">Log In</button>
      </div>
    </form>
    <footer class="login-footer">
      <p>&copy; 2025 MyBrand. All rights reserved.</p>
    </footer>
  </div>
</body>
</html>

Explanation: Uses flex-direction: column on the page container. login-form has flex: 1, so it fills all the remaining space and pushes the footer to the bottom. The form card is centered with justify-content: center and align-items: center on the form wrapper.


Conclusion

Flexbox is the most powerful tool for one-dimensional layouts in CSS. The core concepts include:

  1. Container — display: flex enables Flexbox
  2. Main axis — Controlled by flex-direction and justify-content
  3. Cross axis — Controlled by align-items and align-self
  4. Item sizing — Controlled by flex-grow, flex-shrink, and flex-basis
  5. Order — Controlled by order

Mastering Flexbox will let you solve almost any CSS layout problem more easily and elegantly than with older methods like floats and positioning.