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

Dan Rose
Dan Rose
Share

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:

<nav>
  <ul>
    <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>
  </ul>
</nav>

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.

Frequently Asked Questions on Responsive Fluid Width Variable Item Navigation CSS

What is the significance of using Responsive Fluid Width Variable Item Navigation CSS?

Responsive Fluid Width Variable Item Navigation CSS is a crucial tool in web design. It allows for the creation of navigation bars that are flexible and adapt to different screen sizes. This is particularly important in today’s digital age where users access websites from a variety of devices, including desktops, laptops, tablets, and smartphones. By using this CSS technique, you ensure that your website’s navigation is user-friendly and accessible, regardless of the device used.

How can I create a responsive navigation bar using CSS?

Creating a responsive navigation bar using CSS involves several steps. First, you need to define the HTML structure of your navigation bar. Then, you use CSS to style it. You can use media queries to make the navigation bar responsive. Media queries allow you to apply different styles depending on the screen size of the device.

What are the key differences between a responsive and a non-responsive navigation bar?

A responsive navigation bar adjusts its layout, size, and appearance based on the screen size and resolution of the device it’s viewed on. This ensures optimal usability and user experience on all devices. On the other hand, a non-responsive navigation bar maintains the same layout and appearance regardless of the device, which can lead to usability issues on smaller screens.

How can I ensure equal width of navigation items using CSS?

To ensure equal width of navigation items, you can use the CSS property ‘flex’. By setting the value of ‘flex’ to ‘1’, you ensure that all navigation items take up an equal amount of space within the navigation bar, regardless of their content.

How can I add hover effects to my navigation bar using CSS?

You can add hover effects to your navigation bar using the CSS ‘:hover’ pseudo-class. This pseudo-class allows you to define a different style for an element when the mouse pointer is over it. You can change the color, background color, border, and other properties of the navigation items on hover.

How can I make my navigation bar sticky using CSS?

To make your navigation bar sticky, you can use the CSS property ‘position’ with the value ‘fixed’. This will make the navigation bar stay in the same place even when the user scrolls down the page.

How can I add a dropdown menu to my navigation bar using CSS?

To add a dropdown menu to your navigation bar, you need to nest another ‘ul’ element within a ‘li’ element of your navigation bar. Then, you can use CSS to style the dropdown menu and add interactivity using the ‘:hover’ pseudo-class.

How can I add transitions to my navigation bar using CSS?

You can add transitions to your navigation bar using the CSS ‘transition’ property. This property allows you to specify the speed at which a CSS property changes from one value to another. You can use it to create smooth hover effects, dropdown animations, and more.

How can I add icons to my navigation bar using CSS?

To add icons to your navigation bar, you can use icon libraries such as Font Awesome. You simply need to include the library in your HTML file and then you can use the icons as classes in your ‘i’ elements.

How can I make my navigation bar accessible for screen readers?

To make your navigation bar accessible for screen readers, you can use ARIA roles and properties. For example, you can use the ‘role’ attribute with the value ‘navigation’ to indicate that the element is a navigation bar. You can also use the ‘aria-label’ attribute to provide a descriptive name for the navigation bar.