Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Flexing your HTML Layout Muscles with Flexbox


:P
On this page:

This article was originally published in CODE Magazine Issue 2016 Mar/April and has been updated on November 11th, 2017 with additional information


CSS hasn’t changed much since CSS 3 has been released, but the relatively new Flexbox module provides some much needed relief when it comes to creating complex structured layouts in HTML. Flexbox can be considered a much more flexible successor to HTML tables. In this article I’ll introduce the basic concepts of Flexbox and a few practical examples that demonstrate how to put Flexbox to use in your own HTML applications today.

Let’s face it – most of us doing Web development have struggled with multi-column layouts at sometime in our Web development. Any developer new to HTML coming from a desktop based development environment is very likely to comment immediately on the fact how difficult it is to properly create a structured layout in HTML. While it’s always been possible to make layouts behave using various tricks and specialized workarounds, the process has never been easy.

HTML has always been very good for document style layout – that is, creating flowing documents where content stacks on top of the previous content. HTML thrives on flowing content that takes up as much space as is available and reflowing content around embedded floating elements automatically.

On the other hand, creation of structured layouts that display content in confined areas that sit side by side or need to stack in an exact order and location have been much more elusive to achieve with HTML. Trying to create paneled layouts that can stay fixed and/or dynamically resize relative to each other are not trivial to create in HTML.

Technologies to deal with structured layouts have come and gone over the years: Developers have used HTML frames, HTML tables, float based layouts, and more recently various CSS tricks and grid systems popularized by a number of CSS frameworks like Bootstrap, Foundation and Google’s Material Design. While there have always been solutions and hacks to beat HTML into submission, it has never been an easy road as each of these technologies has limitations and requires compromises. Even today, for many Web developers tables are the first and only tool they reach for when a structured layout is required.

It seems we’ve been struggling long enough with various hacks to create complex, structured HTML layouts.

Flexbox to the Rescue

But that’s finally changing. With the advent of the HTML Flexbox model, HTML gains a rich box formatting engine that addresses complex layouts. You can think of Flexbox as HTML tables on steroids, without the styling limitations of tables and the ability to use any HTML semantic tag to create a Flexbox container and child elements. You can apply Flexbox styling to any HTML element which means you can easily restyle and reflow elements independently of each other as there is no fixed container hierarchy as there is in tables.

Flexbox makes it much easier to lay out documents that require multiple columns or need to flow complex layouts around pages by providing many declarative attributes that describe exactly how each container and their children should size themselves, how content should align and wrap, how much and where spacing should be applied to fill space and so on. For example, it’s easy with Flexbox to create a full page layout that stay fixed to the height of the browser window and adjust all panels within the layout when the browser resizes. Likewise, it’s pretty easy to specify that content should be centered either horizontally and vertically or both. Content inside a container can be made to stack on top of the previous element or to flow side by side and you can easily control the wrapping behavior, which makes it much easier to create responsive mobile friendly layouts that can adjust according to screen size.

Much of this was possible before with HTML without Flexbox, but it required a lot of disjointed CSS attributes to find the right invocations. Flexbox creates a new, comprehensive model using a few clearly defined attributes specific to layout tasks that can interact with each other more easily than the old HTML attributes.

Flexbox History

As we are building more and more interactive applications inside of the browser, it is increasingly important to control layout more easily to enable the complex interfaces we now build with HTML. User interface design still is one of the most time intensive operations in Web application development, and anything that makes this process easier is a welcome change. Flexbox provides some much needed relief in this area as it facilitates creating complex layouts more easily using standard semantic HTML element tags.

The HTML Flexbox model is not exactly new. The initial, now outdated spec for Flexbox was released in 2009 followed by another now outdated update and was finally was replaced in 2012 by the current Flexbox specification that is now available in most browsers. It’s still a working draft in the final recommendation stage (see sidebar), but the draft has been fairly stable for a few years now. All evergreen browsers and most reasonably recent mobile browsers now support Flexbox. The big glaring exception is Internet Explorer 9 and older which have no support and Internet Explorer 10 which has partial (but reasonably good and usable) support for Flexbox.

Although decent Flexbox browser support has been available since 2014, it seems that Flexbox really hasn’t hit the developer mainstream yet. It still feels like bleeding edge technology that hasn’t garnered wide adoption yet. This is because it’s relatively new and because Flexbox has a learning curve. The Flexbox CSS syntax is different and to use it you have to understand the basics of how the model and its relationships works. It’s not as simple as slapping a new attribute on a single HTML element and see behavior change. Flexbox deals with layouts and acts on many elements simultaneously and therefore requires some Flexbox styling on each participating element. It’s not rocket science, but there are quite a few CSS attributes to choose from. The terminology for some these attributes and values is somewhat overlapping, so it can be a little overwhelming at first to figure out which attributes to use. But as is often the case with new technology, you end up using a few features over and over again and the few attributes you need to master are easy to remember once you get the basic hang of how they relate to each other.

You’ll be hearing a lot more about Flexbox in the near future. Many of the updated big CSS frameworks coming out soon like Bootstrap 4.0 and Material Design from Google rely heavily on Flexbox to provide their layout features. It’s a good time to get up to speed on how Flexbox works now. Even if you’re not using Flexbox directly some of the frameworks you might use in the future will leverage Flexbox under the covers and understanding how it works will make it easier to interact with these frameworks.

You can think of Flexbox as HTML tables on steroids, without the limitations of table styling and the ability to use any semantic HTML tags.

Getting Started with Flexbox

Flexbox is a CSS based container layout module. One of the big benefits of Flexbox over HTML tables is its ability to use any HTML element to define its containers and elements. You can use div, nav, article or any other built-in or dynamic semantic HTML tag to define your containers and child items.

The key thing to understand about Flexbox is that it’s a container manipulation tool. It defines the overall behavior on the container and then allows element functionality to override some behavior traits of the elements that are under control of the container. Using a handful of flexbox specific attributes, you get a ton of control how the container alignment and flow is managed.

Figure 1 – Flexbox works through containership using a flex container and flex items. Items can control their own sizing and flow characteristics.

Figure 1 demonstrates the containership and some of the more common CSS attributes you’re going to see in a Flexbox layout. The container controls the overall flow of the layout, using attributes like flex-wrap, align-items and justify-content. The layout in Figure 1 is horizontal using flex-direction: row (along the main axis) but Flexbox also supports flex-direction: column layouts that formats a layout vertically (along the cross axis). Using these attributes, you can control many aspects including element sizing, wrapping and fill mode with very little CSS styling that clearly defines the container behavior.

Individual items can control how they fit into the layout and manage their own internal formatting using standard CSS styling. Child items primarily use the flex attribute to determine their Flexbox behavior. The flex attribute is a combination of the flex-grow, flex-shrink and flex-basis attributes. These three attributes determine whether the element can grow or shrink if the value is non-zero. If the value is non-zero and the element can grow or shrink and the value is used as a ration in relation to the other other elements in the container. The flex-basis determines the initial size or auto to use whatever the elements actual size is initially. Using Flexbox it’s trivial to create relatively sized elements that are recalculated on resizing and even as new elements are added to the container. Other item attributes include align-self which overrides the parent’s align-items setting and order which lets you explicitly control the location of an element in the container’s child collection. These are very useful if you programmatically insert and manage elements dynamically.

Flex containers can be nested so you can create a top level container that vertically manages elements, then use a child container to set up a horizontal flex container inside one of the child containers. A common example of this is a fixed window layout where you have a top level container that manages the full height of the browser window with header, content, footer. The content area can then have a horizontal Flexbox layout that contains multiple panes for a nav sidebar, content and ad sidebar. We’ll look at an example of this later in this article.

Unlike HTML tables, Flexbox can use any semantic HTML element for the container or child elements

The Flex Container

The flex container starts off the Flexbox hierarchy using display:flex attribute. This changes the display mode and tells the container and immediate child elements that they are using Flexbox layout formatting. The flex-direction attribute controls the horizontal (row) or vertical (column) flow of the child elements. The default is row and can be omitted for horizontal layouts. You can also specify the fill characteristics via the align-item and align-content which define the positioning via fill or spacing respectively, the flex-wrap attribute that controls wrapping behavior or elements. In combination these attributes give you a lot of control over how the container renders its child elements.

To demonstrate here’s a simple example of a full-width horizontal container using some very simple HTML:

<div class="panel-container">
    <nav class="panel-left">
        left
    </nav>

    <div class="splitter">
         splitter
    </div>

    <article class="panel-right">
        right
    </article>
</div>

To define a top level container you can do something like this (all but the first attribute are optional):

.panel-container {
    display: flex;
    flex-direction: row;
  
    justify-content: space-around;
    flex-wrap: nowrap;
    align-items: stretch;
}

Flex Elements

Once you have a container you can customize how the contained elements behave inside of that container primarily using the flex attribute.

To demonstrate I’m using three horizontal panels that have two fixed width panels and one auto-resizing panel:

.panel-left {
    flex: none;  /* manual resize */
    width: 300px;
}
.splitter {
    flex: none; /* manual resize */
    width: 18px;
}
.panel-right {
    flex: 1; /* resizable */
}

The most important attribute is the flex attribute is a shorthand for flex-grow, flex-shrink and flex-basis. The first two are numeric values that represent relative sizes of all the child elements. 0 means the size is fixed and shouldn’t shrink or grow respectively. Any number greater than 0 means the element can grow or shrink relative to the other elements’ grow and shrink values. The most common values are 0 0 auto which specifies to keep the size fixed, or 1 1 auto (which is also the default if not provided) which specifies the element will auto size itself to fill available space. When using auto for the flex-basis, the element uses the existing size as its basis, so if you have a fixed width for the element that is used as the base value.

If you want to express a relationship without explicit width (or height) you can also use relative numbers that establish a ratio relationship between the elements:

.panel-left {
  flex: 2 2 auto; /*  resizable */
}

.splitter {
  flex: none; /* fixed */          
  width: 40px;
}

.panel-right {
  flex: 4 4 auto; /* resizable 2x left */
}

This makes the left panel (2) half the size of the right panel (4), and the splitter panel half the size of the left panel (1). As you resize the container that relationship stays intact. This is similar to using percentages in table layouts except that Flexbox can recalculate the ratios even if new elements are added to the layout. Figure 2 shows how this relationship renders in the browser when another .splitter and .panel-right elements are added to the initial layout. You can check it out online at: http://codepen.io/rstrahl/pen/adJPeQ.

Figure 2 – Using relative sizing in the flex property keeps elements sized relatively to each other as you resize the browser window and even if you add new elements dynamically.

Although relative sizing like this is very powerful, you can also use specifically sized layouts where some elements stay fixed and others automatically stretch or shrink to the accommodate the new size of the container. Using flex: 0 0 auto specifies that the element should stay fixed in size while flex: 1 1 auto will resize. This is very common for layouts that have a single expanding element or that are using things like splitters that let a user resize panels.

Vertical Layouts

One of the most difficult layout issues to deal with in HTML consistently, even in modern browsers, is to build a UI that automatically stretches to fill the entire browser window and stays properly sized as you resize the document. The age old problem with vertical sizing in the browser is that HTML has to know the actual size of the window from the top level container (body/html) all the way down into the child elements. Flexbox makes this process much easier.

To create a vertical layout you can use the flex-direction: column on the container, and then layer the elements to fill the height of the container. Using the exact same layout as in Figure 2 and simply switching the flex-direction:column results in a stacked layout displayed in Figure 3. You can also check out the Codepen at: http://codepen.io/rstrahl/pen/NxjxRW.

Figure 3 – Creating a vertical layout that fills a container is as simple as using flex-direction:column.

As in the horizontal layout, the vertical panels now fill the height of the container to its maximum size using the ratios specified by in the flex attribute.

To create full window height layouts that fill the entire browser window and resize to fill the entire content area, you have to ensure that the html,body elements as well as the top level flex container that wraps the entire page, have a height:100% set in their CSS:

html,body {
    height: 100%;
    overflow: hidden;
}
.flex-container {
    display: flex;
    flex-direction: column;
    height: 100%;          
    overflow: auto;          
}

This ensures the content of the items fills the entire window. Note the overflow:auto in the .flex-container, which works around an odd gotcha I ran into with FireFox. FireFox requires overflow:auto in order to keep the panels constrained to the panel height, even though overflow:auto should be the default setting. All other browsers seem to work without this. I’ve found in a few instances where explicit overflow settings are required so I’ve taken to being very explicit with my overflow settings in flex containers.

Vertical and Horizontal Content Centering

Another common difficulty in HTML is vertical centering of elements in a container. While there is a vertical-align property in CSS, this property applies only to table-cells and inline elements. It has no effect on any other container elements.

Flexbox provides a simple solution using align-items. There are several ways to express this:

.panel-right {
    display: flex;
    align-items: center;
}

This implies flex-direction:row as that’s the default. If all you’re after is centering this is the least CSS code you can use**.** This might be counter intuitive because the flex-direction is horizontal while align-items works on the vertical direction. This is exactly the behavior of align-items, which aligns items on the perpendicular axis.

Another slightly more verbose but maybe more obvious way to express this same vertical centering is to use justify-content which aligns content on the active flex-direction:

.panel-right {
    display: flex; 
    flex-direction: column;                    
    justify-content: center;          
}

Both have the same effect of vertical centering the content but it’s easier to see that centering is occurring on the column axis. To summarize: justify-content works on the current flex-direction axis, align-items works on the perpendicular/alternate axis. Hooray for bad naming conventions.

The reason both of these exist is so that you can combine them to center both vertically and horizontally. The following does just that:

.panel-right {
    display: flex; 
    flex-direction: column;                    
    justify-content: center;          
}

Applied to the .panel-right style in the previous example Figure 4 shows what the centered content looks like.

Figure 4 – Centering content inside of an element can be easily done with justify-content and align-items on any flex container.

#PAGEBREAK

At this point we’ve seen most of the Flexbox attributes used, but keep in mind there are many more combinations of these attributes that you can apply. You can control wrapping behavior, fill behavior between elements, whether elements stretch and fill or simply leave space at the beginning or end – the combinations are endless.

As a summary and for a better idea of all the options available using Flexbox syntax here’s a table that shows the Flexbox related attributes grouped by container and child elements.

Flexbox Container Attributes

Attribute Function
display: flex

Top level attribute that enables Flexbox formatting on the container it is applied to.

display:flex

flex-direction

Determines horizontal (row) or vertical (column) flow direction elements in the container.

row,column

flex-wrap

Determines how content wraps when the content overflows the container.

wrap, nowrap, wrap-reverse

flex-flow

Combination of flex-direction and flex-wrap as a single attribute.

flex-flow: row nowrap

justify-content

Aligns content along the flex flow direction.

flex-start, flex-end, center, space-between, space-around

align-items

Like align-content but aligns content along the perpendicular axis.

flex-start, flex-end, center, stretch, baseline

align-content

Aligns multi-line content so that multiple lines of content line up when wrapping.

flex-start, flex-end, center, space-between, space-around, stretch

Attribute Function
flex

Combination of flex-grow, flex-shrink and flex-basis rolled into a single attribute.

Examples: 1 1 auto, 0 0 auto, 0 0 200px

flex-shrink
flex-grow

Numeric value that determines how a child element should grow or shrink. 0 means fixed size, a numeric value is used in relation to other numeric values on other sibling elements in the container.

0 – fixed size, number – relative sizing to other flex items in container

flex-basis

The initial size of the element and the basis on which sizing is based

auto – uses size of element from width, pixel size – fixed size to apply

align-self

Sets the alignment for the element explicitly overriding the value set by align-items on the container.

auto, flex-start, flex-end, center, baseline, stretch

order

Sets the rendering order of the element inside of the container in ascending order

numeric value

A Practical Example – Full Page Panel Layout

To provide a comprehensive and practical example, let’s create a full page layout that includes a number of nested Flexbox containers. Figure 5 shows a five panel layout that contains a header, a sidebar, main content area, an ad bar and a footer.

Figure 5 – An example of a multi-pane layout that uses multiple nested Flexbox containers.

Here's the code or you can play with the code on CodePen.

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" 
          content="width=device-width, initial-scale=1">
    <style>
        html, body {
            height: 100%;
            padding: 0;
            margin: 0;
        }        
        .flex-master {
            display: flex;
            flex-direction: column;
            flex-wrap: nowrap;

            height: 100%;
            overflow: auto;
        }
        .page-header {
            flex: none; /* fixed size */
  
            padding: 15px;
            font-size: 3em;
            font-weight: bold;            
            background: #535353;
            color: white;            
        }
        .page-content {
            flex: 1;   /* resize in container */
            overflow: auto; /* IMPORTANT for FireFox */
            
            /* new flex container for content */
            display: flex;
            flex-direction: row;                        
        }
        .sidebar-left {
            flex: none;
            background: #838383;

            padding: 20px;
            width: 200px;
            overflow: auto;
            color: white;
        }

        .splitter {
            flex: none;
            width: 17px;
            cursor: col-resize;
            background: #535353;
        }
        .content-container {
            flex: 1 1 auto;
            background: #eee;
            padding: 20px;
            width: 100%;
            overflow-y: auto;

            display: flex; /* new flex for content/ads*/
            flex-direction: row;
        }
        .main-content {
            flex: 1 1 auto; 

            width: 100%;
            padding: 10px;
        }
        .page-ads {
            flex: 0 0 auto;
            width: 180px;
            overflow: hidden;

            display: flex; /* new flex for ads */
            flex-direction: column;
        }
        .ad {
            flex: none;
            align-self: center;
            padding: 5px;
            margin: 15px;
            width: 150px;
            height: 150px;
            background: lightblue;
            overflow: hidden;

            /* center ad text */
            display: flex;
            justify-content: center;
            align-items: center;
        }

        footer {
            flex: 0 0 auto;
            background: #535353;
            color: white;
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="flex-master">
        <header class="page-header">
            This is a header
        </header>

        <div class="page-content">
            <nav class="sidebar-left">
                <h3>Sidebar</h3>
                <ul>
                    <li>Item 1</li>
                    <li>Item 2</li>
                </ul>
            </nav>
            <div class="splitter">
            </div>
            <div class="content-container">
                <article class="main-content">
                    This is my main content!
                    <hr />
                    This is my main content!
                    <hr />  …
                </article>
                <aside class="page-ads">
                    <div class="ad">
                        Ad
                    </div>
                    <div class="ad">
                        Ad
                    </div>  …
                 </aside>
            </div>
        </div>

        <footer>
            <small>&copy West Wind Technologies, 2016</small>
        </footer>
    </div>
</body>
</html>

Full page layouts like this that maintain their full size in the browser are becoming more common as we are building more complex applications in the browser. Applications, rather than content pages often require a more fixed layout so that you can find and navigate content more easily.

The layout contains a number of nested containers:

  • Top level page container (.flex-master)
  • Contains header, .page-content and footer
  • .page-content is a new horizontal container
  • Contains .sidebar-left, .content-container
  • .content-container contains .main-content and .page-ads
  • .page-ads contains indivual ads

That’s quite a bit of container nesting that breaks down each page section into smaller and smaller containers. Flexbox makes this relatively easy as any child element can also act as a new Flexbox container to its contained elements. If you’ve used WPF in .NET and the various panel containers this approach should look very familiar.

One of the key features of this layout is that it remains fixed to the full window size, so as you resize the window the footer stays at the bottom and the content in the middle grows or shrinks to match the height of the browser. As mentioned earlier the html,body styles are marked for height:100% to ensure that the various containers can calculate the total page size. The top level .flex-master also sets its height:100% to fill out the entire height of the window. From there on Flexbox’s relative or stretch sizing can fill out the window height.

It’s important to think about the overflow characteristics for each container and due to the funky FireFox I mentioned earlier, it’s a good idea to explicitly specify how you’d like to have the overflow handled in each container. For the top level container overflow should be hidden because we don’t want to ever see a scrollbar on the document and content really shouldn’t be overflowing anyway. The main content container also shouldn’t have any overflow as it should fill the width of the browser and the height between footer and header, but each of the contained panels with the sidebar and main content should have overflow to scroll the container for height and width.

The CSS for all of this is a bit verbose, but the HTML for the containers and elements remains very compact and readable. While it will never be really trivial to create multiple nested containers to create full page layouts, Flexbox makes this a lot easier than it would be using traditional CSS styling.

Bonus: Adding Panel Resizing

While this has nothing to do with Flexbox, wouldn’t it be nice if you could easily resize the sidebar and main panels using splitter like behavior? It turns out there’s an easy way to add this functionality using the jquery-resizable plug-in I created recently. This very small jquery plug-in allows resizing of containers and makes it trivial to create a resizable panel:

<script src="src/jquery.min.js"></script>    
<script src="src/jquery-resizable.js"></script>
<script>
    $(".sidebar-left").resizable({
        handleSelector: ".splitter",
        resizeHeight: false
    });
</script>

And voila – you can now drag the black separator in Figure 5 to resize the left and right panels, which makes a nice addition to a paneled layout.

Form Layouts

Another pain point in HTML is form layout. One of the big draws of the Bootstrap framework is its grid system, which provides responsive form formatting and a semblance of multi-column form layouts. Flexbox can replace much of what the grid system does with a small amount of CSS just by using a Flexbox container around the individual form items. The result looks similar to the HTML that you would write with Bootstrap, but you actually get a lot more control over the elements because you’re not actually constrained by specific grid sizes. You can get automatic resizing of elements, but if you choose you can also give specific sizing hints to size each grid column to a specific relative value that is automatically recalculated by the Flexbox when the page or container is resized.

Figure 6 shows an example of a very simple input form that uses Flexbox.

Figure 6 – An example of an input form built with Flexbox formatting can easily be made responsive.

Here's the code or you can play with the code on CodePen.

<style>
.form-group {
    display: flex;
    flex-direction: row;
}

.form-group label {
    flex: none;
    display: block;
    width: 125px;
    font-weight: bold;
    font-size: 1em;
}
.form-group label.right-inline {
    text-align: right;
    padding-right: 8px;
    padding-left: 10px;
    width: auto;
}
.form-group .input-control {
    flex: 1 1 auto;
    display: block;
    margin-bottom: 10px;
    margin-right: 8px;
    padding: 4px;
    margin-top: -4px;
}
button {
    padding: 5px 15px;
    margin: 5px;
    min-width: 100px
}

@media (max-width: 768px) {
    .form-group {
        flex-direction: column;
    }
    .form-group .input-control {
        margin-top: 2px;
    }
    .form-group label.right-inline {
        text-align: left;
        padding-right: 0;
        padding-left: 0;
    }
}
</style>

<div class="form-group">
    <label>First Name</label>
    <input value="Rick" class="input-control" />

    <label class="right-inline">Last Name</label>
    <input value="Strahl" class="input-control" />
</div>

<div class="form-group">
    <label>Company</label>
    <input value="West Wind" class="input-control" />
</div>

<div class="form-group">
    <label>Address</label>
    <textarea class="input-control">32 North End</textarea>
</div>

<div class="form-group">
    <label>City,State,Zip</label>
    <input value="Walnut Creek" class="input-control" placeholder="City" style="flex: 6" />
    <input value="CA" class="input-control" 
           placeholder="State" style="flex:1" />
    <input value="94152" class="input-control" 
           placeholder="Postal Code" style="flex:2" />
</div>

<div class="form-group">
    <label>&nbsp;</label>
    <button>Save</button>
    <button>Cancel</button>
</div>

The key feature in this layout is that each ‘row’ is wrapped in a container item very much like you would do in Bootstrap:

<div class="form-group">
    <label>Company</label>
    <input value="West Wind" 
           class="input-control" />
</div>

You can then use some relatively simple styling to get the elements to line up in each row:

.form-group {
        display: flex;
        flex-direction: row;
    }
    .form-group label {
        flex: 0;
        display: block;
        width: 125px;
    }
    .form-group .input-control {
        flex: 1;
        display: block;
        margin-bottom: 10px;
    }

This simple CSS allows for the full row styling you see on the left. What’s nice about this is that this existing layout works even will additional items the list. For example, the city/state/zip row automatically sizes multiple input boxes using relative sizing:

<div class="form-group">
    <label>City/State/Zip</label>
    <input value="Clayton" 
           class="input-control" 
           style="flex: 6" />
    <input value="CA" class="input-control"
           style="flex: 1" />
    <input value="94152" 
           class="input-control" 
           style="flex: 2" />
</div>

The textboxes automatically stay relatively sized in the flex container as you resize the container.

Flexbox and Responsive Design

One big advantage that Flexbox has over HTML tables is that you can apply Flexbox styling to any HTML element so you are not limited to the strict structure that HTML tables must adhere to. Because of this it’s much easier to restyle Flexbox containers and elements using media queries and other responsive techniques.

Flexbox is just a styling mechanism which means you can add and remove it at will, and because you change the flow direction easily it’s almost trivial to go from a horizontal layout out a large display to vertical layout just by switching the flex-direction. Often just switch from flex-direction:row for wide screens to flex-direction:column for small screens.

For example in the form example in the previous section you can add a media query and simply flip the direction like this:

@media (max-width: 768px) {
    .form-group {
        flex-direction: column;
    }
}

This has the effect that the form jumps to the display on the right that you see in Figure 6, which is a single column layout.

While it’s not always going to be quite so easy to rearrange content for different sizes, Flexbox gives you a lot of control via CSS to restyle content and automatically reflow content for responsive layouts.

FlexBox makes it much easier to create responsive designs as you can easily redefine how elements flow in a flex container.

Flexbox and Browser Support

Flexbox is relatively new in HTML and as such works primarily in newer browsers. All the evergreen browsers (Chrome, FireFox, Edge and Opera and most mobile browsers) support Flexbox in the current version.

You can check browser support for Flexbox here:

http://caniuse.com/#feat=Flexbox

The big issue here that Internet Explorer only supports Flexbox in Version 10 and greater and then only supports an older version of it although I found it to work well with all the content described in this article. Luckily IE 9 and earlier market share is rapidly dropping off and many JavaScript and CSS frameworks now actively have stopped supporting these old IE versions in an attempt to drive out these ancient and standards hostile browsers.

Flexbox and WC3 Standards

Flexbox’s proper standards name is CSS Flexible Box Layout Module Level 1 and it’s in the Last Call stage of the standards approval process. This means, it’s not an official WC3 standard yet, but the spec has been stable for the last couple of years with only very minor updates and adjustments since the 2012 update. You can review the current standards document at:

Summary

Now that you’ve seen some of the features that Flexbox brings to the table for HTML layout, I think you’ll agree that it’s pretty exciting to see these enhancements come to HTML and CSS design. Flexbox is a very welcome addition to HTML that provides a sorely missing structured layout engine that makes it easier to compose complex HTML layouts more easily than it has been. HTML has suffered long enough from hacks and workarounds to build multi-column layouts that are adaptable and can take advantage of responsive design when the browser resizes.

While Flexbox technology is still relatively new and hasn’t been adopted widely yet, all major browsers have Flexbox support with the exception of IE 9 and older. Flexbox is in the Last Call stage of ratification as a W3C standard, so it’s unlikely there will be any major changes to this spec. A number of big frameworks are betting big on Flexbox including the forthcoming BootStrap 4.0 and Google’s Material Design which are based on Flexbox concepts.

If you haven’t checked out Flexbox before, or you have and initially dismissed it as too different or because not yet widely adopted, it’s time to give it another good look. You won’t regret it for the time you save in your HTML layout...

Resources

  • A complete guide to Flexbox
    A great reference to the available Flexbox styles and values you can use along with a graphical representation.

  • MDN FlexBoxDocumentation
    As usual Mozilla has good official documentation on the various Flexbox attributes that’s easy to use as a reference where all flex related attributes are linked.

  • FlexBox Froggy Game
    An interactive game that teaches the concepts of Flexbox in a fun and very interactive way. If you've never played with Flexbox and even if you have but can't remember the unintuitive flexbox attributes, this game can get you up to speed. Recommended!

this post created and published with Markdown Monster
Posted in HTML  

The Voices of Reason


 

Shail
January 16, 2019

# re: Flexing your HTML Layout Muscles with Flexbox

Awesome article, Rick! Very lucid! Cleared most of my doubts about Flex, and the examples went a long way in my understanding too.

I think you just might want to take a look at the sentence below and rectify it:

If the value is non-zero and the element can grow or shrink and the value is used as a ration in relation to the other other elements in the container.

It appears in the second para just after Figure 1 that talks about individual Flex item attributes.

Shail


Brent
March 29, 2019

# re: Flexing your HTML Layout Muscles with Flexbox

This is a really great article. It has good examples and help me to jump right in and start using it. Thanks!


Frank
June 06, 2019

# re: Flexing your HTML Layout Muscles with Flexbox

Nice work Rick

This is excellent and the re-size plugin is most excellent too. I used Frames in the past and that was excellent too but now its frowned upon. So when I found your sample I was , well my searched ended.

I tried to add another splitter and column to resize the middle a three column page with the first two resize-able. This kind of worked.

It appears that the resizing is tied to to the first column. Am I doing something wrong? Is this possible with out changing jquery-resizable.js. I am not an expert.

I would like for the re-sizing to change the widths of the column on the left and right(s). Anyway thanks for sharing. FxM


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024