By Dan Rose

Responsive, Fluid-Width, Variable-Item Navigation with CSS

By Dan Rose

Around six months ago I was asked to develop a single row navigation bar that could contain a variable number of menu items while filling the entire width of the container. The amount of navigational items was dictated elsewhere and likely to change in future.

Thinking ahead, it would have been impractical to change the CSS every time a menu item was added or removed. A resolution had to be found, ideally without using JavaScript.

Using Percentage Widths

Fixed widths are unable to consistently fill the responsive container, as the below image illustrates.

Fixed-width nav example

So we need to use percentages to accomplish this. Percentages are the prevalent method to achieve a fluid grid layout in responsive designs and will come in useful here.

For example, take the below familiar HTML into consideration:

    <li><a href="home.html">Home</a></li>
    <li><a href="about.html">About</a></li>
    <li><a href="services.html">Services</a></li>
    <li><a href="products.html">Products</a></li>
    <li><a href="jobs.html">Jobs</a></li>
    <li><a href="contact.html">Contact</a></li>

And we’ll add the following CSS:

nav {
    width: 100%;
    background: #f0f0f0;
    border: 1px solid #ccc;
    border-right: none;

nav ul {
    overflow: hidden;
    margin: 0;
    padding: 0;

nav ul li {
    list-style: none;
    float: left;
    text-align: center;
    border-left: 1px solid #fff;
    border-right: 1px solid #ccc;
    width: 16.6667%; /* fallback for non-calc() browsers */
    width: calc(100% / 6);
    box-sizing: border-box;

nav ul li:first-child {
    border-left: none;

nav ul li a {
    display: block;
    text-decoration: none;
    color: #616161;
    padding: 10px 0;

Areas of note are:

  • The <nav> element is given width: 100% to fill the entire available space.
  • <li> elements are supplied with two width properties – width: calc(100% / 6); and width: 16.6667%;. This is where the menu items are divided across the <nav> element into 6 equal widths. The order these properties are listed is important to allow browsers that support calc() to utilize it over the standard percentage width. Browsers without support for calc() will simply ignore it and use the fallback. I tend to use calc() with percentages to assist in readability and to allow the browser to use the result it is optimized for. That way I don’t have to worry about whether to include recurring decimal places.
  • box-sizing: border-box; is declared on the <li> elements. This forces the width property to include the border-left and border-right values in the total width. Without using this property, the <li> elements wouldn’t fit within the <nav> area and the last <li> element would wrap onto a new line. Many prefer to set box-sizing: border-box; to all elements in order to easily manage widths, as Paul Irish suggests.

The result of adding these styles is shown in the CodePen demo below:

See the Pen Fixed-width Fluid Navigation by SitePoint (@SitePoint) on CodePen.

Open it in a new window and test it out for responsiveness. The desired look is achieved and it’s flexible.

What if We Add or Remove Items?

Here’s what happens if we remove one item from the navigation, with our current CSS in place:

See the Pen Fluid-width by SitePoint (@SitePoint) on CodePen.

As you can see, there is an empty area on the right, where the last nav item was.

How about when an extra nav item is added?

See the Pen Fluid-width Navigation, One Extra Item by SitePoint (@SitePoint) on CodePen.

Now the last navigation item wraps onto a second row.

Clearly, this doesn’t satisfy all our requirements. JavaScript could be used to count the number of menu items, work out the percentage and apply width values by looping through the <li> elements. However, I am always reluctant to use JavaScript to define layout unless there’s no other option. Plus, this wouldn’t be a CSS article if I was going to describe how to do that! Back to the drawing board, it is…

(Re)introducing the Table Layout

Fear not, I am not advocating the use of a 90s throwback HTML table for layout; that would be semantically incorrect, of course. However, there are display values that allow elements to act like a table.

This means that the earlier HTML structure can still be used with the following CSS:

nav {
    display: table;
    table-layout: fixed;
    width: 100%;

nav ul {
    display: table-row;
    margin: 0;
    padding: 0;

nav ul li {
    list-style: none;
    display: table-cell;
    text-align: center;

nav ul li a {
    display: block;

Setting the display property allows the <nav> element to act as the table, the <ul> as the row and the <li> as the table cell. Note the inclusion of the table-layout: fixed declaration, which applies an equal width to each menu item. This can be removed, but fluctuating lengths of text can cause the table to look off balance, so approach with caution.

Here’s a demo, with buttons to let you add/remove items:

See the Pen Fluid-width Navigation Using display: table by SitePoint (@SitePoint) on CodePen.

This may not be the cleanest approach (apologies to the table haters), but it works and it’s simple. Browser support is good too.

The Future: Flexbox

Flexbox is the standout candidate to replace this method going forward, as the older versions of Internet Explorer are phased out and browser support for flexbox continues to improve. If you are unfamiliar with flexbox, you can check out this recent article on SitePoint or visit the spec, which explains it as follows:

In the flex layout model, the children of a flex container can be laid out in any direction, and can “flex” their sizes, either growing to fill unused space or shrinking to avoid overflowing the parent. Both horizontal and vertical alignment of the children can be easily manipulated.

Sounds ideal to resolve my problem.

Again, using the earlier HTML, here is the CSS to construct the flexbox approach to solving this problem:

nav {
    width: 100%;

nav ul {
    display: flex;
    flex-direction: row;
    margin: 0;
    padding: 0;

nav ul li {
    list-style: none;
    flex-grow: 1;
    text-align: center;

nav ul li a {
    display: block;

The flexbox properties to note are:

  • display: flex; This is applied to the <ul> element and enables a flex environment for its children.
  • flex-direction: row; is assigned to the <ul> to position it’s children in a left to right format. This is the default value so it isn’t explicitly necessary.
  • flex-grow: 1; is the magic that equally spreads the <li> elements across the container. If you were to give a specific <li> a value of 2, that element would grow to twice the size of the others.

Flexbox has some interesting features that may be appropriate in other use cases, such as the ability to reorder menu items by declaring the order property.

Here’s our final demo using Flexbox:

See the Pen Fluid-width Navigation Using Flexbox by SitePoint (@SitePoint) on CodePen.

As you can see in the above CodePen demo, the same result is achieved. Again, you can use the buttons to test out adding or removing a single item. You can also add more items by editing the HTML. And by resizing your browser window you can see it’s fluidity.

If you’ve ever had to solve this issue, let us know how you accomplished it and what technique you used.

  • Steve

    The text turns into mush when it’s narrowed down to a handheld device. Clearly it’s for desktop/tablet use, unless text is replaced with icons.

  • LouisLazaris

    Yeah, and probably “responsive” is not the best choice for the title, that was my addition. But there are very easy ways to get it working on handheld devices.

    The main idea here was to get it working fluid, at full-width. Maybe I’ll adjust the demos to include a media query that drops the items vertically or something, but I’m sure anyone can solve that problem without extra help. Or use a hamburger icon or whatever.

    • Kevdev

      Louis, with all due respect – you folks at Sitepoint are great – the misuse of the word ‘responsive’ is one of my pet peeves.

      Responsive means that it responds well _to_your_actions; like responsive acceleration in a car or like a ‘peppy’ web site that is not slow when you click around in it.

      Responsive does not mean that the page has the ability to resize itself for a smartphone. Yes, I know it was probably first used to say that the ‘page responds well to all device screen sizes’. But without that specific context, ‘responsive’ could be about any characteristic of your browsing device (processor type, memory size, outside temperature …) and we would just have to guess what they are referring to.

      That is why when I read the title to this article, I was not even thinking about screen size at all.

      Sorry to get off topic … I, I, I just couldn’t hold it back any longer … :)

      • LouisLazaris

        Point noted, but I kind of disagree on your definition of “responsive”. Because if that’s the case, then the entire community is wrong about the way they use the word.

        “Responsive” is in fact in reference to how the page responds to the various device and window sizes, not to the way the user responds.

        All that being said, however, I agree, the community is using that word wrong, and probably “Adaptive” should be the word to describe this (which it often is).

        • Kevdev

          ‘Adaptive’ is great – it describes it so much better!

          And yes, that was my point – the entire community IS wrong about the way they use the word ‘responsive’. Perhaps with Sitepoint’s powerful presence you can sway everyone into using ‘adaptive’.


          • LouisLazaris

            I agree, but unfortunately, we’re stuck with the term ‘responsive’. For example, one of our recent articles discussed the difference between RWD and “adaptive”:


            And there is a well known book on the topic of adaptive design, but I don’t know what that one discusses as far as details.

            I’m not too concerned about terminology, except in one area: What it means to clients, which can be confusing to them. And Craig Buckler discussed that problem here:


            Anyhow, thanks for the feedback!

          • Junk

            No, the community is not “wrong.” Per your definition, “responsive” is a perfectly suitable word. It is simply, for a very pedantic person or a person who is not a web user interface developer, not the most specific choice.

            “Adaptive” would have the exact same problems. What’s adapting? The processor use? The screen brightness? The width of elements?

            Plus, “adaptive” is used to describe a different set of techniques with which a developer can achieve the goal of cross-platform web sites and applications. So, that would be confusing.

            In most–maybe all–industries and communities there is jargon. Responsive is web development jargon for a VERY SPECIFIC thing. Learning the jargon of your industry is part of your job.

  • Ralph Mason

    Useful article. As an aside, though “apologies to the table haters”? It’s HTML table layout that people might object to, but that’s completely different from CSS `display: table`.

    • Dan Rose

      Thanks for your feedback. I agree that it is HTML table layouts that are met with some level of indignation. My comment was merely an attempt to add some light humor to the table subject. As I pointed out, by using the CSS display properties you are avoiding use of the incorrect HTML semantics of a table structure for a navigation area. Of course it is still necessary to apply CSS properties to the different elements to adopt that tabular behavior.

      • Ralph Mason

        No worries, Louis and Dan. I hope I didn’t sound critical. Maybe the problem is in calling them “CSS tables” … although I guess it’s an accurate description. But display: table is very handy in a lot of situations, so I like to talk it up a bit. :) Can’t wait for display: flex to take off, though.

    • LouisLazaris

      That’s true, Ralph, but many people feel that if you use table layout via CSS, then you might as well use regular tables. It’s kind of a purist thing, and that’s probably what Dan was referring to, and why I left the comment in when editing this article. In other words, some people feel there is no difference between the two, but that’s not really the case (for semantics and accessibility reasons, to name a few).

  • What do you think of using Modernizr to test for flexbox and if it is not supported fall back to table display? Or is it just useless and we shall drop table properties and go straight for flexbox?

    .flexbox nav { display: flex; } …

    .no-flexbox nav { display: table; }

    • Guest

      Funnily enough I talked about using Modernizr for that exact purpose on my first draft for this article. It is something I would definitely do if I was building the nav now and when time permits something I’ll add on the live site this appears on. I believe there is already a discussion on Sitepoint about whether we are ready for Flexbox now – It’s still very much up for debate but in my use case browser support demanded the tabular approach. Having said that, it can only be a good thing to plan for the future too.

    • Dan Rose

      Funnily enough, in my first draft I touched upon using Modernizr for that exact purpose. In my use case browser support demanded the need for the tabular approach. Having said that, planning for the future can only be a good thing which is what Modernizr allows us to do. If I was to create a similar navigation bar right now, personally I would use Modernizr to provide both approaches. I think that because navigation is such a crucial component of a website it is a necessity to at least do the tabular approach though. There is an article on SitePoint that discusses whether we’re ready for Flexbox now which you may like to read (I tried to link to it previously but it didn’t pass moderation). It’s still open to interpretation and it largely depends on the browsers you need to support.

      • I found the article you are mentioning, thanks for pointing that.
        I think that it is as you stated, it’s subjected to the browsers we want to support.

    • George Gooding

      Haven’t double-checked, but I think you can just declare the table-based CSS values on display first, and then flex after, which should result in browsers that don’t understand flex box to hang on to the display table values? Even if you set display: table-cell on the “cells”, that will be ignored if the browser understands flex box and sets the container to flex. I think. Please double check! :)

      • Great idea. definitely worth to check

  • Thanks for sharing, great article

  • Theracoon

    I switched our sites to the table layout method a few years ago because people kept adding and removing links to our top nav and I had to keep updating our CSS to match which was very annoying. Another method I used in a few places when I have to have even width blocks involves counting child elements using the last-child selector.

    nav li {display: inline-block; font-size: 0; box-sizing: border-box;
    & a {font-size: 13px;}
    &:first-child:nth-last-child(5) ~ li {width: 20%;}
    &:first-child:nth-last-child(4) ~ li {width: 25%;}
    &:first-child:nth-last-child(3) ~ li {width: 33.3%;}
    &:first-child:nth-last-child(2) ~ li {width: 50%;}
    &:first-child:nth-last-child(1) ~ li {width: 100%;}

  • George Gooding

    What about using flex wrap? Then you can stack the menu vertically, if that’s OK.

  • Your post help me a lot today keep up the good work.

  • Riccardo Zanutta

    What if the navbar has a fixed width?
    You have to remove width: 100% but layout breaks.

  • Louis

    Nice article.

    There is one thing I am really keen to understand but it is not included in the article though. The flexbox items will automatically have variable width based on the the length of text it contains. See the with text “Jobs” is actually smaller than the one with “products”. While in the table layout example, every share exactly the same width regardless how much text they contain.

    The variable width feature is really useful. It is certainly another big advantage over the use of table layout. However, I do not understand how this has happened. Since every is given flex-grow: 1, they should have the same width according to the definition and explanation you have given in the article. I noticed this feature and loved it but I would like to fully understand why it is working this way.


  • Paweł Garnek

    thanx for reciepe.

    But in this example every item of menu has same width…
    My problem is, in my menu 2 items have width grater than default width, and it looks terrible.

    I don’t want to have constant width of every item (left and right margin differs on each one).
    I want to have same, constant left and right margin for every-different-width item.

    Have You solution for that?
    It takes me some time trying to do that, but i didn’t find the proper way to solve it…

  • will

    if you set the table to “auto” in place of fixed, each li item will be auto sized.

  • Sekhar

    Hi Rose, Thanks for good article. I have a certain requirement but I have curved shapes in my navbar. How to start with this requirement for managing different size of screens or while doing landscape or portrait.

    Please check the following link,

    in this you can find the HTC phone having phone symbol & “+” symbol and one more symbol in a curved fashion. The same kind of curved manner I need to implement in Jquery mobile.
    Please help me in the same.
    Thanks in the advance.

  • Juan Pablo Cuellar

    Very nice article. I try to avoid using tables for my web pages. Only use it when I have to. But for designing purposes css alone should be used. However the only thing missing perhaps it was missed on purpose was to have a dropdown when running on mobile to click it to open and close. I work for a fulfillment company when we converted our web pages to be responsive. We had to re-format a lot of code. I read that starting mobile first was the way to go. But I opted for my starting point to be desktop then tablet then mobile. Do you think it will be worth to make the approach as mobile first for my company?


    Juan Pablo

  • Dragomir Vasile Georgiana Lari

    Thank you for this article.

  • Jijesh

    really useful.

  • Carlos

    Thank You!

  • Raj

    Looks like CSS tables are not good for creating navigation menus (having nested menus) as shown here:

Get the latest in Front-end, once a week, for free.